You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
266 lines
6.5 KiB
266 lines
6.5 KiB
package dao |
|
|
|
import ( |
|
"context" |
|
"fmt" |
|
"strconv" |
|
|
|
"go-common/app/admin/main/reply/model" |
|
"go-common/library/cache/memcache" |
|
"go-common/library/log" |
|
) |
|
|
|
const ( |
|
_prefixSub = "s_" // sub_oid<<8|type |
|
_prefixReply = "r_" // r_rpID |
|
_prefixAdminTop = "at_" // at_rpID |
|
_prefixUpperTop = "ut_" // ut_rpID |
|
_prefixConfig = "c_%d_%d_%d" // oid_type_category |
|
|
|
_oidOverflow = 1 << 48 |
|
) |
|
|
|
func keyReply(rpID int64) string { |
|
return _prefixReply + strconv.FormatInt(rpID, 10) |
|
} |
|
|
|
func keySubject(oid int64, typ int32) string { |
|
if oid > _oidOverflow { |
|
return fmt.Sprintf("%s_%d_%d", _prefixSub, oid, typ) |
|
} |
|
return _prefixSub + strconv.FormatInt((oid<<8)|int64(typ), 10) |
|
} |
|
|
|
func keyConfig(oid int64, typ, category int32) string { |
|
return fmt.Sprintf(_prefixConfig, oid, typ, category) |
|
} |
|
|
|
func keyAdminTop(oid int64, attr uint32) string { |
|
if oid > _oidOverflow { |
|
return fmt.Sprintf("%s_%d_%d", _prefixAdminTop, oid, attr) |
|
} |
|
return _prefixAdminTop + strconv.FormatInt((oid<<8)|int64(attr), 10) |
|
} |
|
|
|
func keyUpperTop(oid int64, attr uint32) string { |
|
if oid > _oidOverflow { |
|
return fmt.Sprintf("%s_%d_%d", _prefixUpperTop, oid, attr) |
|
} |
|
return _prefixUpperTop + strconv.FormatInt((oid<<8)|int64(attr), 10) |
|
} |
|
|
|
// PingMC check connection success. |
|
func (d *Dao) pingMC(c context.Context) (err error) { |
|
conn := d.mc.Get(c) |
|
item := memcache.Item{Key: "ping", Value: []byte{1}, Expiration: d.mcExpire} |
|
err = conn.Set(&item) |
|
conn.Close() |
|
return |
|
} |
|
|
|
// SubjectCache get subject from memcache. |
|
func (d *Dao) SubjectCache(c context.Context, oid int64, typ int32) (sub *model.Subject, err error) { |
|
key := keySubject(oid, typ) |
|
conn := d.mc.Get(c) |
|
defer conn.Close() |
|
item, err := conn.Get(key) |
|
if err != nil { |
|
if err == memcache.ErrNotFound { |
|
err = nil |
|
} |
|
return |
|
} |
|
sub = new(model.Subject) |
|
if err = conn.Scan(item, sub); err != nil { |
|
log.Error("conn.Scan(%s) error(%v)", item.Value, err) |
|
sub = nil |
|
} |
|
return |
|
} |
|
|
|
// AddSubjectCache add subject into memcache. |
|
func (d *Dao) AddSubjectCache(c context.Context, subs ...*model.Subject) (err error) { |
|
conn := d.mc.Get(c) |
|
for _, sub := range subs { |
|
key := keySubject(sub.Oid, sub.Type) |
|
item := &memcache.Item{Key: key, Object: sub, Expiration: d.mcExpire, Flags: memcache.FlagJSON} |
|
if err = conn.Set(item); err != nil { |
|
log.Error("conn.Set(%s,%v) error(%v)", key, sub, err) |
|
} |
|
} |
|
conn.Close() |
|
return |
|
} |
|
|
|
// DelSubjectCache delete subject from memcache. |
|
func (d *Dao) DelSubjectCache(c context.Context, oid int64, typ int32) (err error) { |
|
key := keySubject(oid, typ) |
|
conn := d.mc.Get(c) |
|
if err = conn.Delete(key); err != nil { |
|
if err == memcache.ErrNotFound { |
|
err = nil |
|
} |
|
} |
|
conn.Close() |
|
return |
|
} |
|
|
|
// ReplyCache get a reply from memcache. |
|
func (d *Dao) ReplyCache(c context.Context, rpID int64) (rp *model.Reply, err error) { |
|
key := keyReply(rpID) |
|
conn := d.mc.Get(c) |
|
defer conn.Close() |
|
item, err := conn.Get(key) |
|
if err != nil { |
|
if err == memcache.ErrNotFound { |
|
err = nil |
|
} |
|
return |
|
} |
|
rp = new(model.Reply) |
|
if err = conn.Scan(item, rp); err != nil { |
|
rp = nil |
|
} |
|
return |
|
} |
|
|
|
// RepliesCache multi get replies from memcache. |
|
func (d *Dao) RepliesCache(c context.Context, rpIDs []int64) (rpMap map[int64]*model.Reply, missed []int64, err error) { |
|
rpMap = make(map[int64]*model.Reply, len(rpIDs)) |
|
keys := make([]string, len(rpIDs)) |
|
mm := make(map[string]int64, len(rpIDs)) |
|
for i, rpID := range rpIDs { |
|
key := keyReply(rpID) |
|
keys[i] = key |
|
mm[key] = rpID |
|
} |
|
conn := d.mc.Get(c) |
|
defer conn.Close() |
|
items, err := conn.GetMulti(keys) |
|
if err != nil { |
|
if err == memcache.ErrNotFound { |
|
err = nil |
|
} |
|
return |
|
} |
|
for _, item := range items { |
|
rp := new(model.Reply) |
|
if err = conn.Scan(item, rp); err != nil { |
|
log.Error("conn.Scan(%s) error(%v)", item.Value, err) |
|
continue |
|
} |
|
rpMap[mm[item.Key]] = rp |
|
delete(mm, item.Key) |
|
} |
|
missed = make([]int64, 0, len(mm)) |
|
for _, valIn := range mm { |
|
missed = append(missed, valIn) |
|
} |
|
return |
|
} |
|
|
|
// AddReplyCache add reply into memcache. |
|
func (d *Dao) AddReplyCache(c context.Context, rps ...*model.Reply) (err error) { |
|
conn := d.mc.Get(c) |
|
defer conn.Close() |
|
for _, rp := range rps { |
|
item := &memcache.Item{ |
|
Key: keyReply(rp.ID), |
|
Object: rp, |
|
Expiration: d.mcExpire, |
|
Flags: memcache.FlagJSON, |
|
} |
|
if err = conn.Set(item); err != nil { |
|
return |
|
} |
|
} |
|
return |
|
} |
|
|
|
// DelReplyCache delete reply from memcache. |
|
func (d *Dao) DelReplyCache(c context.Context, rpID int64) (err error) { |
|
conn := d.mc.Get(c) |
|
if err = conn.Delete(keyReply(rpID)); err != nil { |
|
if err == memcache.ErrNotFound { |
|
err = nil |
|
} |
|
} |
|
conn.Close() |
|
return |
|
} |
|
|
|
// DelConfigCache delete reply config from memcache. |
|
func (d *Dao) DelConfigCache(c context.Context, oid int64, typ, category int32) (err error) { |
|
key := keyConfig(oid, typ, category) |
|
conn := d.mc.Get(c) |
|
if err = conn.Delete(key); err != nil { |
|
if err == memcache.ErrNotFound { |
|
err = nil |
|
} |
|
} |
|
conn.Close() |
|
return |
|
} |
|
|
|
// TopCache get a reply from memcache. |
|
func (d *Dao) TopCache(c context.Context, oid int64, attr uint32) (rp *model.Reply, err error) { |
|
var key string |
|
if attr == model.SubAttrTopAdmin { |
|
key = keyAdminTop(oid, attr) |
|
} else if attr == model.SubAttrTopUpper { |
|
key = keyUpperTop(oid, attr) |
|
} |
|
conn := d.mc.Get(c) |
|
defer conn.Close() |
|
item, err := conn.Get(key) |
|
if err != nil { |
|
if err == memcache.ErrNotFound { |
|
err = nil |
|
} |
|
return |
|
} |
|
rp = new(model.Reply) |
|
if err = conn.Scan(item, rp); err != nil { |
|
rp = nil |
|
} |
|
return |
|
} |
|
|
|
// DelTopCache delete topreply from memcache. |
|
func (d *Dao) DelTopCache(c context.Context, oid int64, attr uint32) (err error) { |
|
var key string |
|
if attr == model.SubAttrTopAdmin { |
|
key = keyAdminTop(oid, attr) |
|
} else if attr == model.SubAttrTopUpper { |
|
key = keyUpperTop(oid, attr) |
|
} |
|
conn := d.mc.Get(c) |
|
if err = conn.Delete(key); err != nil { |
|
if err == memcache.ErrNotFound { |
|
err = nil |
|
} else { |
|
log.Error("conn.Delete(%s) error(%v)", key, err) |
|
} |
|
} |
|
conn.Close() |
|
return |
|
} |
|
|
|
// AddTopCache add top reply into memcache. |
|
func (d *Dao) AddTopCache(c context.Context, rp *model.Reply) (err error) { |
|
var key string |
|
if rp.AttrVal(model.AttrTopAdmin) == model.AttrYes { |
|
key = keyAdminTop(rp.Oid, model.AttrTopAdmin) |
|
} else if rp.AttrVal(model.AttrTopUpper) == model.AttrYes { |
|
key = keyUpperTop(rp.Oid, model.AttrTopUpper) |
|
} else { |
|
return |
|
} |
|
conn := d.mc.Get(c) |
|
defer conn.Close() |
|
item := &memcache.Item{Key: key, Object: rp, Expiration: d.mcExpire, Flags: memcache.FlagJSON} |
|
if err = conn.Set(item); err != nil { |
|
log.Error("conn.Set(%s,%v) error(%v)", key, rp, err) |
|
} |
|
return |
|
}
|
|
|