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.
206 lines
5.0 KiB
206 lines
5.0 KiB
package bplus |
|
|
|
import ( |
|
"context" |
|
"strconv" |
|
|
|
"go-common/app/interface/main/app-interface/model" |
|
"go-common/app/interface/main/app-interface/model/space" |
|
"go-common/library/cache/redis" |
|
"go-common/library/log" |
|
xtime "go-common/library/time" |
|
|
|
"github.com/pkg/errors" |
|
) |
|
|
|
const ( |
|
_prefixContributeAttr = "cba_" |
|
_prefixContribute = "cb_" |
|
) |
|
|
|
func keyContributeAttr(vmid int64) string { |
|
return _prefixContributeAttr + strconv.FormatInt(vmid, 10) |
|
} |
|
|
|
func keyContribute(vmid int64) string { |
|
return _prefixContribute + strconv.FormatInt(vmid, 10) |
|
} |
|
|
|
// AddContributeCache . |
|
func (d *Dao) AddContributeCache(c context.Context, vmid int64, attrs *space.Attrs, items []*space.Item) (err error) { |
|
var attr int32 |
|
conn := d.redis.Get(c) |
|
key := keyContribute(vmid) |
|
defer conn.Close() |
|
for _, item := range items { |
|
score := item.CTime.Time().Unix() |
|
item.FormatKey() |
|
if err = conn.Send("ZADD", key, score, item.Member); err != nil { |
|
err = errors.Wrapf(err, "conn.Send(ZADD,%s,%d,%d)", key, score, item.Member) |
|
return |
|
} |
|
} |
|
keyAttr := keyContributeAttr(vmid) |
|
if attrs != nil { |
|
if attrs.Archive { |
|
attr = model.AttrSet(attr, model.AttrYes, model.AttrBitArchive) |
|
} |
|
if attrs.Article { |
|
attr = model.AttrSet(attr, model.AttrYes, model.AttrBitArticle) |
|
} |
|
if attrs.Clip { |
|
attr = model.AttrSet(attr, model.AttrYes, model.AttrBitClip) |
|
} |
|
if attrs.Album { |
|
attr = model.AttrSet(attr, model.AttrYes, model.AttrBitAlbum) |
|
} |
|
if attrs.Audio { |
|
attr = model.AttrSet(attr, model.AttrYes, model.AttrBitAudio) |
|
} |
|
} |
|
if err = conn.Send("SET", keyAttr, attr); err != nil { |
|
err = errors.Wrapf(err, "conn.Send(SET,%s,%d)", keyAttr, attr) |
|
return |
|
} |
|
if err = conn.Flush(); err != nil { |
|
return |
|
} |
|
for i := 0; i < len(items)+1; i++ { |
|
if _, err = conn.Receive(); err != nil { |
|
return |
|
} |
|
} |
|
return |
|
} |
|
|
|
// RangeContributeCache . |
|
func (d *Dao) RangeContributeCache(c context.Context, vmid int64, pn, ps int) (items []*space.Item, err error) { |
|
conn := d.redis.Get(c) |
|
key := keyContribute(vmid) |
|
start := (pn - 1) * ps |
|
stop := pn*ps - 1 |
|
defer conn.Close() |
|
var vs []interface{} |
|
if vs, err = redis.Values(conn.Do("ZREVRANGE", key, start, stop, "WITHSCORES")); err != nil { |
|
err = errors.Wrapf(err, "conn.Do(ZREVRANGE,%s,%d,%d)", key, start, stop) |
|
return |
|
} else if len(vs) == 0 { |
|
return |
|
} |
|
items = make([]*space.Item, 0, ps) |
|
for len(vs) > 0 { |
|
var ( |
|
member int64 |
|
score int64 |
|
) |
|
if vs, err = redis.Scan(vs, &member, &score); err != nil { |
|
log.Error("redis.Scan(%v) error(%v)", vs, err) |
|
err = nil |
|
continue |
|
} |
|
if member != 0 && score != 0 { |
|
item := &space.Item{Member: member, CTime: xtime.Time(score)} |
|
item.ParseKey() |
|
if item.Goto != "" { |
|
items = append(items, item) |
|
} |
|
} |
|
} |
|
return |
|
} |
|
|
|
func (d *Dao) RangeContributionCache(c context.Context, vmid int64, cursor *model.Cursor) (items []*space.Item, err error) { |
|
conn := d.redis.Get(c) |
|
key := keyContribute(vmid) |
|
defer conn.Close() |
|
var ( |
|
vs []interface{} |
|
rank int64 |
|
start, stop int64 |
|
) |
|
if cursor.MoveUpward() || cursor.MoveDownward() { |
|
if rank, err = redis.Int64(conn.Do("ZREVRANK", key, cursor.Current)); err != nil { |
|
if err == redis.ErrNil { |
|
err = nil |
|
return |
|
} |
|
err = errors.Wrapf(err, "conn.Do(ZREVRANK,%s,%d)", key, cursor.Current) |
|
return |
|
} |
|
} |
|
if cursor.Latest() { |
|
start = 0 |
|
stop = rank + int64(cursor.Size) - 1 |
|
} else if cursor.MoveUpward() { |
|
if rank == 0 { |
|
return |
|
} |
|
if start = rank - int64(cursor.Size); start < 0 { |
|
start = 0 |
|
} |
|
stop = rank - 1 |
|
} else if cursor.MoveDownward() { |
|
start = rank + 1 |
|
stop = rank + int64(cursor.Size) |
|
} |
|
if vs, err = redis.Values(conn.Do("ZREVRANGE", key, start, stop, "WITHSCORES")); err != nil { |
|
err = errors.Wrapf(err, "conn.Do(ZREVRANGE,%s,%d,%d)", key, start, stop) |
|
return |
|
} |
|
if len(vs) == 0 { |
|
return |
|
} |
|
items = make([]*space.Item, 0, len(vs)) |
|
for len(vs) > 0 { |
|
var ( |
|
member int64 |
|
score int64 |
|
) |
|
if vs, err = redis.Scan(vs, &member, &score); err != nil { |
|
log.Error("redis.Scan(%v) error(%v)", vs, err) |
|
err = nil |
|
continue |
|
} |
|
if member != 0 && score != 0 { |
|
item := &space.Item{Member: member, CTime: xtime.Time(score)} |
|
item.ParseKey() |
|
if item.Goto != "" { |
|
items = append(items, item) |
|
} |
|
} |
|
} |
|
return |
|
} |
|
|
|
// AttrCache . |
|
func (d *Dao) AttrCache(c context.Context, vmid int64) (attrs *space.Attrs, err error) { |
|
var attr int64 |
|
conn := d.redis.Get(c) |
|
key := keyContributeAttr(vmid) |
|
if attr, err = redis.Int64(conn.Do("GET", key)); err != nil { |
|
if err == redis.ErrNil { |
|
err = nil |
|
return |
|
} |
|
err = errors.Wrapf(err, "conn.Do(GET,%s)", key) |
|
return |
|
} |
|
conn.Close() |
|
attrs = &space.Attrs{} |
|
if model.AttrVal(int32(attr), model.AttrBitArchive) == model.AttrYes { |
|
attrs.Archive = true |
|
} |
|
if model.AttrVal(int32(attr), model.AttrBitArticle) == model.AttrYes { |
|
attrs.Article = true |
|
} |
|
if model.AttrVal(int32(attr), model.AttrBitClip) == model.AttrYes { |
|
attrs.Clip = true |
|
} |
|
if model.AttrVal(int32(attr), model.AttrBitAlbum) == model.AttrYes { |
|
attrs.Album = true |
|
} |
|
if model.AttrVal(int32(attr), model.AttrBitAudio) == model.AttrYes { |
|
attrs.Audio = true |
|
} |
|
return |
|
}
|
|
|