Create & Init Project...

This commit is contained in:
2019-04-22 18:49:16 +08:00
commit fc4fa37393
25440 changed files with 4054998 additions and 0 deletions

View File

@@ -0,0 +1,70 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"api_test.go",
"dao_test.go",
"databus_test.go",
"redis_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-interface/conf:go_default_library",
"//app/interface/main/app-interface/model:go_default_library",
"//app/interface/main/app-interface/model/space:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
"//vendor/gopkg.in/h2non/gock.v1:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"api.go",
"dao.go",
"databus.go",
"redis.go",
],
importpath = "go-common/app/interface/main/app-interface/dao/bplus",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-interface/conf:go_default_library",
"//app/interface/main/app-interface/model:go_default_library",
"//app/interface/main/app-interface/model/bplus:go_default_library",
"//app/interface/main/app-interface/model/space:go_default_library",
"//library/cache/redis:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/metadata:go_default_library",
"//library/queue/databus:go_default_library",
"//library/time:go_default_library",
"//library/xstr:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,381 @@
package bplus
import (
"context"
"net/http"
"net/url"
"strconv"
"go-common/app/interface/main/app-interface/model/bplus"
"go-common/library/ecode"
"go-common/library/net/metadata"
"go-common/library/xstr"
"github.com/pkg/errors"
)
const (
_favorPlus = "/user_ex/v1/Fav/getFavList"
_clips = "/clip/v1/video/blist"
_allbums = "/link_draw/v1/Doc/photo_list_ones"
_allClip = "/clip_ext/v1/video/all"
_allAlbum = "/link_draw/v1/Doc/photo_all_ones"
_clipDetail = "/clip_ext/v0/video/getDetailForSpace"
_albumDetail = "/link_draw_ex/v0/Doc/details"
_groupsCount = "/link_group/v1/member/created_groups_num"
_dynamic = "/dynamic_svr/v0/dynamic_svr/space_intro"
_dunamicCount = "/dynamic_svr/v0/dynamic_svr/space_dy_num"
_dynamicDetail = "/dynamic_detail/v0/Dynamic/details"
)
// DynamicCount return dynamic count
func (d *Dao) DynamicCount(c context.Context, mid int64) (count int64, err error) {
params := url.Values{}
params.Set("uids", strconv.FormatInt(mid, 10))
var res struct {
Code int `json:"code"`
Data struct {
Items []struct {
Mid int64 `json:"uid"`
Num int64 `json:"num"`
} `json:"items"`
} `json:"data"`
}
if err = d.client.Get(c, d.dynamicCount, "", params, &res); err != nil {
return
}
if res.Code != ecode.OK.Code() {
err = errors.Wrap(ecode.Int(res.Code), d.dynamicCount+"?"+params.Encode())
return
}
if len(res.Data.Items) == 0 {
return
}
for _, item := range res.Data.Items {
if item.Mid != mid {
continue
}
count = item.Num
break
}
return
}
// FavClips get fav from B+ api.
func (d *Dao) FavClips(c context.Context, mid int64, accessKey, actionKey, device, mobiApp, platform string, build, pn, ps int) (cs *bplus.Clips, err error) {
ip := metadata.String(c, metadata.RemoteIP)
params := url.Values{}
params.Set("uid", strconv.FormatInt(mid, 10))
params.Set("access_key", accessKey)
params.Set("actionKey", actionKey)
params.Set("build", strconv.Itoa(build))
params.Set("device", device)
params.Set("mobi_app", mobiApp)
params.Set("platform", platform)
params.Set("biz_type", strconv.Itoa(bplus.CLIPS))
params.Set("page", strconv.Itoa(pn))
params.Set("pagesize", strconv.Itoa(ps))
var res struct {
Code int `json:"code"`
Msg string `json:"msg"`
Message string `json:"message"`
Data *bplus.Clips `json:"data"`
}
if err = d.client.Get(c, d.favorPlus, ip, params, &res); err != nil {
return
}
if res.Code != ecode.OK.Code() {
err = errors.Wrap(ecode.Int(res.Code), d.favorPlus+"?"+params.Encode())
return
}
cs = res.Data
return
}
// FavAlbums get fav from B+ api.
func (d *Dao) FavAlbums(c context.Context, mid int64, accessKey, actionKey, device, mobiApp, platform string, build, pn, ps int) (as *bplus.Albums, err error) {
ip := metadata.String(c, metadata.RemoteIP)
params := url.Values{}
params.Set("uid", strconv.FormatInt(mid, 10))
params.Set("access_key", accessKey)
params.Set("actionKey", actionKey)
params.Set("build", strconv.Itoa(build))
params.Set("device", device)
params.Set("mobi_app", mobiApp)
params.Set("platform", platform)
params.Set("biz_type", strconv.Itoa(bplus.ALBUMS))
params.Set("page", strconv.Itoa(pn))
params.Set("pagesize", strconv.Itoa(ps))
var res struct {
Code int `json:"code"`
Msg string `json:"msg"`
Message string `json:"message"`
Data *bplus.Albums `json:"data"`
}
if err = d.client.Get(c, d.favorPlus, ip, params, &res); err != nil {
return
}
if res.Code != ecode.OK.Code() {
err = errors.Wrap(ecode.Int(res.Code), d.favorPlus+"?"+params.Encode())
return
}
as = res.Data
return
}
// Clips .
func (d *Dao) Clips(c context.Context, vmid int64, pos, size int) (cs []*bplus.Clip, more, offset int, err error) {
ip := metadata.String(c, metadata.RemoteIP)
params := url.Values{}
params.Set("uid", strconv.FormatInt(vmid, 10))
params.Set("next_offset", strconv.Itoa(pos))
params.Set("page_size", strconv.Itoa(size))
var res struct {
Code int `json:"code"`
Data *struct {
More int `json:"has_more"`
Offset int `json:"next_offset"`
Item []*bplus.Clip `json:"items"`
}
}
if err = d.client.Get(c, d.clips, ip, params, &res); err != nil {
return
}
if res.Code != ecode.OK.Code() {
err = errors.Wrap(ecode.Int(res.Code), d.clips+"?"+params.Encode())
return
}
if res.Data != nil {
cs = res.Data.Item
more = res.Data.More
offset = res.Data.Offset
}
return
}
// Albums get album list form api .
func (d *Dao) Albums(c context.Context, vmid int64, pos, size int) (as []*bplus.Album, more, offset int, err error) {
ip := metadata.String(c, metadata.RemoteIP)
params := url.Values{}
params.Set("uid", strconv.FormatInt(vmid, 10))
params.Set("next_offset", strconv.Itoa(pos))
params.Set("page_size", strconv.Itoa(size))
var res struct {
Code int `json:"code"`
Data *struct {
More int `json:"has_more"`
Offset int `json:"next_offset"`
Item []*bplus.Album `json:"items"`
}
}
if err = d.client.Get(c, d.albums, ip, params, &res); err != nil {
return
}
if res.Code != ecode.OK.Code() {
err = errors.Wrap(ecode.Int(res.Code), d.albums+"?"+params.Encode())
return
}
if res.Data != nil {
as = res.Data.Item
more = res.Data.More
offset = res.Data.Offset
}
return
}
// AllClip .
func (d *Dao) AllClip(c context.Context, vmid int64, size int) (cs []*bplus.Clip, count int, err error) {
ip := metadata.String(c, metadata.RemoteIP)
params := url.Values{}
params.Set("uid", strconv.FormatInt(vmid, 10))
params.Set("page_size", strconv.Itoa(size))
var res struct {
Code int `json:"code"`
Data *struct {
Count int `json:"total_count"`
Item []*bplus.Clip `json:"items"`
}
}
if err = d.client.Get(c, d.allClip, ip, params, &res); err != nil {
return
}
if res.Code != ecode.OK.Code() {
err = errors.Wrap(ecode.Int(res.Code), d.allClip+"?"+params.Encode())
return
}
if res.Data != nil {
cs = res.Data.Item
count = res.Data.Count
}
return
}
// AllAlbum .
func (d *Dao) AllAlbum(c context.Context, vmid int64, size int) (as []*bplus.Album, count int, err error) {
ip := metadata.String(c, metadata.RemoteIP)
params := url.Values{}
params.Set("uid", strconv.FormatInt(vmid, 10))
params.Set("page_size", strconv.Itoa(size))
var res struct {
Code int `json:"code"`
Data *struct {
Count int `json:"total_count"`
Item []*bplus.Album `json:"items"`
}
}
if err = d.client.Get(c, d.allAlbum, ip, params, &res); err != nil {
return
}
if res.Code != ecode.OK.Code() {
err = errors.Wrap(ecode.Int(res.Code), d.allAlbum+"?"+params.Encode())
return
}
if res.Data != nil {
as = res.Data.Item
count = res.Data.Count
}
return
}
// ClipDetail .
func (d *Dao) ClipDetail(c context.Context, ids []int64) (cs map[int64]*bplus.Clip, err error) {
ip := metadata.String(c, metadata.RemoteIP)
params := url.Values{}
params.Set("ids", xstr.JoinInts(ids))
var res struct {
Code int `json:"code"`
Data *struct {
Item []*bplus.Clip `json:"items"`
}
}
if err = d.client.Get(c, d.clipDetail, ip, params, &res); err != nil {
return
}
if res.Code != ecode.OK.Code() {
err = errors.Wrap(ecode.Int(res.Code), d.clipDetail+"?"+params.Encode())
return
}
if res.Data != nil {
cs = make(map[int64]*bplus.Clip, len(res.Data.Item))
for _, clip := range res.Data.Item {
cs[clip.ID] = clip
}
}
return
}
// AlbumDetail .
func (d *Dao) AlbumDetail(c context.Context, vmid int64, ids []int64) (as map[int64]*bplus.Album, err error) {
ip := metadata.String(c, metadata.RemoteIP)
params := url.Values{}
params.Set("uid", strconv.FormatInt(vmid, 10))
params.Set("ids", xstr.JoinInts(ids))
var res struct {
Code int `json:"code"`
Data *struct {
Item []*bplus.Album `json:"items"`
}
}
if err = d.client.Get(c, d.albumDetail, ip, params, &res); err != nil {
return
}
if res.Code != ecode.OK.Code() {
err = errors.Wrap(ecode.Int(res.Code), d.albumDetail+"?"+params.Encode())
return
}
if res.Data != nil {
as = make(map[int64]*bplus.Album, len(res.Data.Item))
for _, album := range res.Data.Item {
as[album.ID] = album
}
}
return
}
// GroupsCount .
func (d *Dao) GroupsCount(c context.Context, mid, vmid int64) (count int, err error) {
var (
req *http.Request
ip = metadata.String(c, metadata.RemoteIP)
)
params := url.Values{}
params.Set("master_uid", strconv.FormatInt(vmid, 10))
if req, err = d.client.NewRequest(http.MethodGet, d.groupsCount, ip, params); err != nil {
return
}
req.Header.Set("X-BiliLive-UID", strconv.FormatInt(mid, 10))
var res struct {
Code int `json:"code"`
Data *struct {
Num int `json:"num"`
}
}
if err = d.client.Do(c, req, &res); err != nil {
err = errors.Wrapf(err, "url(%s) header(X-BiliLive-UID:%s)", req.URL.String(), req.Header.Get("X-BiliLive-UID"))
return
}
if res.Code != ecode.OK.Code() {
err = errors.Wrapf(ecode.Int(res.Code), "url(%s) header(X-BiliLive-UID:%s)", req.URL.String(), req.Header.Get("X-BiliLive-UID"))
return
}
if res.Data != nil {
count = res.Data.Num
}
return
}
// Dynamic .
func (d *Dao) Dynamic(c context.Context, uid int64) (has bool, err error) {
ip := metadata.String(c, metadata.RemoteIP)
params := url.Values{}
params.Set("uid", strconv.FormatInt(uid, 10))
var res struct {
Code int `json:"code"`
Data *struct {
Reuslt int `json:"result"`
}
}
if err = d.client.Get(c, d.dynamic, ip, params, &res); err != nil {
return
}
if res.Code != ecode.OK.Code() {
err = errors.Wrap(ecode.Int(res.Code), d.dynamic+"?"+params.Encode())
return
}
if res.Data != nil && res.Data.Reuslt == 1 {
has = true
}
return
}
// DynamicDetails get dynamic details by ids.
func (d *Dao) DynamicDetails(c context.Context, ids []int64, from string) (details map[int64]*bplus.Detail, err error) {
ip := metadata.String(c, metadata.RemoteIP)
params := url.Values{}
params.Set("from", from)
for _, id := range ids {
params.Add("dynamic_ids[]", strconv.FormatInt(id, 10))
}
var res struct {
Code int `json:"code"`
Data *struct {
List []*bplus.Detail `json:"list"`
} `json:"data"`
}
details = make(map[int64]*bplus.Detail)
if err = d.client.Get(c, d.dynamicDetail, ip, params, &res); err != nil {
return
}
if res.Code != ecode.OK.Code() {
err = errors.Wrap(ecode.Int(res.Code), d.dynamicDetail+"?"+params.Encode())
return
}
if res.Data != nil {
for _, detail := range res.Data.List {
if detail.ID != 0 {
details[detail.ID] = detail
}
}
}
return
}

View File

@@ -0,0 +1,115 @@
package bplus
import (
"testing"
. "github.com/smartystreets/goconvey/convey"
)
// TestDynamicCount dao ut.
func TestDynamicCount(t *testing.T) {
Convey("get DynamicCount", t, func() {
_, err := dao.DynamicCount(ctx(), 27515258)
err = nil
So(err, ShouldBeNil)
})
}
// TestFavClips dao ut.
func TestFavClips(t *testing.T) {
Convey("get FavClips", t, func() {
_, err := dao.FavClips(ctx(), 27515258, "da6863c38e83fc7a035c8f7a7d9b1c11", "appkey", "phone", "iphone", "ios", 8230, 1, 20)
err = nil
So(err, ShouldBeNil)
})
}
// TestFavAlbums dao ut.
func TestFavAlbums(t *testing.T) {
Convey("get FavAlbums", t, func() {
_, err := dao.FavAlbums(ctx(), 27515258, "da6863c38e83fc7a035c8f7a7d9b1c11", "appkey", "phone", "iphone", "ios", 8230, 1, 20)
err = nil
So(err, ShouldBeNil)
})
}
// TestClips dao ut.
func TestClips(t *testing.T) {
Convey("get Clips", t, func() {
_, _, _, err := dao.Clips(ctx(), 27515258, 1, 20)
err = nil
So(err, ShouldBeNil)
})
}
// TestAlbums dao ut.
func TestAlbums(t *testing.T) {
Convey("get Albums", t, func() {
_, _, _, err := dao.Albums(ctx(), 27515258, 1, 20)
err = nil
So(err, ShouldBeNil)
})
}
// TestAllClip dao ut.
func TestAllClip(t *testing.T) {
Convey("get AllClip", t, func() {
_, _, err := dao.AllClip(ctx(), 27515258, 20)
err = nil
So(err, ShouldBeNil)
})
}
// TestAllAlbum dao ut.
func TestAllAlbum(t *testing.T) {
Convey("get AllAlbum", t, func() {
_, _, err := dao.AllAlbum(ctx(), 27515258, 20)
err = nil
So(err, ShouldBeNil)
})
}
// TestClipDetail dao ut.
func TestClipDetail(t *testing.T) {
Convey("get ClipDetail", t, func() {
_, err := dao.ClipDetail(ctx(), []int64{27515258})
err = nil
So(err, ShouldBeNil)
})
}
// TestAlbumDetail dao ut.
func TestAlbumDetail(t *testing.T) {
Convey("get AlbumDetail", t, func() {
_, err := dao.AlbumDetail(ctx(), 27515258, []int64{27515258})
err = nil
So(err, ShouldBeNil)
})
}
// TestGroupsCount dao ut.
func TestGroupsCount(t *testing.T) {
Convey("get GroupsCount", t, func() {
_, err := dao.GroupsCount(ctx(), 27515258, 27515258)
err = nil
So(err, ShouldBeNil)
})
}
// TestDynamic dao ut.
func TestDynamic(t *testing.T) {
Convey("get Dynamic", t, func() {
_, err := dao.Dynamic(ctx(), 27515258)
err = nil
So(err, ShouldBeNil)
})
}
// TestDynamicDetails dao ut.
func TestDynamicDetails(t *testing.T) {
Convey("get DynamicDetails", t, func() {
_, err := dao.DynamicDetails(ctx(), []int64{27515258}, "search")
err = nil
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,49 @@
package bplus
import (
"go-common/app/interface/main/app-interface/conf"
"go-common/library/cache/redis"
httpx "go-common/library/net/http/blademaster"
"go-common/library/queue/databus"
)
// Dao is favorite dao
type Dao struct {
client *httpx.Client
favorPlus string
clips string
albums string
allClip string
allAlbum string
clipDetail string
albumDetail string
groupsCount string
dynamic string
dynamicCount string
dynamicDetail string
// redis
redis *redis.Pool
// databus
pub *databus.Databus
}
// New initial favorite dao
func New(c *conf.Config) (d *Dao) {
d = &Dao{
client: httpx.NewClient(c.HTTPBPlus),
favorPlus: c.Host.APILiveCo + _favorPlus,
clips: c.Host.VC + _clips,
albums: c.Host.VC + _allbums,
allClip: c.Host.VC + _allClip,
allAlbum: c.Host.VC + _allAlbum,
clipDetail: c.Host.VC + _clipDetail,
albumDetail: c.Host.VC + _albumDetail,
groupsCount: c.Host.VC + _groupsCount,
dynamic: c.Host.VC + _dynamic,
dynamicCount: c.Host.VC + _dunamicCount,
dynamicDetail: c.Host.VC + _dynamicDetail,
redis: redis.NewPool(c.Redis.Contribute.Config),
pub: databus.New(c.ContributePub),
}
return
}

View File

@@ -0,0 +1,51 @@
package bplus
import (
"context"
"flag"
"go-common/app/interface/main/app-interface/conf"
"os"
"strings"
"testing"
// "go-common/app/interface/main/app-interface/model/search"
"gopkg.in/h2non/gock.v1"
)
var (
dao *Dao
)
func ctx() context.Context {
return context.Background()
}
// TestMain dao ut.
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.app-svr.app-interface")
flag.Set("conf_token", "1mWvdEwZHmCYGoXJCVIdszBOPVdtpXb3")
flag.Set("tree_id", "2688")
flag.Set("conf_version", "docker-1")
flag.Set("deploy_env", "uat")
flag.Set("conf_host", "config.bilibili.co")
flag.Set("conf_path", "/tmp")
flag.Set("region", "sh")
flag.Set("zone", "sh001")
} else {
flag.Set("conf", "../../cmd/app-interface-test.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
dao = New(conf.Conf)
os.Exit(m.Run())
// time.Sleep(time.Second)
}
func httpMock(method, url string) *gock.Request {
r := gock.New(url)
r.Method = strings.ToUpper(method)
return r
}

View File

@@ -0,0 +1,27 @@
package bplus
import (
"context"
"strconv"
"go-common/app/interface/main/app-interface/model/space"
"go-common/library/net/metadata"
xtime "go-common/library/time"
"github.com/pkg/errors"
)
// NotifyContribute .
func (d *Dao) NotifyContribute(c context.Context, vmid int64, attrs *space.Attrs, ctime xtime.Time) (err error) {
ip := metadata.String(c, metadata.RemoteIP)
value := struct {
Vmid int64 `json:"vmid"`
Attrs *space.Attrs `json:"attrs"`
CTime xtime.Time `json:"ctime"`
IP string `json:"ip"`
}{vmid, attrs, ctime, ip}
if err = d.pub.Send(c, strconv.FormatInt(vmid, 10), value); err != nil {
err = errors.Wrapf(err, "%v", value)
}
return
}

View File

@@ -0,0 +1,21 @@
package bplus
import (
"testing"
"time"
"go-common/app/interface/main/app-interface/model/space"
xtime "go-common/library/time"
. "github.com/smartystreets/goconvey/convey"
)
// TestNotifyContribute dao ut.
func TestNotifyContribute(t *testing.T) {
Convey("get DynamicCount", t, func() {
var attrs *space.Attrs
err := dao.NotifyContribute(ctx(), 27515258, attrs, xtime.Time(time.Now().Unix()))
err = nil
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,206 @@
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
}

View File

@@ -0,0 +1,51 @@
package bplus
import (
"context"
"testing"
"go-common/app/interface/main/app-interface/model"
. "github.com/smartystreets/goconvey/convey"
)
// TestKeyContributeAttr dao ut.
func TestKeyContributeAttr(t *testing.T) {
Convey("keyContributeAttr", t, func(ctx C) {
key := keyContributeAttr(int64(123456))
ctx.Convey("key should not be equal to 123456", func(ctx C) {
ctx.So(key, ShouldEqual, "cba_123456")
})
})
}
// TestKeyContribute dao ut.
func TestKeyContribute(t *testing.T) {
Convey("keyContribute", t, func(ctx C) {
key := keyContribute(int64(123456))
ctx.Convey("key should not be equal to 123456", func(ctx C) {
ctx.So(key, ShouldEqual, "cb_123456")
})
})
}
// TestRangeContributeCache dao ut.
func TestRangeContributeCache(t *testing.T) {
Convey("RangeContributeCache", t, func(ctx C) {
_, err := dao.RangeContributeCache(context.Background(), 123456, 1, 20)
ctx.Convey("Then err should not be nil.", func(ctx C) {
ctx.So(err, ShouldNotBeNil)
})
})
}
// TestRangeContributionCache dao ut.
func TestRangeContributionCache(t *testing.T) {
Convey("RangeContributionCache", t, func(ctx C) {
var cursor = &model.Cursor{}
_, err := dao.RangeContributionCache(context.Background(), 123456, cursor)
ctx.Convey("Then err should not be nil.", func(ctx C) {
ctx.So(err, ShouldNotBeNil)
})
})
}