123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- 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
- }
|