2019-04-22 02:59:20 +00:00

287 lines
6.9 KiB
Go

package pendant
import (
"context"
"strconv"
"encoding/json"
"go-common/app/service/main/usersuit/model"
"go-common/library/cache/redis"
"go-common/library/log"
"github.com/pkg/errors"
)
const (
_pendantPKG = "pkg_" // key of
_pendantEquip = "pe_"
)
func keyEquip(mid int64) string {
return _pendantEquip + strconv.FormatInt(mid, 10)
}
// encode
func (d *Dao) encode(mid, pid, expires, tp int64, status, isVIP int32, pendant *model.Pendant) (res []byte, err error) {
ft := &model.PendantPackage{Mid: mid, Pid: pid, Expires: expires, Type: tp, Status: status, IsVIP: isVIP, Pendant: pendant}
return json.Marshal(ft)
}
// decode
func (d *Dao) decode(src []byte, v *model.PendantPackage) (err error) {
return json.Unmarshal(src, v)
}
// AddPKGCache set package cache.
func (d *Dao) AddPKGCache(c context.Context, mid int64, info []*model.PendantPackage) (err error) {
var (
key = _pendantPKG + strconv.FormatInt(mid, 10)
args = redis.Args{}.Add(key)
)
for i := 0; i < len(info); i++ {
var ef []byte
if ef, err = d.encode(info[i].Mid, info[i].Pid, info[i].Expires, info[i].Type, info[i].Status, info[i].IsVIP, info[i].Pendant); err != nil {
return
}
args = args.Add(i, ef)
}
conn := d.redis.Get(c)
defer conn.Close()
if err = conn.Send("DEL", key); err != nil {
log.Error("conn.Send(DEL, %s) error(%v)", key, err)
return
}
if err = conn.Send("HMSET", args...); err != nil {
log.Error("conn.Send(HMSET, %s) error(%v)", key, err)
return
}
if err = conn.Send("EXPIRE", key, d.pendantExpire); err != nil {
log.Error("conn.Send(EXPIRE, %s) error(%v)", key, err)
return
}
if err = conn.Flush(); err != nil {
log.Error("conn.Flush() error(%v)", err)
return
}
for i := 0; i < 3; i++ {
if _, err = conn.Receive(); err != nil {
log.Error("conn.Receive() %d error(%v)", i+1, err)
break
}
}
return
}
// PKGCache get package cache.
func (d *Dao) PKGCache(c context.Context, mid int64) (info []*model.PendantPackage, err error) {
var (
key = _pendantPKG + strconv.FormatInt(mid, 10)
tmp = make(map[string]string, len(info))
)
conn := d.redis.Get(c)
defer conn.Close()
if tmp, err = redis.StringMap(conn.Do("HGETALL", key)); err != nil {
return
}
if err == nil && len(tmp) > 0 {
for i := 0; i < len(tmp); i++ {
s := strconv.FormatInt(int64(i), 10)
vf := &model.PendantPackage{}
vf.Pendant = &model.Pendant{}
if err = d.decode([]byte(tmp[s]), vf); err != nil {
return
}
info = append(info, &model.PendantPackage{
Mid: vf.Mid,
Pid: vf.Pid,
Expires: vf.Expires,
Type: vf.Type,
Status: vf.Status,
IsVIP: vf.IsVIP,
Pendant: vf.Pendant,
})
}
}
return
}
// DelPKGCache del package cache
func (d *Dao) DelPKGCache(c context.Context, mid int64) (err error) {
key := _pendantPKG + strconv.FormatInt(mid, 10)
conn := d.redis.Get(c)
defer conn.Close()
if err = conn.Send("DEL", key); err != nil {
log.Error("conn.Send(DEL, %s) error(%v)", key, err)
return
}
return
}
// equipCache return pendant info cache
func (d *Dao) equipCache(c context.Context, mid int64) (info *model.PendantEquip, err error) {
var (
item []byte
conn = d.redis.Get(c)
)
defer conn.Close()
if item, err = redis.Bytes(conn.Do("GET", keyEquip(mid))); err != nil {
if err == redis.ErrNil {
err = nil
}
return
}
if err = json.Unmarshal(item, &info); err != nil {
log.Error("json.Unmarshal(%v) err(%v)", item, err)
}
return
}
// equipsCache obtain equips from redis .
func (d *Dao) equipsCache(c context.Context, mids []int64) (map[int64]*model.PendantEquip, []int64, error) {
var (
err error
bss [][]byte
key string
args = redis.Args{}
conn = d.redis.Get(c)
)
for _, v := range mids {
key = keyEquip(v)
args = args.Add(key)
}
defer conn.Close()
if bss, err = redis.ByteSlices(conn.Do("MGET", args...)); err != nil {
if err == redis.ErrNil {
return nil, nil, nil
}
log.Error("Failed mget equip: keys: %+v: %+v", args, err)
return nil, nil, err
}
info := make(map[int64]*model.PendantEquip, len(mids))
for _, bs := range bss {
if bs == nil {
continue
}
pe := &model.PendantEquip{}
if err = json.Unmarshal(bs, pe); err != nil {
log.Error("json.Unmarshal(%s) error(%v)", string(bs), err)
err = nil
continue
}
info[pe.Mid] = pe
}
missed := make([]int64, 0, len(mids))
for _, mid := range mids {
if _, ok := info[mid]; !ok {
missed = append(missed, mid)
}
}
return info, missed, nil
}
// AddEquipCache set pendant info cache
func (d *Dao) AddEquipCache(c context.Context, mid int64, info *model.PendantEquip) (err error) {
var (
key = keyEquip(mid)
values []byte
conn = d.redis.Get(c)
)
defer conn.Close()
if values, err = json.Marshal(info); err != nil {
return
}
if err = conn.Send("SET", keyEquip(mid), values); err != nil {
log.Error("conn.Send(SET, %s, %d) error(%v)", key, values, err)
return
}
if err = conn.Send("EXPIRE", key, d.pendantExpire); err != nil {
log.Error("conn.Send(Expire, %s, %d) error(%v)", key, d.pendantExpire, err)
return
}
if err = conn.Flush(); err != nil {
err = errors.Wrap(err, "conn.Send Flush")
return
}
for i := 0; i < 2; i++ {
if _, err = conn.Receive(); err != nil {
err = errors.Wrap(err, "conn.Send conn.Receive()")
return
}
}
return
}
// AddEquipsCache mset equips info to caache .
func (d *Dao) AddEquipsCache(c context.Context, equips map[int64]*model.PendantEquip) (err error) {
var (
bs []byte
key string
keys []string
argsMid = redis.Args{}
conn = d.redis.Get(c)
)
defer conn.Close()
for _, v := range equips {
if bs, err = json.Marshal(v); err != nil {
log.Error("json.Marshal err(%v)", err)
continue
}
key = keyEquip(v.Mid)
keys = append(keys, key)
argsMid = argsMid.Add(key).Add(string(bs))
}
if err = conn.Send("MSET", argsMid...); err != nil {
err = errors.Wrap(err, "conn.Send(MSET) error")
return
}
count := 1
for _, v := range keys {
count++
if err = conn.Send("EXPIRE", v, d.pendantExpire); err != nil {
err = errors.Wrap(err, "conn.Send error")
return
}
}
if err = conn.Flush(); err != nil {
err = errors.Wrap(err, "conn.Send Flush")
return
}
for i := 0; i < count; i++ {
if _, err = conn.Receive(); err != nil {
err = errors.Wrap(err, "conn.Send conn.Receive()")
return
}
}
return
}
// DelEquipCache set pendant info cache
func (d *Dao) DelEquipCache(c context.Context, mid int64) (err error) {
key := keyEquip(mid)
conn := d.redis.Get(c)
defer conn.Close()
if _, err = conn.Do("DEL", key); err != nil {
log.Error("conn.Do(DEL, %s) error(%v)", key, err)
}
return
}
// DelEquipsCache del batch equip cache .
func (d *Dao) DelEquipsCache(c context.Context, mids []int64) (err error) {
var (
args = redis.Args{}
conn = d.redis.Get(c)
)
defer conn.Close()
for _, v := range mids {
args = args.Add(keyEquip(v))
}
if _, err = conn.Do("DEL", args...); err != nil {
log.Error("conn.Do(DEL, %s) error(%v)", args, err)
}
return
}