123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558 |
- package fav
- import (
- "context"
- "encoding/json"
- "fmt"
- "go-common/app/job/main/favorite/model"
- favmdl "go-common/app/service/main/favorite/model"
- "go-common/library/cache/redis"
- "go-common/library/log"
- )
- const (
- // _fid list fid => ([]model.Cover)
- _covers = "fcs_"
- _folderKey = "fi_%d_%d" // sortedset f_type_mid value:fid,score:ctime
- _oldRelationKey = "r_%d_%d_%d"
- _allRelationKey = "ar_%d_%d"
- _relationKey = "r_%d_%d" // sortedset r_mid_fid(mtime, oid)
- _relationOidsKey = "ro_%d_%d" // set ro_type_mid value:oids
- _cleanedKey = "rc_%d_%d" // hash key:rc_type_mid field:fid value:timestamp
- // key fb_mid/100000 offset => mid%100000
- // bit value 1 mean unfaved; bit value 0 mean faved
- _favedBit = "fb_%d_%d"
- _bucket = 100000
- )
- func favedBitKey(tp int8, mid int64) string {
- return fmt.Sprintf(_favedBit, tp, mid/_bucket)
- }
- // folderKey return a user folder key.
- func folderKey(tp int8, mid int64) string {
- return fmt.Sprintf(_folderKey, tp, mid)
- }
- // relationKey return folder relation key.
- func relationKey(mid, fid int64) string {
- return fmt.Sprintf(_relationKey, mid, fid)
- }
- // allRelationKey return folder relation key.
- func allRelationKey(mid, fid int64) string {
- return fmt.Sprintf(_allRelationKey, mid, fid)
- }
- // oldRelationKey return folder relation key.
- func oldRelationKey(typ int8, mid, fid int64) string {
- return fmt.Sprintf(_oldRelationKey, typ, mid, fid)
- }
- // relationOidsKey return a user oids key.
- func relationOidsKey(tp int8, mid int64) string {
- return fmt.Sprintf(_relationOidsKey, tp, mid)
- }
- // cleanKey return user whether cleaned key.
- func cleanedKey(tp int8, mid int64) string {
- return fmt.Sprintf(_cleanedKey, tp, mid)
- }
- // redisKey make key for redis by prefix and mid
- func coversKey(mid, fid int64) string {
- return fmt.Sprintf("%s%d_%d", _covers, mid, fid)
- }
- // PingRedis ping connection success.
- func (d *Dao) pingRedis(c context.Context) (err error) {
- conn := d.redis.Get(c)
- _, err = conn.Do("SET", "PING", "PONG")
- conn.Close()
- return
- }
- // DelNewCoverCache delete cover picture cache.
- func (d *Dao) DelNewCoverCache(c context.Context, mid, fid int64) (err error) {
- var (
- key = coversKey(mid, fid)
- conn = d.redis.Get(c)
- )
- defer conn.Close()
- if _, err = conn.Do("DEL", key); err != nil {
- log.Error("DEL %v failed error(%v)", key, err)
- }
- return
- }
- // SetUnFavedBit set unfaved user bit to 1
- func (d *Dao) SetUnFavedBit(c context.Context, tp int8, mid int64) (err error) {
- key := favedBitKey(tp, mid)
- offset := mid % _bucket
- conn := d.redis.Get(c)
- defer conn.Close()
- if _, err = conn.Do("SETBIT", key, offset, 1); err != nil {
- log.Error("conn.DO(SETBIT) key(%s) offset(%d) err(%v)", key, offset, err)
- }
- return
- }
- // SetFavedBit set unfaved user bit to 0
- func (d *Dao) SetFavedBit(c context.Context, tp int8, mid int64) (err error) {
- key := favedBitKey(tp, mid)
- offset := mid % _bucket
- conn := d.redis.Get(c)
- defer conn.Close()
- if _, err = conn.Do("SETBIT", key, offset, 0); err != nil {
- log.Error("conn.DO(SETBIT) key(%s) offset(%d) err(%v)", key, offset, err)
- }
- return
- }
- // ExpireAllRelations expire folder relations cache.
- func (d *Dao) ExpireAllRelations(c context.Context, mid, fid int64) (ok bool, err error) {
- key := allRelationKey(mid, fid)
- conn := d.redis.Get(c)
- if ok, err = redis.Bool(conn.Do("EXPIRE", key, d.redisExpire)); err != nil {
- log.Error("conn.Do(EXPIRE %s) error(%v)", key, err)
- }
- conn.Close()
- return
- }
- // ExpireRelations expire folder relations cache.
- func (d *Dao) ExpireRelations(c context.Context, mid, fid int64) (ok bool, err error) {
- key := relationKey(mid, fid)
- conn := d.redis.Get(c)
- if ok, err = redis.Bool(conn.Do("EXPIRE", key, d.redisExpire)); err != nil {
- log.Error("conn.Do(EXPIRE %s) error(%v)", key, err)
- }
- conn.Close()
- return
- }
- // FolderCache return a favorite folder from redis.
- func (d *Dao) FolderCache(c context.Context, tp int8, mid, fid int64) (folder *favmdl.Folder, err error) {
- var (
- value []byte
- key = folderKey(tp, mid)
- conn = d.redis.Get(c)
- )
- defer conn.Close()
- if value, err = redis.Bytes(conn.Do("HGET", key, fid)); err != nil {
- if err == redis.ErrNil {
- err = nil
- folder = nil
- } else {
- log.Error("conn.Do(HGET, %v, %v) error(%v)", key, fid, err)
- }
- return
- }
- folder = &favmdl.Folder{}
- if err = json.Unmarshal(value, folder); err != nil {
- log.Error("json.Unmarshal(%s) error(%v)", value, err)
- }
- return
- }
- // DefaultFolderCache return default favorite folder from redis.
- func (d *Dao) DefaultFolderCache(c context.Context, tp int8, mid int64) (folder *favmdl.Folder, err error) {
- var res map[int64]*favmdl.Folder
- if res, err = d.foldersCache(c, tp, mid); err != nil {
- return
- }
- if res == nil {
- return
- }
- for _, folder = range res {
- if folder.IsDefault() {
- return
- }
- }
- folder = nil
- return
- }
- // foldersCache return the user all folders from redis.
- func (d *Dao) foldersCache(c context.Context, tp int8, mid int64) (res map[int64]*favmdl.Folder, err error) {
- var (
- values map[string]string
- key = folderKey(tp, mid)
- conn = d.redis.Get(c)
- )
- defer conn.Close()
- if values, err = redis.StringMap(conn.Do("HGETALL", key)); err != nil {
- if err == redis.ErrNil {
- return nil, nil
- }
- log.Error("conn.Do(HGETALL %s) error(%v)", key, err)
- return
- }
- res = make(map[int64]*favmdl.Folder, len(res))
- for _, data := range values {
- folder := &favmdl.Folder{}
- if err = json.Unmarshal([]byte(data), folder); err != nil {
- log.Error("json.Unmarshal(%s) error(%v)", data, err)
- return
- }
- res[folder.ID] = folder
- }
- return
- }
- // RelationCntCache return the folder all relation count from redis.
- func (d *Dao) RelationCntCache(c context.Context, mid, fid int64) (cnt int, err error) {
- key := relationKey(mid, fid)
- conn := d.redis.Get(c)
- defer conn.Close()
- if cnt, err = redis.Int(conn.Do("ZCARD", key)); err != nil {
- if err == redis.ErrNil {
- return model.CacheNotFound, nil
- }
- log.Error("conn.Do(ZCARD %s) error(%v)", key, err)
- }
- return
- }
- // MaxScore get the max score from sorted set
- func (d *Dao) MaxScore(c context.Context, m *favmdl.Favorite) (score int64, err error) {
- key := allRelationKey(m.Mid, m.Fid)
- conn := d.redis.Get(c)
- defer conn.Close()
- values, err := redis.Values(conn.Do("ZREVRANGE", key, 0, 0, "WITHSCORES"))
- if err != nil {
- log.Error("conn.Do(ZREVRANGE, %s) error(%v)", key, err)
- return
- }
- if len(values) != 2 {
- err = fmt.Errorf("redis zrange items(%v) length not 2", values)
- return
- }
- var id int64
- redis.Scan(values, &id, &score)
- return
- }
- // AddAllRelationCache add a relation to redis.
- func (d *Dao) AddAllRelationCache(c context.Context, m *favmdl.Favorite) (err error) {
- key := allRelationKey(m.Mid, m.Fid)
- score, err := d.MaxScore(c, m)
- if err != nil {
- return
- }
- if score <= 0 {
- log.Error("dao.AddAllRelationCache invalid score(%d)!%+v", d, *m)
- return
- }
- seq := int64(score/1e10) + 1
- conn := d.redis.Get(c)
- defer conn.Close()
- if err = conn.Send("ZADD", key, seq*1e10+int64(m.MTime), m.Oid*100+int64(m.Type)); err != nil {
- log.Error("conn.Send(ZADD %s,%d) error(%v)", key, m.Oid, err)
- return
- }
- if err = conn.Send("EXPIRE", key, d.redisExpire); err != nil {
- log.Error("conn.Send(EXPIRE) error(%v)", err)
- return
- }
- if err = conn.Flush(); err != nil {
- log.Error("conn.Flush() error(%v)", err)
- return
- }
- for i := 0; i < 2; i++ {
- if _, err = conn.Receive(); err != nil {
- log.Error("conn.Receive() error(%v)", err)
- return
- }
- }
- return
- }
- // AddRelationCache add a relation to redis.
- func (d *Dao) AddRelationCache(c context.Context, m *favmdl.Favorite) (err error) {
- key := relationKey(m.Mid, m.Fid)
- conn := d.redis.Get(c)
- defer conn.Close()
- if err = conn.Send("ZADD", key, m.MTime, m.Oid); err != nil {
- log.Error("conn.Send(ZADD %s,%d) error(%v)", key, m.Oid, err)
- return
- }
- if err = conn.Send("EXPIRE", key, d.redisExpire); err != nil {
- log.Error("conn.Send(EXPIRE) error(%v)", err)
- return
- }
- if err = conn.Flush(); err != nil {
- log.Error("conn.Flush() error(%v)", err)
- return
- }
- for i := 0; i < 2; i++ {
- if _, err = conn.Receive(); err != nil {
- log.Error("conn.Receive() error(%v)", err)
- return
- }
- }
- return
- }
- // AddAllRelationsCache add a relation to redis.
- func (d *Dao) AddAllRelationsCache(c context.Context, mid, fid int64, fs []*favmdl.Favorite) (err error) {
- key := allRelationKey(mid, fid)
- conn := d.redis.Get(c)
- defer conn.Close()
- for _, fav := range fs {
- if err = conn.Send("ZADD", key, fav.Sequence*1e10+uint64(fav.MTime), fav.Oid*100+int64(fav.Type)); err != nil {
- log.Error("conn.Send(ZADD %s,%d) error(%v)", key, fav.Oid, err)
- return
- }
- }
- if err = conn.Send("EXPIRE", key, d.redisExpire); err != nil {
- log.Error("conn.Send(EXPIRE) error(%v)", err)
- return
- }
- if err = conn.Flush(); err != nil {
- log.Error("conn.Flush() error(%v)", err)
- return
- }
- for i := 0; i < len(fs)+1; i++ {
- if _, err = conn.Receive(); err != nil {
- log.Error("conn.Receive() error(%v)", err)
- return
- }
- }
- return
- }
- // AddRelationsCache add a relation to redis.
- func (d *Dao) AddRelationsCache(c context.Context, tp int8, mid, fid int64, fs []*favmdl.Favorite) (err error) {
- key := relationKey(mid, fid)
- conn := d.redis.Get(c)
- defer conn.Close()
- for _, fav := range fs {
- if err = conn.Send("ZADD", key, fav.MTime, fav.Oid); err != nil {
- log.Error("conn.Send(ZADD %s,%d) error(%v)", key, fav.Oid, err)
- return
- }
- }
- if err = conn.Send("EXPIRE", key, d.redisExpire); err != nil {
- log.Error("conn.Send(EXPIRE) error(%v)", err)
- return
- }
- if err = conn.Flush(); err != nil {
- log.Error("conn.Flush() error(%v)", err)
- return
- }
- for i := 0; i < len(fs)+1; i++ {
- if _, err = conn.Receive(); err != nil {
- log.Error("conn.Receive() error(%v)", err)
- return
- }
- }
- return
- }
- // DelRelationsCache delete the folder relation cache.
- func (d *Dao) DelRelationsCache(c context.Context, mid, fid int64) (err error) {
- key := relationKey(mid, fid)
- 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
- }
- // DelAllRelationsCache delete the folder relation cache.
- func (d *Dao) DelAllRelationsCache(c context.Context, mid, fid int64) (err error) {
- key := allRelationKey(mid, fid)
- 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
- }
- // DelRelationCache delete one relation cache.
- func (d *Dao) DelRelationCache(c context.Context, mid, fid, oid int64) (err error) {
- key := relationKey(mid, fid)
- conn := d.redis.Get(c)
- defer conn.Close()
- if err = conn.Send("ZREM", key, oid); err != nil {
- log.Error("conn.Send error(%v)", err)
- return
- }
- if err = conn.Send("EXPIRE", key, d.redisExpire); err != nil {
- log.Error("conn.Send error(%v)", err)
- return
- }
- if err = conn.Flush(); err != nil {
- log.Error("conn.Flush error(%v)", err)
- return
- }
- for i := 0; i < 2; i++ {
- if _, err = conn.Receive(); err != nil {
- log.Error("conn.Receive() error(%v)", err)
- return
- }
- }
- return
- }
- // DelAllRelationCache delete one relation cache.
- func (d *Dao) DelAllRelationCache(c context.Context, mid, fid, oid int64, typ int8) (err error) {
- key := allRelationKey(mid, fid)
- conn := d.redis.Get(c)
- defer conn.Close()
- if err = conn.Send("ZREM", key, oid*100+int64(typ)); err != nil {
- log.Error("conn.Send error(%v)", err)
- return
- }
- if err = conn.Send("EXPIRE", key, d.redisExpire); err != nil {
- log.Error("conn.Send error(%v)", err)
- return
- }
- if err = conn.Flush(); err != nil {
- log.Error("conn.Flush error(%v)", err)
- return
- }
- for i := 0; i < 2; i++ {
- if _, err = conn.Receive(); err != nil {
- log.Error("conn.Receive() error(%v)", err)
- return
- }
- }
- return
- }
- // DelOldRelationsCache delete the folder relation cache. TODO:del at 2018.06.08
- func (d *Dao) DelOldRelationsCache(c context.Context, typ int8, mid, fid int64) (err error) {
- key := oldRelationKey(typ, mid, fid)
- 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
- }
- // ExpireRelationOids set expire for faved oids.
- func (d *Dao) ExpireRelationOids(c context.Context, tp int8, mid int64) (ok bool, err error) {
- key := relationOidsKey(tp, mid)
- var conn = d.redis.Get(c)
- defer conn.Close()
- if ok, err = redis.Bool(conn.Do("EXPIRE", key, d.redisExpire)); err != nil {
- log.Error("conn.Do(EXPIRE, %s) error(%v)", key, err)
- }
- return
- }
- // AddRelationOidCache add favoured oid.
- func (d *Dao) AddRelationOidCache(c context.Context, tp int8, mid, oid int64) (err error) {
- var (
- key = relationOidsKey(tp, mid)
- conn = d.redis.Get(c)
- )
- defer conn.Close()
- if err = conn.Send("SADD", key, oid); err != nil {
- log.Error("conn.Send error(%v)", err)
- return
- }
- if err = conn.Send("EXPIRE", key, d.redisExpire); err != nil {
- log.Error("conn.Send error(%v)", err)
- return
- }
- if err = conn.Flush(); err != nil {
- log.Error("conn.Flush error(%v)", err)
- return
- }
- for i := 0; i < 2; i++ {
- if _, err = conn.Receive(); err != nil {
- log.Error("conn.Receive() error(%v)", err)
- return
- }
- }
- return
- }
- // RemRelationOidCache del favoured oid.
- func (d *Dao) RemRelationOidCache(c context.Context, tp int8, mid, oid int64) (err error) {
- var (
- key = relationOidsKey(tp, mid)
- conn = d.redis.Get(c)
- )
- defer conn.Close()
- if _, err = conn.Do("SREM", key, oid); err != nil {
- log.Error("conn.Do(%s,%d) error(%v)", key, oid, err)
- }
- return
- }
- // SetRelationOidsCache set favoured oids .
- func (d *Dao) SetRelationOidsCache(c context.Context, tp int8, mid int64, oids []int64) (err error) {
- var (
- key = relationOidsKey(tp, mid)
- conn = d.redis.Get(c)
- )
- defer conn.Close()
- for _, oid := range oids {
- if err = conn.Send("SADD", key, oid); err != nil {
- log.Error("conn.Send error(%v)", err)
- return
- }
- }
- if err = conn.Send("EXPIRE", key, d.redisExpire); err != nil {
- log.Error("conn.Send error(%v)", err)
- return
- }
- if err = conn.Flush(); err != nil {
- log.Error("conn.Flush error(%v)", err)
- return
- }
- for i := 0; i < len(oids)+1; i++ {
- if _, err = conn.Receive(); err != nil {
- log.Error("conn.Receive() error(%v)", err)
- return
- }
- }
- return
- }
- // SetCleanedCache .
- func (d *Dao) SetCleanedCache(c context.Context, typ int8, mid, fid, ftime, expire int64) (err error) {
- var (
- key = cleanedKey(typ, mid)
- conn = d.redis.Get(c)
- )
- defer conn.Close()
- if err = conn.Send("HSET", key, fid, ftime); err != nil {
- log.Error("conn.Send error(%v)", err)
- return
- }
- if err = conn.Send("EXPIRE", key, expire); err != nil {
- log.Error("conn.Send error(%v)", err)
- return
- }
- if err = conn.Flush(); err != nil {
- log.Error("conn.Flush error(%v)", err)
- return
- }
- for i := 0; i < 2; i++ {
- if _, err = conn.Receive(); err != nil {
- log.Error("conn.Receive() error(%v)", err)
- return
- }
- }
- return
- }
- // DelRelationOidsCache .
- func (d *Dao) DelRelationOidsCache(c context.Context, typ int8, mid int64) (err error) {
- key := relationOidsKey(typ, 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
- }
|