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,81 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"audit.go",
"dao.go",
"localcache.go",
"memcache.go",
"mysql.go",
"prompt_redis.go",
"recent_redis.go",
"redis.go",
"relation_log.go",
],
importpath = "go-common/app/service/main/relation/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/relation/conf:go_default_library",
"//app/service/main/relation/model:go_default_library",
"//app/service/main/relation/model/i64b:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/cache/redis:go_default_library",
"//library/database/sql:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/queue/databus/report:go_default_library",
"//library/stat/prom:go_default_library",
"//library/time:go_default_library",
"//library/xstr:go_default_library",
"//vendor/github.com/bluele/gcache: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"],
)
go_test(
name = "go_default_test",
srcs = [
"audit_test.go",
"dao_test.go",
"localcache_test.go",
"memcache_test.go",
"mysql_test.go",
"prompt_redis_test.go",
"recent_redis_test.go",
"redis_test.go",
"relation_log_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/relation/conf:go_default_library",
"//app/service/main/relation/model:go_default_library",
"//app/service/main/relation/model/i64b:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,39 @@
package dao
import (
"context"
"net/url"
"strconv"
"go-common/app/service/main/relation/model"
"go-common/library/ecode"
"github.com/pkg/errors"
)
// PassportDetail get passport detail from passport service through http
func (d *Dao) PassportDetail(c context.Context, mid int64, ip string) (res *model.PassportDetail, err error) {
params := url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
var resp struct {
Code int `json:"code"`
Data *model.PassportDetail `json:"data"`
}
req, err := d.client.NewRequest("GET", d.detailURI, ip, params)
if err != nil {
err = errors.Wrap(err, "dao passport detail")
return
}
req.Header.Set("X-BACKEND-BILI-REAL-IP", ip)
if err = d.client.Do(c, req, &resp); err != nil {
err = errors.Wrap(err, "dao passport detail")
return
}
if resp.Code != 0 {
err = ecode.Int(resp.Code)
err = errors.Wrap(err, "dao passport detail")
return
}
res = resp.Data
return
}

View File

@@ -0,0 +1,23 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoPassportDetail(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
ip = ""
)
convey.Convey("PassportDetail", t, func(cv convey.C) {
res, err := d.PassportDetail(c, mid, ip)
cv.Convey("Then err should be nil.res should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(res, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,94 @@
package dao
import (
"context"
"time"
"github.com/bluele/gcache"
"go-common/app/service/main/relation/conf"
"go-common/library/cache/memcache"
"go-common/library/cache/redis"
"go-common/library/database/sql"
bm "go-common/library/net/http/blademaster"
)
const (
_passportDetailURL = "/intranet/acc/detail"
)
// Dao struct info of Dao.
type Dao struct {
// mysql
db *sql.DB
// memcache
mc *memcache.Pool
followerExpire int32
mcExpire int32
// redis
redis *redis.Pool
redisExpire int32
// conf
c *conf.Config
// prompt
period int64
bcount int64
ucount int64
// followers unread duration
UnreadDuration int64
// apis
detailURI string
// client
client *bm.Client
// statCache
statStore gcache.Cache
}
// New new a Dao and return.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
// conf
c: c,
// db
db: sql.NewMySQL(c.Mysql),
// memcache
mc: memcache.NewPool(c.Memcache.Config),
mcExpire: int32(time.Duration(c.Memcache.Expire) / time.Second),
followerExpire: int32(time.Duration(c.Memcache.FollowerExpire) / time.Second),
// redis
redis: redis.NewPool(c.Redis.Config),
redisExpire: int32(time.Duration(c.Redis.Expire) / time.Second),
// prompt
period: int64(time.Duration(c.Relation.Period) / time.Second),
bcount: c.Relation.Bcount,
ucount: c.Relation.Ucount,
// followers unread
UnreadDuration: int64(time.Duration(c.Relation.FollowersUnread) / time.Second),
// passport api
detailURI: c.Host.Passport + _passportDetailURL,
client: bm.NewClient(c.HTTPClient),
statStore: gcache.New(c.StatCache.Size).LFU().Build(),
}
return
}
// Ping ping health.
func (d *Dao) Ping(c context.Context) (err error) {
if err = d.pingMC(c); err != nil {
return
}
return d.pingRedis(c)
}
// Close close connections of mc, redis, db.
func (d *Dao) Close() {
if d.mc != nil {
d.mc.Close()
}
if d.redis != nil {
d.redis.Close()
}
if d.db != nil {
d.db.Close()
}
}

View File

@@ -0,0 +1,33 @@
package dao
import (
"flag"
"go-common/app/service/main/relation/conf"
"os"
"testing"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.account.relation-service")
flag.Set("conf_token", "8hm3I5rWzuhChxrBI6VTqmCs7TpJwFhO")
flag.Set("tree_id", "2139")
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")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
m.Run()
os.Exit(0)
}

View File

@@ -0,0 +1,86 @@
package dao
import (
"context"
"time"
"go-common/app/service/main/relation/model"
"go-common/library/log"
"go-common/library/stat/prom"
"github.com/bluele/gcache"
"github.com/pkg/errors"
)
func (d *Dao) loadStat(ctx context.Context, mid int64) (*model.Stat, error) {
stat, err := d.statCache(ctx, mid)
if err != nil {
return nil, err
}
d.storeStat(mid, stat)
return stat, nil
}
func (d *Dao) storeStat(mid int64, stat *model.Stat) {
if stat == nil || stat.Follower < int64(d.c.StatCache.LeastFollower) {
return
}
d.statStore.SetWithExpire(mid, stat, time.Duration(d.c.StatCache.Expire))
}
func (d *Dao) localStat(mid int64) (*model.Stat, error) {
prom.CacheHit.Incr("local_stat_cache")
item, err := d.statStore.Get(mid)
if err != nil {
prom.CacheMiss.Incr("local_stat_cache")
return nil, err
}
stat, ok := item.(*model.Stat)
if !ok {
prom.CacheMiss.Incr("local_stat_cache")
return nil, errors.New("Not a stat")
}
return stat, nil
}
// StatCache get stat cache.
func (d *Dao) StatCache(c context.Context, mid int64) (*model.Stat, error) {
stat, err := d.localStat(mid)
if err != nil {
if err != gcache.KeyNotFoundError {
log.Error("Failed to get stat from local: mid: %d: %+v", mid, err)
}
return d.loadStat(c, mid)
}
return stat, nil
}
// StatsCache get multi stat cache.
func (d *Dao) StatsCache(c context.Context, mids []int64) (map[int64]*model.Stat, []int64, error) {
stats := make(map[int64]*model.Stat, len(mids))
lcMissed := make([]int64, 0, len(mids))
for _, mid := range mids {
stat, err := d.localStat(mid)
if err != nil {
if err != gcache.KeyNotFoundError {
log.Error("Failed to get stat from local: mid: %d: %+v", mid, err)
}
lcMissed = append(lcMissed, mid)
continue
}
stats[stat.Mid] = stat
}
if len(lcMissed) == 0 {
return stats, nil, nil
}
mcStats, mcMissed, err := d.statsCache(c, lcMissed)
if err != nil {
return nil, nil, err
}
for _, stat := range mcStats {
d.storeStat(stat.Mid, stat)
stats[stat.Mid] = stat
}
return stats, mcMissed, nil
}

View File

@@ -0,0 +1,43 @@
package dao
import (
"context"
"go-common/app/service/main/relation/model"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoloadStat(t *testing.T) {
var (
ctx = context.Background()
mid = int64(1)
stat = &model.Stat{
Mid: 1,
Follower: 1,
Following: 1,
Black: 1,
Whisper: 1,
}
)
d.SetStatCache(ctx, mid, stat)
d.storeStat(mid, stat)
convey.Convey("loadStat", t, func(cv convey.C) {
d.storeStat(mid, stat)
cv.Convey("No return values", func(cv convey.C) {
})
s1, err := d.loadStat(ctx, mid)
cv.Convey("loadStat", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(s1, convey.ShouldNotBeNil)
})
p1, p2, err := d.StatsCache(ctx, []int64{1})
cv.Convey("StatsCache", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(p2, convey.ShouldNotBeNil)
cv.So(p1, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,405 @@
package dao
import (
"context"
"fmt"
"strconv"
"go-common/app/service/main/relation/model"
gmc "go-common/library/cache/memcache"
"go-common/library/log"
)
const (
_prefixFollowing = "pb_a_" // key of following
_prefixFollower = "pb_f_" // key of follower
_prefixTagCount = "rs_tmtc_%d" // key of relation tag by mid & tag's count
_prefixTags = "tags_" // user tag info.
_prefixGlobalHotRec = "gh_rec" // global hot rec
_prefixStat = "c_" // key of stat
_prefixFollowerNotify = "f_notify_"
_emptyExpire = 20 * 24 * 3600
_recExpire = 5 * 24 * 3600
)
func statKey(mid int64) string {
return _prefixStat + strconv.FormatInt(mid, 10)
}
func tagsKey(mid int64) string {
return _prefixTags + strconv.FormatInt(mid, 10)
}
func followingKey(mid int64) string {
return _prefixFollowing + strconv.FormatInt(mid, 10)
}
func followerKey(mid int64) string {
return _prefixFollower + strconv.FormatInt(mid, 10)
}
func tagCountKey(mid int64) string {
return fmt.Sprintf(_prefixTagCount, mid)
}
func globalHotKey() string {
return _prefixGlobalHotRec
}
func followerNotifySetting(mid int64) string {
return _prefixFollowerNotify + strconv.FormatInt(mid, 10)
}
// pingMC ping memcache.
func (d *Dao) pingMC(c context.Context) (err error) {
conn := d.mc.Get(c)
if err = conn.Set(&gmc.Item{Key: "ping", Value: []byte{1}, Expiration: d.mcExpire}); err != nil {
log.Error("conn.Store(set, ping, 1) error(%v)", err)
}
conn.Close()
return
}
// SetFollowingCache set following cache.
func (d *Dao) SetFollowingCache(c context.Context, mid int64, followings []*model.Following) (err error) {
return d.setFollowingCache(c, followingKey(mid), followings)
}
// FollowingCache get following cache.
func (d *Dao) FollowingCache(c context.Context, mid int64) (followings []*model.Following, err error) {
return d.followingCache(c, followingKey(mid))
}
// DelFollowingCache delete following cache.
func (d *Dao) DelFollowingCache(c context.Context, mid int64) (err error) {
return d.delFollowingCache(c, followingKey(mid))
}
// SetFollowerCache set follower cache.
func (d *Dao) SetFollowerCache(c context.Context, mid int64, followers []*model.Following) (err error) {
return d.setFollowingCache(c, followerKey(mid), followers)
}
// FollowerCache get follower cache.
func (d *Dao) FollowerCache(c context.Context, mid int64) (followers []*model.Following, err error) {
return d.followingCache(c, followerKey(mid))
}
// DelFollowerCache delete follower cache.
func (d *Dao) DelFollowerCache(c context.Context, mid int64) (err error) {
return d.delFollowingCache(c, followerKey(mid))
}
// setFollowingCache set following cache.
func (d *Dao) setFollowingCache(c context.Context, key string, followings []*model.Following) (err error) {
expire := d.followerExpire
if len(followings) == 0 {
expire = _emptyExpire
}
item := &gmc.Item{Key: key, Object: &model.FollowingList{FollowingList: followings}, Expiration: expire, Flags: gmc.FlagProtobuf}
conn := d.mc.Get(c)
if err = conn.Set(item); err != nil {
log.Error("setFollowingCache err(%v)", err)
}
conn.Close()
return
}
// followingCache get following cache.
func (d *Dao) followingCache(c context.Context, key string) (followings []*model.Following, err error) {
conn := d.mc.Get(c)
defer conn.Close()
item, err := conn.Get(key)
if err != nil {
if err == gmc.ErrNotFound {
err = nil
return
}
log.Error("d.followingCache err(%v)", err)
return
}
followingList := &model.FollowingList{}
if err = conn.Scan(item, followingList); err != nil {
log.Error("d.followinfCache err(%v)", err)
}
followings = followingList.FollowingList
if followings == nil {
followings = []*model.Following{}
}
return
}
// delFollowingCache delete following cache.
func (d *Dao) delFollowingCache(c context.Context, key string) (err error) {
conn := d.mc.Get(c)
if err = conn.Delete(key); err != nil {
if err == gmc.ErrNotFound {
err = nil
} else {
log.Error("conn.Delete(%s) error(%v)", key, err)
}
}
conn.Close()
return
}
// TagCountCache tag count cache
func (d *Dao) TagCountCache(c context.Context, mid int64) (tagCount []*model.TagCount, err error) {
conn := d.mc.Get(c)
defer conn.Close()
res, err := conn.Get(tagCountKey(mid))
if err != nil {
if err == gmc.ErrNotFound {
err = nil
return
}
log.Error("mc.Get error(%v)", err)
return
}
tc := &model.TagCountList{}
if err = conn.Scan(res, tc); err != nil {
log.Error("conn.Scan error(%v)", err)
}
tagCount = tc.TagCountList
return
}
// SetTagCountCache set tag count cache
func (d *Dao) SetTagCountCache(c context.Context, mid int64, tagCount []*model.TagCount) (err error) {
item := &gmc.Item{Key: tagCountKey(mid), Object: &model.TagCountList{TagCountList: tagCount}, Expiration: d.mcExpire, Flags: gmc.FlagProtobuf}
conn := d.mc.Get(c)
if err = conn.Set(item); err != nil {
log.Error("setTagMidFidCache(%s) error(%v)", tagCountKey(mid), err)
}
conn.Close()
return
}
// DelTagCountCache del tag count cache
func (d *Dao) DelTagCountCache(c context.Context, mid int64) (err error) {
conn := d.mc.Get(c)
if err = conn.Delete(tagCountKey(mid)); err != nil {
if err == gmc.ErrNotFound {
err = nil
} else {
log.Error("conn.Delete(%s) error(%v)", tagCountKey(mid), err)
}
}
conn.Close()
return
}
// SetTagsCache set user tags cache.
func (d *Dao) SetTagsCache(c context.Context, mid int64, tags *model.Tags) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
item := &gmc.Item{Key: tagsKey(mid), Object: tags, Expiration: d.mcExpire, Flags: gmc.FlagProtobuf}
if err = conn.Set(item); err != nil {
log.Error("SetTagsCache err %v", err)
}
return
}
// TagsCache get user tags.
func (d *Dao) TagsCache(c context.Context, mid int64) (tags map[int64]*model.Tag, err error) {
conn := d.mc.Get(c)
defer conn.Close()
res, err := conn.Get(tagsKey(mid))
if err != nil {
if err == gmc.ErrNotFound {
err = nil
return
}
return
}
tag := new(model.Tags)
if err = conn.Scan(res, tag); err != nil {
return
}
tags = tag.Tags
return
}
// DelTagsCache del user tags cache.
func (d *Dao) DelTagsCache(c context.Context, mid int64) (err error) {
conn := d.mc.Get(c)
if err = conn.Delete(tagsKey(mid)); err != nil {
if err == gmc.ErrNotFound {
err = nil
} else {
log.Error("conn.Delete(%s) error(%v)", tagCountKey(mid), err)
}
}
conn.Close()
return
}
// SetGlobalHotRecCache set global hot recommend cache.
func (d *Dao) SetGlobalHotRecCache(c context.Context, fids []int64) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
item := &gmc.Item{Key: globalHotKey(), Object: &model.GlobalRec{Fids: fids}, Expiration: _recExpire, Flags: gmc.FlagProtobuf}
if err = conn.Set(item); err != nil {
log.Error("SetGlobalHotRecCache err %v", err)
}
return
}
// GlobalHotRecCache get global hot recommend.
func (d *Dao) GlobalHotRecCache(c context.Context) (fs []int64, err error) {
conn := d.mc.Get(c)
defer conn.Close()
res, err := conn.Get(globalHotKey())
if err != nil {
if err == gmc.ErrNotFound {
err = nil
}
return
}
gh := new(model.GlobalRec)
if err = conn.Scan(res, gh); err != nil {
return
}
fs = gh.Fids
return
}
// SetStatCache set stat cache.
func (d *Dao) SetStatCache(c context.Context, mid int64, st *model.Stat) error {
conn := d.mc.Get(c)
defer conn.Close()
item := &gmc.Item{
Key: statKey(mid),
Object: st,
Expiration: d.mcExpire,
Flags: gmc.FlagProtobuf,
}
if err := conn.Set(item); err != nil {
log.Error("Failed to set stat cache: mid: %d stat: %+v: %+v", mid, st, err)
return err
}
return nil
}
// statCache get stat cache.
func (d *Dao) statCache(c context.Context, mid int64) (*model.Stat, error) {
conn := d.mc.Get(c)
defer conn.Close()
item, err := conn.Get(statKey(mid))
if err != nil {
if err == gmc.ErrNotFound {
return nil, nil
}
return nil, err
}
stat := &model.Stat{}
if err := conn.Scan(item, stat); err != nil {
log.Error("Failed to get stat cache: mid: %d: %+v", mid, err)
return nil, err
}
return stat, nil
}
// statsCache get multi stat cache.
func (d *Dao) statsCache(c context.Context, mids []int64) (map[int64]*model.Stat, []int64, error) {
conn := d.mc.Get(c)
defer conn.Close()
keys := make([]string, 0, len(mids))
for _, mid := range mids {
keys = append(keys, statKey(mid))
}
items, err := conn.GetMulti(keys)
if err != nil {
log.Error("Failed to get multi stat: keys: %+v: %+v", keys, err)
return nil, nil, err
}
stats := make(map[int64]*model.Stat, len(mids))
for _, item := range items {
stat := &model.Stat{}
if err := conn.Scan(item, stat); err != nil {
log.Error("Failed to scan item: key: %s item: %+v: %+v", item.Key, item, err)
continue
}
stats[stat.Mid] = stat
}
missed := make([]int64, 0, len(mids))
for _, mid := range mids {
if _, ok := stats[mid]; !ok {
missed = append(missed, mid)
}
}
return stats, missed, nil
}
// DelStatCache delete stat cache.
func (d *Dao) DelStatCache(c context.Context, mid int64) error {
conn := d.mc.Get(c)
defer conn.Close()
if err := conn.Delete(statKey(mid)); err != nil {
if err == gmc.ErrNotFound {
return nil
}
log.Error("Failed to delete stat cache: mid: %d: %+v", mid, err)
return err
}
return nil
}
// GetFollowerNotifyCache get data from mc
func (d *Dao) GetFollowerNotifyCache(c context.Context, mid int64) (res *model.FollowerNotifySetting, err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := followerNotifySetting(mid)
reply, err := conn.Get(key)
if err != nil {
if err == gmc.ErrNotFound {
err = nil
return
}
log.Errorv(c, log.KV("GetFollowerNotifyCache", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
res = &model.FollowerNotifySetting{}
err = conn.Scan(reply, res)
if err != nil {
log.Errorv(c, log.KV("GetFollowerNotifyCache", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// SetFollowerNotifyCache Set data to mc
func (d *Dao) SetFollowerNotifyCache(c context.Context, mid int64, val *model.FollowerNotifySetting) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := followerNotifySetting(mid)
item := &gmc.Item{
Key: key,
Object: val,
Expiration: 86400,
Flags: gmc.FlagJSON,
}
if err = conn.Set(item); err != nil {
log.Errorv(c, log.KV("SetFollowerNotifyCache", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// DelFollowerNotifyCache Del data from mc
func (d *Dao) DelFollowerNotifyCache(c context.Context, mid int64) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := followerNotifySetting(mid)
if err = conn.Delete(key); err != nil {
if err == gmc.ErrNotFound {
err = nil
return
}
log.Errorv(c, log.KV("DelFollowerNotifyCache", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}

View File

@@ -0,0 +1,375 @@
package dao
import (
"context"
"go-common/app/service/main/relation/model"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaostatKey(t *testing.T) {
var (
mid = int64(1)
)
convey.Convey("statKey", t, func(cv convey.C) {
p1 := statKey(mid)
cv.Convey("Then p1 should not be nil.", func(cv convey.C) {
cv.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaotagsKey(t *testing.T) {
var (
mid = int64(1)
)
convey.Convey("tagsKey", t, func(cv convey.C) {
p1 := tagsKey(mid)
cv.Convey("Then p1 should not be nil.", func(cv convey.C) {
cv.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaofollowingKey(t *testing.T) {
var (
mid = int64(1)
)
convey.Convey("followingKey", t, func(cv convey.C) {
p1 := followingKey(mid)
cv.Convey("Then p1 should not be nil.", func(cv convey.C) {
cv.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaofollowerKey(t *testing.T) {
var (
mid = int64(1)
)
convey.Convey("followerKey", t, func(cv convey.C) {
p1 := followerKey(mid)
cv.Convey("Then p1 should not be nil.", func(cv convey.C) {
cv.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaotagCountKey(t *testing.T) {
var (
mid = int64(1)
)
convey.Convey("tagCountKey", t, func(cv convey.C) {
p1 := tagCountKey(mid)
cv.Convey("Then p1 should not be nil.", func(cv convey.C) {
cv.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoglobalHotKey(t *testing.T) {
convey.Convey("globalHotKey", t, func(cv convey.C) {
p1 := globalHotKey()
cv.Convey("Then p1 should not be nil.", func(cv convey.C) {
cv.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaofollowerNotifySetting(t *testing.T) {
var (
mid = int64(1)
)
convey.Convey("followerNotifySetting", t, func(cv convey.C) {
p1 := followerNotifySetting(mid)
cv.Convey("Then p1 should not be nil.", func(cv convey.C) {
cv.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaopingMC(t *testing.T) {
var (
c = context.Background()
)
convey.Convey("pingMC", t, func(cv convey.C) {
err := d.pingMC(c)
cv.Convey("Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoSetFollowingCache(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
followings = []*model.Following{}
)
convey.Convey("SetFollowingCache", t, func(cv convey.C) {
err := d.SetFollowingCache(c, mid, followings)
cv.Convey("Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoFollowingCache(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
)
convey.Convey("FollowingCache", t, func(cv convey.C) {
followings, err := d.FollowingCache(c, mid)
cv.Convey("Then err should be nil.followings should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(followings, convey.ShouldNotBeNil)
})
})
}
func TestDaoDelFollowingCache(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
)
convey.Convey("DelFollowingCache", t, func(cv convey.C) {
err := d.DelFollowingCache(c, mid)
cv.Convey("Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoSetFollowerCache(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
followers = []*model.Following{}
)
convey.Convey("SetFollowerCache", t, func(cv convey.C) {
err := d.SetFollowerCache(c, mid, followers)
cv.Convey("Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoFollowerCache(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
)
convey.Convey("FollowerCache", t, func(cv convey.C) {
followers, err := d.FollowerCache(c, mid)
cv.Convey("Then err should be nil.followers should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(followers, convey.ShouldNotBeNil)
})
})
}
func TestDaoDelFollowerCache(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
)
convey.Convey("DelFollowerCache", t, func(cv convey.C) {
err := d.DelFollowerCache(c, mid)
cv.Convey("Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
})
}
func TestDaosetFollowingCache(t *testing.T) {
var (
c = context.Background()
key = followingKey(1)
followings = []*model.Following{}
)
convey.Convey("setFollowingCache", t, func(cv convey.C) {
err := d.setFollowingCache(c, key, followings)
cv.Convey("Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
})
}
func TestDaofollowingCache(t *testing.T) {
var (
c = context.Background()
key = followingKey(1)
)
convey.Convey("followingCache", t, func(cv convey.C) {
followings, err := d.followingCache(c, key)
cv.Convey("Then err should be nil.followings should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(followings, convey.ShouldNotBeNil)
})
})
}
func TestDaodelFollowingCache(t *testing.T) {
var (
c = context.Background()
key = followingKey(1)
)
convey.Convey("delFollowingCache", t, func(cv convey.C) {
err := d.delFollowingCache(c, key)
cv.Convey("Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoTagCountCache(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
tagCount = []*model.TagCount{
{
Tagid: 1,
Name: "test",
Count: 1,
},
}
)
convey.Convey("TagCountCache", t, func(cv convey.C) {
err := d.SetTagCountCache(c, mid, tagCount)
cv.So(err, convey.ShouldBeNil)
tagCount, err := d.TagCountCache(c, mid)
cv.So(err, convey.ShouldBeNil)
cv.So(tagCount, convey.ShouldNotBeNil)
err = d.DelTagCountCache(c, mid)
cv.So(err, convey.ShouldBeNil)
})
}
func TestDaoTagsCache(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
tags = &model.Tags{
Tags: map[int64]*model.Tag{
1: {
Id: 1,
Name: "1",
Status: 1,
},
},
}
)
convey.Convey("TagsCache", t, func(cv convey.C) {
err := d.SetTagsCache(c, mid, tags)
cv.Convey("SetTagsCache; Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
tags, err := d.TagsCache(c, mid)
cv.Convey("TagsCache; Then err should be nil.tags should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(tags, convey.ShouldNotBeNil)
})
err = d.DelTagsCache(c, mid)
cv.Convey("DelTagsCache; Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoSetGlobalHotRecCache(t *testing.T) {
var (
c = context.Background()
fids = []int64{1}
)
convey.Convey("SetGlobalHotRecCache", t, func(cv convey.C) {
err := d.SetGlobalHotRecCache(c, fids)
cv.Convey("Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoGlobalHotRecCache(t *testing.T) {
var (
c = context.Background()
)
convey.Convey("GlobalHotRecCache", t, func(cv convey.C) {
fs, err := d.GlobalHotRecCache(c)
cv.Convey("Then err should be nil.fs should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(fs, convey.ShouldNotBeNil)
})
})
}
func TestDaostatCache(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
st = &model.Stat{
Mid: 1,
Follower: 1,
Following: 1,
Black: 1,
Whisper: 1,
}
)
convey.Convey("statCache", t, func(cv convey.C) {
err := d.SetStatCache(c, mid, st)
cv.Convey("SetStatCache; Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
s1, err := d.statCache(c, mid)
cv.Convey("statCache; Then err should be nil.p1 should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(s1, convey.ShouldNotBeNil)
})
p1, p2, err := d.statsCache(c, []int64{1})
cv.Convey("statsCache; Then err should be nil.p1,p2 should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(p2, convey.ShouldNotBeNil)
cv.So(p1, convey.ShouldNotBeNil)
})
err = d.DelStatCache(c, mid)
cv.Convey("DelStatCache; Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoGetFollowerNotifyCache(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
val = &model.FollowerNotifySetting{
Mid: 1,
Enabled: true,
}
)
convey.Convey("GetFollowerNotifyCache", t, func(cv convey.C) {
err := d.SetFollowerNotifyCache(c, mid, val)
cv.Convey("SetFollowerNotifyCache; Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
res, err := d.GetFollowerNotifyCache(c, mid)
cv.Convey("GetFollowerNotifyCache; Then err should be nil.res should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(res, convey.ShouldNotBeNil)
})
err = d.DelFollowerNotifyCache(c, mid)
cv.Convey("DelFollowerNotifyCache; Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,499 @@
package dao
import (
"context"
xsql "database/sql"
"fmt"
"time"
"go-common/app/service/main/relation/model"
"go-common/app/service/main/relation/model/i64b"
"go-common/library/database/sql"
"go-common/library/log"
"go-common/library/xstr"
)
const (
_shard = 500
_statShard = 50
_tagShard = 100
_tagUserShard = 500
_defaultTag = "默认分组"
_specialTag = "特别关注"
// relation
_getFollowingSQL = "SELECT fid,attribute,mtime FROM user_relation_mid_%03d WHERE mid=? AND status=0"
_getFollowingInSQL = "SELECT fid,attribute,mtime FROM user_relation_mid_%03d WHERE mid=? AND status=0 AND fid IN (%s)"
_addFollowingSQL = "INSERT INTO user_relation_mid_%03d (mid,fid,attribute,source,status, ctime,mtime) VALUES (?,?,?,?,0,?,?) ON DUPLICATE KEY UPDATE attribute=attribute|?,source=?,status=0,mtime=?"
_setFollowingSQL = "UPDATE user_relation_mid_%03d SET attribute=?,source=?,status=?,mtime=? WHERE mid=? AND fid=?"
_getFollowersSQL = "SELECT mid,attribute,mtime FROM user_relation_fid_%03d WHERE fid=? AND status=0 AND attribute IN (2,6) ORDER BY mtime DESC LIMIT 1000"
_addFollowersSQL = "INSERT INTO user_relation_fid_%03d (mid,fid,attribute,source,status,ctime,mtime) VALUES (?,?,?,?,0,?,?) ON DUPLICATE KEY UPDATE attribute=attribute|?,source=?,status=0,mtime=?"
_setFollowersSQL = "UPDATE user_relation_fid_%03d SET attribute=?,source=?,status=?,mtime=? WHERE fid=? AND mid=?"
_getRelationSQL = "SELECT attribute FROM user_relation_mid_%03d WHERE mid=? AND fid=? AND status=0 LIMIT 1"
_addStatIgnoreSQL = "INSERT IGNORE INTO user_relation_stat_%02d (mid,following,whisper,black,follower,ctime,mtime) VALUES (?,?,?,?,?,?,?)"
_addStatSQL = "UPDATE user_relation_stat_%02d SET following=following+?,whisper=whisper+?,black=black+?,follower=follower+?,mtime=? WHERE mid=?"
_setStatSQL = "UPDATE user_relation_stat_%02d SET following=?,whisper=?,black=?,follower=?,mtime=? WHERE mid=?"
_getStatSQL = "SELECT mid,following,whisper,black,follower, ctime,mtime from user_relation_stat_%02d where mid=?"
_getTxStatSQL = "SELECT mid,following,whisper,black,follower,ctime,mtime from user_relation_stat_%02d where mid=? FOR UPDATE"
// relation tag table
_getTagsSQL = "SELECT id,name,status,mtime FROM user_relation_tag_%02d WHERE mid=? AND status=0"
_addTagSQL = "INSERT INTO user_relation_tag_%02d (mid,name,status,ctime,mtime) VALUES (?,?,0,?,?)"
_delTagSQL = "DELETE FROM user_relation_tag_%02d WHERE id=? AND mid=?"
_setTagNameSQL = "UPDATE user_relation_tag_%02d SET name=?,mtime=? WHERE id=?"
// relation tag user table
_getTagUserSQL = "SELECT fid,tag FROM user_relation_tag_user_%03d WHERE mid=?"
_getUsersTagSQL = "SELECT fid,tag FROM user_relation_tag_user_%03d WHERE mid=? AND fid IN(%s)"
_getTagsByMidFidSQL = "SELECT fid,tag,mtime FROM user_relation_tag_user_%03d WHERE mid=? and fid=?"
_addTagUserSQL = "INSERT INTO user_relation_tag_user_%03d (mid,fid,tag,ctime,mtime) VALUES (?,?,?,?,?) ON DUPLICATE KEY UPDATE tag=?"
_setTagUserSQL = "UPDATE user_relation_tag_user_%03d SET tag=?,mtime=? WHERE mid=? AND fid=?"
_delTagUserSQL = "DELETE FROM user_relation_tag_user_%03d WHERE mid=? AND fid=?"
// relation monitor
_loadMonitorSQL = "SELECT mid FROM user_relation_monitor"
_addMonitorSQL = "INSERT IGNORE INTO user_relation_monitor (mid,ctime,mtime) VALUES (?,?,?)"
_delMonitorSQL = "DELETE FROM user_relation_monitor WHERE mid = ?"
// relation achieve
_hasReachAchieve = "SELECT count(1) FROM user_addit WHERE mid=? AND achieve_flags>=?"
// follower notify
_getFollowerNotifySettingSQL = "SELECT disable_follower_notify FROM user_addit where mid=?"
_enableFollowerNotifySQL = "INSERT INTO user_addit (mid, disable_follower_notify) VALUES(?, 0) ON DUPLICATE KEY UPDATE disable_follower_notify=0"
_disableFollowerNotifySQL = "INSERT INTO user_addit (mid, disable_follower_notify) VALUES(?, 1) ON DUPLICATE KEY UPDATE disable_follower_notify=1"
)
func hit(id int64) int64 {
return id % _shard
}
func statHit(id int64) int64 {
return id % _statShard
}
func tagHit(id int64) int64 {
return id % _tagShard
}
func tagUserHit(id int64) int64 {
return id % _tagUserShard
}
// BeginTran begin transaction.
func (d *Dao) BeginTran(c context.Context) (*sql.Tx, error) {
return d.db.Begin(c)
}
// Followings get user's following list.
func (d *Dao) Followings(c context.Context, mid int64) (res []*model.Following, err error) {
var rows *sql.Rows
if rows, err = d.db.Query(c, fmt.Sprintf(_getFollowingSQL, hit(mid)), mid); err != nil {
log.Error("d.query[%s].hit(%d).mid(%d) error(%v)", _getFollowingSQL, hit(mid), mid, err)
return
}
defer rows.Close()
for rows.Next() {
r := new(model.Following)
if err = rows.Scan(&r.Mid, &r.Attribute, &r.MTime); err != nil {
log.Error("row.Scan() error(%v)", err)
res = nil
return
}
res = append(res, r)
}
err = rows.Err()
return
}
// FollowingsIn get user's following list by in fids
func (d *Dao) FollowingsIn(c context.Context, mid int64, fids []int64) (res []*model.Following, err error) {
var rows *sql.Rows
if rows, err = d.db.Query(c, fmt.Sprintf(_getFollowingInSQL, hit(mid), xstr.JoinInts(fids)), mid); err != nil {
log.Error("d.query[%d].Query(%d) error(%v)", hit(mid), mid, err)
return
}
defer rows.Close()
for rows.Next() {
r := new(model.Following)
if err = rows.Scan(&r.Mid, &r.Attribute, &r.MTime); err != nil {
log.Error("row.Scan() error(%v)", err)
res = nil
return
}
res = append(res, r)
}
err = rows.Err()
return
}
// TxAddFollowing add following by transaction.
func (d *Dao) TxAddFollowing(c context.Context, tx *sql.Tx, mid, fid int64, mask uint32, source uint8, now time.Time) (affected int64, err error) {
var res xsql.Result
if res, err = tx.Exec(fmt.Sprintf(_addFollowingSQL, hit(mid)), mid, fid, mask, source, now, now, mask, source, now); err != nil {
log.Error("add following: tx.Exec(%v, %d, %d, %d) error(%v)", mid, fid, mask, source, err)
return
}
return res.RowsAffected()
}
// TxSetFollowing set following by transaction.
func (d *Dao) TxSetFollowing(c context.Context, tx *sql.Tx, mid, fid int64, attribute uint32, source uint8, status int, now time.Time) (affected int64, err error) {
var res xsql.Result
if res, err = tx.Exec(fmt.Sprintf(_setFollowingSQL, hit(mid)), attribute, source, status, now, mid, fid); err != nil {
log.Error("tx.Exec(%d, %d, %d, %d, %d) error(%v)", mid, fid, attribute, source, status, err)
return
}
return res.RowsAffected()
}
// Followers get user's latest 1000 followers(attribute = AttrFollowing), order by mtime desc.
func (d *Dao) Followers(c context.Context, mid int64) (res []*model.Following, err error) {
var rows *sql.Rows
if rows, err = d.db.Query(c, fmt.Sprintf(_getFollowersSQL, hit(mid)), mid); err != nil {
log.Error("d.query(%s).hit(%d).mid(%d) error(%v)", _getFollowersSQL, hit(mid), mid, err)
return
}
defer rows.Close()
for rows.Next() {
r := new(model.Following)
if err = rows.Scan(&r.Mid, &r.Attribute, &r.MTime); err != nil {
log.Error("row.Scan() error(%v)", err)
res = nil
return
}
res = append(res, r)
}
err = rows.Err()
return
}
// TxAddFollower add follower by transaction.
func (d *Dao) TxAddFollower(c context.Context, tx *sql.Tx, mid, fid int64, mask uint32, source uint8, now time.Time) (affected int64, err error) {
var res xsql.Result
if res, err = tx.Exec(fmt.Sprintf(_addFollowersSQL, hit(fid)), mid, fid, mask, source, now, now, mask, source, now); err != nil {
log.Error("add follower: tx.Exec(%v, %d, %d, %d), error(%v)", mid, fid, mask, source, err)
return
}
return res.RowsAffected()
}
// TxSetFollower set follower by transaction.
func (d *Dao) TxSetFollower(c context.Context, tx *sql.Tx, mid, fid int64, attribute uint32, source uint8, status int, now time.Time) (affected int64, err error) {
var res xsql.Result
if res, err = tx.Exec(fmt.Sprintf(_setFollowersSQL, hit(fid)), attribute, source, status, now, fid, mid); err != nil {
log.Error("tx.Exec(%d, %d, %d, %d, %d) error(%v)", mid, fid, attribute, source, status, err)
return
}
return res.RowsAffected()
}
// Stat get stat.
func (d *Dao) Stat(c context.Context, mid int64) (stat *model.Stat, err error) {
var row = d.db.QueryRow(c, fmt.Sprintf(_getStatSQL, statHit(mid)), mid)
stat = new(model.Stat)
if err = row.Scan(&stat.Mid, &stat.Following, &stat.Whisper, &stat.Black, &stat.Follower, &stat.CTime, &stat.MTime); err != nil {
if err == sql.ErrNoRows {
stat = nil
err = nil
} else {
log.Error("row.Scan() error(%v)", err)
}
}
return
}
// TxStat get stat for update by transaction.
func (d *Dao) TxStat(c context.Context, tx *sql.Tx, mid int64) (stat *model.Stat, err error) {
row := tx.QueryRow(fmt.Sprintf(_getTxStatSQL, statHit(mid)), mid)
stat = new(model.Stat)
if err = row.Scan(&stat.Mid, &stat.Following, &stat.Whisper, &stat.Black, &stat.Follower, &stat.CTime, &stat.MTime); err != nil {
if err == sql.ErrNoRows {
stat = nil
err = nil
} else {
log.Error("row.Scan() error(%v)", err)
}
}
return
}
// AddStat try add stat.
func (d *Dao) AddStat(c context.Context, mid int64, stat *model.Stat, now time.Time) (affected int64, err error) {
var res xsql.Result
if res, err = d.db.Exec(c, fmt.Sprintf(_addStatIgnoreSQL, statHit(mid)), mid, stat.Following, stat.Whisper, stat.Black, stat.Follower, now, now); err != nil {
log.Error("d.db.Exec(%s, %d, %v, %v) error(%v)", _addStatIgnoreSQL, mid, stat, now, err)
return
}
return res.RowsAffected()
}
// TxAddStat add params stat to stat by transaction.
func (d *Dao) TxAddStat(c context.Context, tx *sql.Tx, mid int64, stat *model.Stat, now time.Time) (affected int64, err error) {
var res xsql.Result
if res, err = tx.Exec(fmt.Sprintf(_addStatSQL, statHit(mid)), stat.Following, stat.Whisper, stat.Black, stat.Follower, now, mid); err != nil {
log.Error("tx.Exec(%s, %d, %v, %v) error(%v)", _addStatSQL, mid, stat, now, err)
return
}
return res.RowsAffected()
}
// TxSetStat set stat to params stat by transaction.
func (d *Dao) TxSetStat(c context.Context, tx *sql.Tx, mid int64, stat *model.Stat, now time.Time) (affected int64, err error) {
var res xsql.Result
if res, err = tx.Exec(fmt.Sprintf(_setStatSQL, statHit(mid)), stat.Following, stat.Whisper, stat.Black, stat.Follower, now, mid); err != nil {
log.Error("tx.Exec(%s, %d, %v, %v) error(%v)", _setStatSQL, mid, stat, now, err)
return
}
return res.RowsAffected()
}
// Relation get relation between mid and fid.
func (d *Dao) Relation(c context.Context, mid, fid int64) (attr uint32, err error) {
row := d.db.QueryRow(c, fmt.Sprintf(_getRelationSQL, hit(mid)), mid, fid)
if err = row.Scan(&attr); err != nil {
if err == sql.ErrNoRows {
attr = model.AttrNoRelation
err = nil
} else {
log.Error("row.Scan() error(%v)", err)
}
}
return
}
// LoadMonitor load all mids into redis set.
func (d *Dao) LoadMonitor(c context.Context) (mids []int64, err error) {
var rows *sql.Rows
if rows, err = d.db.Query(c, _loadMonitorSQL); err != nil {
log.Error("d.Query.Exec(%s) error(%v)", _loadMonitorSQL, err)
return
}
defer rows.Close()
for rows.Next() {
var mid int64
if err = rows.Scan(&mid); err != nil {
log.Error("row.Scan() error(%v)", err)
mids = nil
return
}
mids = append(mids, mid)
}
err = rows.Err()
return
}
// AddMonitor add mid to monitor table
func (d *Dao) AddMonitor(c context.Context, mid int64, now time.Time) (affected int64, err error) {
var res xsql.Result
if res, err = d.db.Exec(c, _addMonitorSQL, mid, now, now); err != nil {
log.Error("d.AddMonitor.Exec(%s, %d) error(%v)", _addMonitorSQL, mid, err)
return
}
return res.RowsAffected()
}
// DelMonitor del mid from monitor table
func (d *Dao) DelMonitor(c context.Context, mid int64) (affected int64, err error) {
var res xsql.Result
if res, err = d.db.Exec(c, _delMonitorSQL, mid); err != nil {
log.Error("d.DelMonitor.Exec(%s, %d)", _delMonitorSQL, mid)
return
}
return res.RowsAffected()
}
// TxDelTagUser delete tag user record.
func (d *Dao) TxDelTagUser(c context.Context, tx *sql.Tx, mid, fid int64) (affected int64, err error) {
var res xsql.Result
if res, err = tx.Exec(fmt.Sprintf(_delTagUserSQL, tagUserHit(mid)), mid, fid); err != nil {
log.Error("tx.Exec(%d, %d) error(%v)", mid, fid, err)
return
}
return res.RowsAffected()
}
// Tags get tags list.
func (d *Dao) Tags(c context.Context, mid int64) (res map[int64]*model.Tag, err error) {
var rows *sql.Rows
if rows, err = d.db.Query(c, fmt.Sprintf(_getTagsSQL, tagHit(mid)), mid); err != nil {
log.Error("d.getTagsStmt[%d].Query(%d) error(%sv)", tagHit(mid), mid, err)
return
}
defer rows.Close()
res = make(map[int64]*model.Tag)
for rows.Next() {
r := new(model.Tag)
if err = rows.Scan(&r.Id, &r.Name, &r.Status, &r.MTime); err != nil {
log.Error("d.getTagsStmt[%d].Query(%d) row.Scan() error(%v)", tagHit(mid), mid, err)
res = nil
return
}
res[r.Id] = r
}
res[0] = &model.Tag{Id: 0, Name: _defaultTag}
res[-10] = &model.Tag{Id: -10, Name: _specialTag}
err = rows.Err()
return
}
// AddTag add tag.
func (d *Dao) AddTag(c context.Context, mid, fid int64, tag string, now time.Time) (lastID int64, err error) {
var res xsql.Result
if res, err = d.db.Exec(c, fmt.Sprintf(_addTagSQL, tagHit(mid)), mid, tag, now, now); err != nil {
log.Error("d.db.Exec(%s, %d, %d, %s) error(%v)", _addTagSQL, mid, fid, tag, err)
return
}
return res.LastInsertId()
}
// DelTag del tag.
func (d *Dao) DelTag(c context.Context, mid, id int64) (affected int64, err error) {
var res xsql.Result
if res, err = d.db.Exec(c, fmt.Sprintf(_delTagSQL, tagHit(mid)), id, mid); err != nil {
log.Error("d.db.Exec(%s, %d, %d) error(%v)", _delTagSQL, mid, id, err)
return
}
return res.RowsAffected()
}
// SetTagName update tag name info.
func (d *Dao) SetTagName(c context.Context, id, mid int64, name string, now time.Time) (affected int64, err error) {
var res xsql.Result
if res, err = d.db.Exec(c, fmt.Sprintf(_setTagNameSQL, tagHit(mid)), name, now, id); err != nil {
log.Error("d.db.Exec(%s, %s, %d, %d)", _setTagNameSQL, name, mid, id)
return
}
return res.RowsAffected()
}
// TagUserByMidFid get tagIds by mid and fid.
func (d *Dao) TagUserByMidFid(c context.Context, mid, fid int64) (tag *model.TagUser, err error) {
row := d.db.QueryRow(c, fmt.Sprintf(_getTagsByMidFidSQL, tagUserHit(mid)), mid, fid)
var tids i64b.Int64Bytes
tag = new(model.TagUser)
if err = row.Scan(&tag.Fid, &tids, &tag.MTime); err != nil {
if err == sql.ErrNoRows {
tag = nil
err = nil
} else {
log.Error("d.getTagStmt[%d].Query(%d) row.Scan() error(%v)", tagUserHit(mid), mid, err)
}
return
}
tag.Tag = tids
return
}
// UsersTags users tag by fids.
func (d *Dao) UsersTags(c context.Context, mid int64, fid []int64) (tags map[int64]*model.TagUser, err error) {
row, err := d.db.Query(c, fmt.Sprintf(_getUsersTagSQL, tagUserHit(mid), xstr.JoinInts(fid)), mid)
if err != nil {
return
}
defer row.Close()
tags = make(map[int64]*model.TagUser)
for row.Next() {
tag := new(model.TagUser)
var tids i64b.Int64Bytes
if err = row.Scan(&tag.Fid, &tids); err != nil {
return
}
tag.Tag = tids
tags[tag.Fid] = tag
}
return
}
// UserTag user tag
func (d *Dao) UserTag(c context.Context, mid int64) (tags map[int64][]int64, err error) {
var rows *sql.Rows
if rows, err = d.db.Query(c, fmt.Sprintf(_getTagUserSQL, tagUserHit(mid)), mid); err != nil {
log.Error("d.Query[%d].Query(%d) error(%sv)", tagUserHit(mid), mid, err)
return
}
defer rows.Close()
tags = make(map[int64][]int64)
for rows.Next() {
var (
tids i64b.Int64Bytes
fid int64
)
if err = rows.Scan(&fid, &tids); err != nil {
log.Error("d.Scan[%d].Query(%d) row.Scan() error(%v)", tagUserHit(mid), mid, err)
tags = nil
return
}
tags[fid] = tids
}
err = rows.Err()
return
}
// SetTagUser setTagUser info.
func (d *Dao) SetTagUser(c context.Context, mid, fid int64, tag i64b.Int64Bytes, now time.Time) (affected int64, err error) {
var res xsql.Result
if res, err = d.db.Exec(c, fmt.Sprintf(_setTagUserSQL, tagUserHit(mid)), tag.Bytes(), now, mid, fid); err != nil {
log.Error("d.db.Exec(%s, %d, %d, %v) error (%v)", _setTagUserSQL, mid, fid, tag.Bytes(), err)
return
}
return res.RowsAffected()
}
// AddTagUser update tag name info.
func (d *Dao) AddTagUser(c context.Context, mid, fid int64, tag []int64, now time.Time) (affected int64, err error) {
var res xsql.Result
if res, err = d.db.Exec(c, fmt.Sprintf(_addTagUserSQL, tagUserHit(mid)), mid, fid, i64b.Int64Bytes(tag), now, now, i64b.Int64Bytes(tag)); err != nil {
log.Error("d.db.Exec(%s, %d, %d, %v) error (%v)", _addTagUserSQL, mid, fid, tag, err)
return
}
return res.RowsAffected()
}
// HasReachAchieve is
func (d *Dao) HasReachAchieve(c context.Context, mid int64, achieve model.AchieveFlag) bool {
row := d.db.QueryRow(c, _hasReachAchieve, mid, uint64(achieve))
count := 0
if err := row.Scan(&count); err != nil {
if err == xsql.ErrNoRows {
return false
}
log.Warn("Failed to check has reach achieve: mid: %d, achieve: %d, error: %+v", mid, achieve, err)
return false
}
if count > 0 {
return true
}
return false
}
// FollowerNotifySetting get follower-notify setting
// 这里返回用户通知开关的状态(和数据库存储的状态值相反)
func (d *Dao) FollowerNotifySetting(c context.Context, mid int64) (bool, error) {
row := d.db.QueryRow(c, _getFollowerNotifySettingSQL, mid)
var disableFollowerNotify bool
if err := row.Scan(&disableFollowerNotify); err != nil {
if err != sql.ErrNoRows {
log.Error("row.Scan() error(%v)", err)
}
return true, nil
}
if disableFollowerNotify {
return false, nil
}
return true, nil
}
// EnableFollowerNotify enable follower-notify setting
func (d *Dao) EnableFollowerNotify(c context.Context, mid int64) (affected int64, err error) {
var res xsql.Result
if res, err = d.db.Exec(c, _enableFollowerNotifySQL, mid); err != nil {
log.Error("enable follower-notify: tx.Exec(%d) error(%v)", mid, err)
return
}
return res.RowsAffected()
}
// DisableFollowerNotify disable follower-notify setting
func (d *Dao) DisableFollowerNotify(c context.Context, mid int64) (affected int64, err error) {
var res xsql.Result
if res, err = d.db.Exec(c, _disableFollowerNotifySQL, mid); err != nil {
log.Error("diabel follower-notify: tx.Exec(%d) error(%v)", mid, err)
return
}
return res.RowsAffected()
}

View File

@@ -0,0 +1,506 @@
package dao
import (
"context"
"go-common/app/service/main/relation/model"
"go-common/app/service/main/relation/model/i64b"
"math/rand"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func init() {
rand.Seed(time.Now().UnixNano())
}
var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
func RandStringRunes(n int) string {
b := make([]rune, n)
for i := range b {
b[i] = letterRunes[rand.Intn(len(letterRunes))]
}
return string(b)
}
func TestDaohit(t *testing.T) {
var (
id = int64(1)
)
convey.Convey("hit", t, func(cv convey.C) {
p1 := hit(id)
cv.Convey("Then p1 should not be nil.", func(cv convey.C) {
cv.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaostatHit(t *testing.T) {
var (
id = int64(1)
)
convey.Convey("statHit", t, func(cv convey.C) {
p1 := statHit(id)
cv.Convey("Then p1 should not be nil.", func(cv convey.C) {
cv.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaotagHit(t *testing.T) {
var (
id = int64(1)
)
convey.Convey("tagHit", t, func(cv convey.C) {
p1 := tagHit(id)
cv.Convey("Then p1 should not be nil.", func(cv convey.C) {
cv.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaotagUserHit(t *testing.T) {
var (
id = int64(1)
)
convey.Convey("tagUserHit", t, func(cv convey.C) {
p1 := tagUserHit(id)
cv.Convey("Then p1 should not be nil.", func(cv convey.C) {
cv.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoBeginTran(t *testing.T) {
var (
c = context.Background()
)
convey.Convey("BeginTran", t, func(cv convey.C) {
p1, err := d.BeginTran(c)
cv.Convey("Then err should be nil.p1 should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(p1, convey.ShouldNotBeNil)
})
p1.Commit()
})
}
func TestDaoFollowings(t *testing.T) {
var (
c = context.Background()
tx, _ = d.BeginTran(c)
mid = int64(1)
fid = int64(2)
mask = uint32(2)
source = uint8(1)
now = time.Now()
)
convey.Convey("Followings", t, func(cv convey.C) {
affected, err := d.TxAddFollowing(c, tx, mid, fid, mask, source, now)
cv.Convey("Then err should be nil.affected should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(affected, convey.ShouldNotBeNil)
})
tx.Commit()
res, err := d.Followings(c, mid)
cv.Convey("Then err should be nil.res should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoFollowingsIn(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
fids = []int64{1, 2}
)
convey.Convey("FollowingsIn", t, func(cv convey.C) {
res, err := d.FollowingsIn(c, mid, fids)
cv.Convey("Then err should be nil.res should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoTxSetFollowing(t *testing.T) {
var (
c = context.Background()
tx, _ = d.BeginTran(c)
mid = int64(1)
fid = int64(2)
attribute = uint32(2)
source = uint8(1)
status = int(0)
now = time.Now()
)
convey.Convey("TxSetFollowing", t, func(cv convey.C) {
affected, err := d.TxSetFollowing(c, tx, mid, fid, attribute, source, status, now)
cv.Convey("Then err should be nil.affected should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(affected, convey.ShouldNotBeNil)
})
tx.Commit()
})
}
func TestDaoFollowers(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
)
convey.Convey("Followers", t, func(cv convey.C) {
res, err := d.Followers(c, mid)
cv.Convey("Then err should be nil.res should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoTxAddFollower(t *testing.T) {
var (
c = context.Background()
tx, _ = d.BeginTran(c)
mid = int64(1)
fid = int64(2)
mask = uint32(2)
source = uint8(1)
now = time.Now()
)
convey.Convey("TxAddFollower", t, func(cv convey.C) {
affected, err := d.TxAddFollower(c, tx, mid, fid, mask, source, now)
cv.Convey("Then err should be nil.affected should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(affected, convey.ShouldNotBeNil)
})
tx.Commit()
})
}
func TestDaoTxSetFollower(t *testing.T) {
var (
c = context.Background()
tx, _ = d.BeginTran(c)
mid = int64(1)
fid = int64(2)
attribute = uint32(2)
source = uint8(1)
status = int(0)
now = time.Now()
)
convey.Convey("TxSetFollower", t, func(cv convey.C) {
affected, err := d.TxSetFollower(c, tx, mid, fid, attribute, source, status, now)
cv.Convey("Then err should be nil.affected should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(affected, convey.ShouldNotBeNil)
})
tx.Commit()
})
}
func TestDaoStat(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
)
convey.Convey("Stat", t, func(cv convey.C) {
stat, err := d.Stat(c, mid)
cv.Convey("Then err should be nil.stat should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(stat, convey.ShouldNotBeNil)
})
})
}
func TestDaoTxStat(t *testing.T) {
var (
c = context.Background()
tx, _ = d.BeginTran(c)
mid = int64(1)
)
convey.Convey("TxStat", t, func(cv convey.C) {
stat, err := d.TxStat(c, tx, mid)
cv.Convey("Then err should be nil.stat should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(stat, convey.ShouldNotBeNil)
})
tx.Commit()
})
}
func TestDaoAddStat(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
stat = &model.Stat{
Mid: 1,
}
now = time.Now()
)
convey.Convey("AddStat", t, func(cv convey.C) {
affected, err := d.AddStat(c, mid, stat, now)
cv.Convey("Then err should be nil.affected should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(affected, convey.ShouldNotBeNil)
})
})
}
func TestDaoTxAddStat(t *testing.T) {
var (
c = context.Background()
tx, _ = d.BeginTran(c)
mid = int64(1)
stat = &model.Stat{
Mid: 1,
}
now = time.Now()
)
convey.Convey("TxAddStat", t, func(cv convey.C) {
affected, err := d.TxAddStat(c, tx, mid, stat, now)
cv.Convey("Then err should be nil.affected should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(affected, convey.ShouldNotBeNil)
})
tx.Commit()
})
}
func TestDaoTxSetStat(t *testing.T) {
var (
c = context.Background()
tx, _ = d.BeginTran(c)
mid = int64(1)
stat = &model.Stat{
Mid: 1,
}
now = time.Now()
)
convey.Convey("TxSetStat", t, func(cv convey.C) {
affected, err := d.TxSetStat(c, tx, mid, stat, now)
cv.Convey("Then err should be nil.affected should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(affected, convey.ShouldNotBeNil)
})
tx.Commit()
})
}
func TestDaoRelation(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
fid = int64(2)
)
convey.Convey("Relation", t, func(cv convey.C) {
attr, err := d.Relation(c, mid, fid)
cv.Convey("Then err should be nil.attr should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(attr, convey.ShouldNotBeNil)
})
})
}
func TestDaoLoadMonitor(t *testing.T) {
var (
c = context.Background()
)
convey.Convey("LoadMonitor", t, func(cv convey.C) {
affected, err := d.AddMonitor(c, 1, time.Now())
cv.Convey("Then err should be nil.affected should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(affected, convey.ShouldNotBeNil)
})
mids, err := d.LoadMonitor(c)
cv.Convey("Then err should be nil.mids should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(mids, convey.ShouldNotBeNil)
})
})
}
func TestDaoDelMonitor(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
)
convey.Convey("DelMonitor", t, func(cv convey.C) {
affected, err := d.DelMonitor(c, mid)
cv.Convey("Then err should be nil.affected should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(affected, convey.ShouldNotBeNil)
})
})
}
func TestDaoTxDelTagUser(t *testing.T) {
var (
c = context.Background()
tx, _ = d.BeginTran(c)
mid = int64(1)
fid = int64(2)
)
convey.Convey("TxDelTagUser", t, func(cv convey.C) {
affected, err := d.TxDelTagUser(c, tx, mid, fid)
cv.Convey("Then err should be nil.affected should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(affected, convey.ShouldNotBeNil)
})
tx.Commit()
})
}
func TestDaoTags(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
)
convey.Convey("Tags", t, func(cv convey.C) {
res, err := d.Tags(c, mid)
cv.Convey("Then err should be nil.res should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoDelTag(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
id = int64(2)
)
convey.Convey("DelTag", t, func(cv convey.C) {
affected, err := d.DelTag(c, mid, id)
cv.Convey("Then err should be nil.affected should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(affected, convey.ShouldNotBeNil)
})
})
}
func TestDaoSetTagName(t *testing.T) {
var (
c = context.Background()
id = int64(1)
mid = int64(2)
name = "test"
now = time.Now()
)
convey.Convey("SetTagName", t, func(cv convey.C) {
affected, err := d.SetTagName(c, id, mid, name, now)
cv.Convey("Then err should be nil.affected should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(affected, convey.ShouldNotBeNil)
})
})
}
func TestDaoTagUserByMidFid(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
fid = int64(2)
)
convey.Convey("TagUserByMidFid", t, func(cv convey.C) {
lastID, err := d.AddTag(c, mid, fid, "test"+RandStringRunes(5), time.Now())
cv.Convey("AddTag; Then err should be nil.lastID should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(lastID, convey.ShouldNotBeNil)
})
tids := i64b.Int64Bytes([]int64{lastID})
affected, err := d.SetTagUser(c, mid, fid, tids, time.Now())
cv.Convey("SetTagUser; Then err should be nil.affected should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(affected, convey.ShouldNotBeNil)
})
affected2, err := d.AddTagUser(c, mid, fid, tids, time.Now())
cv.Convey("AddTagUser; Then err should be nil.affected should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(affected2, convey.ShouldNotBeNil)
})
tag1, err := d.TagUserByMidFid(c, mid, fid)
cv.Convey("TagUserByMidFid; Then err should be nil.tag1 should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(tag1, convey.ShouldNotBeNil)
})
tags2, err := d.UsersTags(c, mid, []int64{fid})
cv.Convey("UsersTags; Then err should be nil.tags2 should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(tags2, convey.ShouldNotBeNil)
})
tags3, err := d.UserTag(c, mid)
cv.Convey("UserTag; Then err should be nil.tags3 should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(tags3, convey.ShouldNotBeNil)
})
})
}
func TestDaoHasReachAchieve(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
achieve model.AchieveFlag
)
convey.Convey("HasReachAchieve", t, func(cv convey.C) {
p1 := d.HasReachAchieve(c, mid, achieve)
cv.Convey("Then p1 should not be nil.", func(cv convey.C) {
cv.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoFollowerNotifySetting(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
)
convey.Convey("FollowerNotifySetting", t, func(cv convey.C) {
p1, err := d.FollowerNotifySetting(c, mid)
cv.Convey("Then err should be nil.p1 should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoEnableFollowerNotify(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
)
convey.Convey("EnableFollowerNotify", t, func(cv convey.C) {
affected, err := d.EnableFollowerNotify(c, mid)
cv.Convey("Then err should be nil.affected should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(affected, convey.ShouldNotBeNil)
})
})
}
func TestDaoDisableFollowerNotify(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
)
convey.Convey("DisableFollowerNotify", t, func(cv convey.C) {
affected, err := d.DisableFollowerNotify(c, mid)
cv.Convey("Then err should be nil.affected should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(affected, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,78 @@
package dao
import (
"context"
"fmt"
"go-common/library/cache/redis"
)
const (
_cacheShard = 10000
_upPrompt = "rl_up_%d_%d" // key of upper prompt; hashes(fid-count)
_buPrompt = "rl_bu_%d_%d_%d" // key of business type prompt;hashes(mid-count)
)
// key upPrompt : rl_up_mid_ts/period
func (d *Dao) upPrompt(mid, ts int64) string {
return fmt.Sprintf(_upPrompt, mid, ts/d.period)
}
// key _buPrompt : rl_bu_businesstype_mid/10000_ts
func (d *Dao) buPrompt(btype int8, mid, ts int64) string {
return fmt.Sprintf(_buPrompt, btype, mid/_cacheShard, ts/d.period)
}
// IncrPromptCount incr up prompt count and business type prompt count.
func (d *Dao) IncrPromptCount(c context.Context, mid, fid, ts int64, btype int8) (ucount, bcount int64, err error) {
conn := d.redis.Get(c)
defer conn.Close()
keyUp := d.upPrompt(mid, ts)
keyBs := d.buPrompt(btype, mid, ts)
conn.Send("HINCRBY", keyUp, fid, 1)
conn.Send("EXPIRE", keyUp, d.period)
conn.Send("HINCRBY", keyBs, mid, 1)
conn.Send("EXPIRE", keyBs, d.period)
err = conn.Flush()
if err != nil {
return
}
ucount, err = redis.Int64(conn.Receive())
if err != nil {
return
}
conn.Receive()
bcount, err = redis.Int64(conn.Receive())
if err != nil {
return
}
conn.Receive()
return
}
// ClosePrompt set prompt count to max config value.
func (d *Dao) ClosePrompt(c context.Context, mid, fid, ts int64, btype int8) (err error) {
conn := d.redis.Get(c)
defer conn.Close()
keyUp := d.upPrompt(mid, ts)
keyBs := d.buPrompt(btype, mid, ts)
conn.Send("HSET", keyUp, fid, d.ucount)
conn.Send("HSET", keyBs, mid, d.bcount)
return conn.Flush()
}
// UpCount get upper prompt count.
func (d *Dao) UpCount(c context.Context, mid, fid, ts int64) (count int64, err error) {
conn := d.redis.Get(c)
count, err = redis.Int64(conn.Do("HGET", d.upPrompt(mid, ts), fid))
conn.Close()
return
}
// BCount get business type prompt count.
func (d *Dao) BCount(c context.Context, mid, ts int64, btype int8) (count int64, err error) {
conn := d.redis.Get(c)
count, err = redis.Int64(conn.Do("HGET", d.buPrompt(btype, mid, ts), mid))
conn.Close()
return
}

View File

@@ -0,0 +1,102 @@
package dao
import (
"context"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoupPrompt(t *testing.T) {
var (
mid = int64(1)
ts = time.Now().Unix()
)
convey.Convey("upPrompt", t, func(cv convey.C) {
p1 := d.upPrompt(mid, ts)
cv.Convey("Then p1 should not be nil.", func(cv convey.C) {
cv.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaobuPrompt(t *testing.T) {
var (
btype = int8(1)
mid = int64(1)
ts = time.Now().Unix()
)
convey.Convey("buPrompt", t, func(cv convey.C) {
p1 := d.buPrompt(btype, mid, ts)
cv.Convey("Then p1 should not be nil.", func(cv convey.C) {
cv.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoIncrPromptCount(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
fid = int64(2)
ts = time.Now().Unix()
btype = int8(1)
)
convey.Convey("IncrPromptCount", t, func(cv convey.C) {
ucount, bcount, err := d.IncrPromptCount(c, mid, fid, ts, btype)
cv.Convey("Then err should be nil.ucount,bcount should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(bcount, convey.ShouldNotBeNil)
cv.So(ucount, convey.ShouldNotBeNil)
})
})
}
func TestDaoClosePrompt(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
fid = int64(2)
ts = time.Now().Unix()
btype = int8(1)
)
convey.Convey("ClosePrompt", t, func(cv convey.C) {
err := d.ClosePrompt(c, mid, fid, ts, btype)
cv.Convey("Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoUpCount(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
fid = int64(2)
ts = time.Now().Unix()
)
convey.Convey("UpCount", t, func(cv convey.C) {
count, err := d.UpCount(c, mid, fid, ts)
cv.Convey("Then err should be nil.count should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(count, convey.ShouldNotBeNil)
})
})
}
func TestDaoBCount(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
btype = int8(1)
ts = time.Now().Unix()
)
convey.Convey("BCount", t, func(cv convey.C) {
count, err := d.BCount(c, mid, ts, btype)
cv.Convey("Then err should be nil.count should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(count, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,95 @@
package dao
import (
"context"
"time"
"go-common/library/cache/redis"
)
// AddRctFollower is
func (d *Dao) AddRctFollower(c context.Context, mid, fid int64) error {
key := recentFollower(fid)
conn := d.redis.Get(c)
defer conn.Close()
if err := conn.Send("ZADD", key, time.Now().Unix(), mid); err != nil {
return err
}
if err := conn.Send("EXPIRE", key, d.UnreadDuration); err != nil {
return err
}
if err := conn.Flush(); err != nil {
return err
}
return nil
}
// DelRctFollower is
func (d *Dao) DelRctFollower(c context.Context, mid, fid int64) error {
key := recentFollower(fid)
conn := d.redis.Get(c)
defer conn.Close()
_, err := conn.Do("ZREM", key, mid)
return err
}
// RctFollowerCount is
func (d *Dao) RctFollowerCount(ctx context.Context, fid int64) (int64, error) {
key := recentFollower(fid)
conn := d.redis.Get(ctx)
defer conn.Close()
count, err := redis.Int64(conn.Do("ZCARD", key))
if err != nil {
return 0, err
}
return count, nil
}
// EmptyRctFollower is
func (d *Dao) EmptyRctFollower(ctx context.Context, fid int64) error {
key := recentFollower(fid)
conn := d.redis.Get(ctx)
defer conn.Close()
_, err := conn.Do("DEL", key)
return err
}
// RctFollowerNotify is
func (d *Dao) RctFollowerNotify(c context.Context, fid int64) (bool, error) {
key := recentFollowerNotify(fid)
conn := d.redis.Get(c)
defer conn.Close()
flagi, err := redis.Int64(conn.Do("HGET", key, fid))
if err != nil {
if err == redis.ErrNil {
return false, nil
}
return false, err
}
flag := false
if flagi > 0 {
flag = true
}
return flag, err
}
// SetRctFollowerNotify is
func (d *Dao) SetRctFollowerNotify(c context.Context, fid int64, flag bool) error {
key := recentFollowerNotify(fid)
flagi := 0
if flag {
flagi = 1
}
conn := d.redis.Get(c)
defer conn.Close()
if err := conn.Send("HSET", key, fid, flagi); err != nil {
return err
}
if err := conn.Send("EXPIRE", key, d.UnreadDuration); err != nil {
return err
}
if err := conn.Flush(); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,91 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoAddRctFollower(t *testing.T) {
var (
c = context.Background()
mid = int64(0)
fid = int64(0)
)
convey.Convey("AddRctFollower", t, func(cv convey.C) {
err := d.AddRctFollower(c, mid, fid)
cv.Convey("Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoDelRctFollower(t *testing.T) {
var (
c = context.Background()
mid = int64(0)
fid = int64(0)
)
convey.Convey("DelRctFollower", t, func(cv convey.C) {
err := d.DelRctFollower(c, mid, fid)
cv.Convey("Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoRctFollowerCount(t *testing.T) {
var (
ctx = context.Background()
fid = int64(0)
)
convey.Convey("RctFollowerCount", t, func(cv convey.C) {
p1, err := d.RctFollowerCount(ctx, fid)
cv.Convey("Then err should be nil.p1 should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoEmptyRctFollower(t *testing.T) {
var (
ctx = context.Background()
fid = int64(0)
)
convey.Convey("EmptyRctFollower", t, func(cv convey.C) {
err := d.EmptyRctFollower(ctx, fid)
cv.Convey("Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoRctFollowerNotify(t *testing.T) {
var (
c = context.Background()
fid = int64(0)
)
convey.Convey("RctFollowerNotify", t, func(cv convey.C) {
p1, err := d.RctFollowerNotify(c, fid)
cv.Convey("Then err should be nil.p1 should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoSetRctFollowerNotify(t *testing.T) {
var (
c = context.Background()
fid = int64(0)
flag bool
)
convey.Convey("SetRctFollowerNotify", t, func(cv convey.C) {
err := d.SetRctFollowerNotify(c, fid, flag)
cv.Convey("Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,330 @@
package dao
import (
"context"
"fmt"
"strconv"
gtime "time"
"go-common/app/service/main/relation/model"
"go-common/library/cache/redis"
"go-common/library/log"
"go-common/library/time"
)
const (
_prefixFollowings = "at_" // key of public following with tags datas.
_prefixMonitor = "rs_mo_list" // key of monitor
_prefixRecentFollower = "rf_" // recent follower sorted set
_prefixRecentFollowerTime = "rft_" // recent follower sorted set
_prefixDailyNotifyCount = "dnc_%d_%s" // daily new-follower notificaiton count
_notifyCountExpire = 24 * 3600 // notify count scope is daily
)
func followingsKey(mid int64) string {
return _prefixFollowings + strconv.FormatInt(mid, 10)
}
func monitorKey() string {
return _prefixMonitor
}
func recentFollower(mid int64) string {
return _prefixRecentFollower + strconv.FormatInt(mid, 10)
}
func recentFollowerNotify(mid int64) string {
return _prefixRecentFollowerTime + strconv.FormatInt(mid%10000, 10)
}
func dailyNotifyCount(mid int64, date gtime.Time) string {
// _cacheShard 作为sharding
return fmt.Sprintf(_prefixDailyNotifyCount, mid%_cacheShard, date.Format("2006-01-02"))
}
// pingRedis ping redis.
func (d *Dao) pingRedis(c context.Context) (err error) {
conn := d.redis.Get(c)
if _, err = conn.Do("SET", "PING", "PONG"); err != nil {
log.Error("conn.Do(SET,PING,PONG) error(%v)", err)
}
conn.Close()
return
}
// SetFollowingsCache set followings cache.
func (d *Dao) SetFollowingsCache(c context.Context, mid int64, followings []*model.Following) (err error) {
key := followingsKey(mid)
args := redis.Args{}.Add(key)
expire := d.redisExpire
if len(followings) == 0 {
expire = 7200
}
ef, _ := d.encode(0, 0, nil, 0)
args = args.Add(0, ef)
for i := 0; i < len(followings); i++ {
var ef []byte
if ef, err = d.encode(followings[i].Attribute, followings[i].MTime, followings[i].Tag, followings[i].Special); err != nil {
return
}
args = args.Add(followings[i].Mid, ef)
}
conn := d.redis.Get(c)
defer conn.Close()
if err = conn.Send("DEL", key); err != nil {
log.Error("conn.Send(DEL, %s) error(%v)", key, err)
return
}
if err = conn.Send("HMSET", args...); err != nil {
log.Error("conn.Send(HMSET, %s) error(%v)", key, err)
return
}
if err = conn.Send("EXPIRE", key, expire); err != nil {
log.Error("conn.Send(EXPIRE, %s) error(%v)", key, err)
return
}
if err = conn.Flush(); err != nil {
log.Error("conn.Flush() error(%v)", err)
return
}
for i := 0; i < 3; i++ {
if _, err = conn.Receive(); err != nil {
log.Error("conn.Receive() %d error(%v)", i+1, err)
break
}
}
return
}
// AddFollowingCache add following cache.
func (d *Dao) AddFollowingCache(c context.Context, mid int64, following *model.Following) (err error) {
var (
ok bool
key = followingsKey(mid)
)
conn := d.redis.Get(c)
if ok, err = redis.Bool(conn.Do("EXPIRE", key, d.redisExpire)); err != nil {
log.Error("redis.Bool(conn.Do(EXPIRE, %s)) error(%v)", key, err)
} else if ok {
var ef []byte
if ef, err = d.encode(following.Attribute, following.MTime, following.Tag, following.Special); err != nil {
return
}
if _, err = conn.Do("HSET", key, following.Mid, ef); err != nil {
log.Error("conn.Do(HSET, %s, %d) error(%v)", key, following.Mid, err)
}
}
conn.Close()
return
}
// DelFollowing del following cache.
func (d *Dao) DelFollowing(c context.Context, mid int64, following *model.Following) (err error) {
var (
ok bool
key = followingsKey(mid)
)
conn := d.redis.Get(c)
if ok, err = redis.Bool(conn.Do("EXPIRE", key, d.redisExpire)); err != nil {
log.Error("redis.Bool(conn.Do(EXPIRE, %s)) error(%v)", key, err)
} else if ok {
if _, err = conn.Do("HDEL", key, following.Mid); err != nil {
log.Error("conn.Do(HDEL, %s, %d) error(%v)", key, following.Mid, err)
}
}
conn.Close()
return
}
// FollowingsCache get followings cache.
func (d *Dao) FollowingsCache(c context.Context, mid int64) (followings []*model.Following, err error) {
key := followingsKey(mid)
conn := d.redis.Get(c)
defer conn.Close()
tmp, err := redis.StringMap(conn.Do("HGETALL", key))
if err != nil {
return
}
if err == nil && len(tmp) > 0 {
for k, v := range tmp {
if mid, err = strconv.ParseInt(k, 10, 64); err != nil {
return
}
if mid <= 0 {
continue
}
vf := &model.FollowingTags{}
if err = d.decode([]byte(v), vf); err != nil {
//todo
return
}
followings = append(followings, &model.Following{
Mid: mid,
Attribute: vf.Attr,
Tag: vf.TagIds,
MTime: vf.Ts,
Special: vf.Special,
})
}
}
return
}
// DelFollowingsCache delete followings cache.
func (d *Dao) DelFollowingsCache(c context.Context, mid int64) (err error) {
key := followingsKey(mid)
conn := d.redis.Get(c)
if _, err = conn.Do("DEL", key); err != nil {
log.Error("conn.Do(DEL, %s) error(%v)", key, err)
}
conn.Close()
return
}
// RelationsCache relations cache.
func (d *Dao) RelationsCache(c context.Context, mid int64, fids []int64) (resMap map[int64]*model.Following, err error) {
var retRedis [][]byte
key := followingsKey(mid)
args := redis.Args{}.Add(key)
for _, fid := range fids {
args = args.Add(fid)
}
args.Add(0)
conn := d.redis.Get(c)
defer conn.Close()
if retRedis, err = redis.ByteSlices(conn.Do("HMGET", args...)); err != nil {
log.Error("redis.Int64s(conn.DO(HMGET, %v)) error(%v)", args, err)
return
}
resMap = make(map[int64]*model.Following)
for index, fid := range fids {
if retRedis[index] == nil {
continue
}
v := &model.FollowingTags{}
if err = d.decode(retRedis[index], v); err != nil {
return
}
resMap[fid] = &model.Following{
Mid: fid,
Attribute: v.Attr,
Tag: v.TagIds,
MTime: v.Ts,
Special: v.Special,
}
}
return
}
// encode
func (d *Dao) encode(attribute uint32, mtime time.Time, tagids []int64, special int32) (res []byte, err error) {
ft := &model.FollowingTags{Attr: attribute, Ts: mtime, TagIds: tagids, Special: special}
return ft.Marshal()
}
// decode
func (d *Dao) decode(src []byte, v *model.FollowingTags) (err error) {
return v.Unmarshal(src)
}
// MonitorCache monitor cache
func (d *Dao) MonitorCache(c context.Context, mid int64) (exist bool, err error) {
key := monitorKey()
conn := d.redis.Get(c)
if exist, err = redis.Bool(conn.Do("SISMEMBER", key, mid)); err != nil {
log.Error("redis.Bool(conn.Do(SISMEMBER, %s, %d)) error(%v)", key, mid, err)
}
conn.Close()
return
}
// SetMonitorCache set monitor cache
func (d *Dao) SetMonitorCache(c context.Context, mid int64) (err error) {
var (
key = monitorKey()
conn = d.redis.Get(c)
)
defer conn.Close()
if _, err = conn.Do("SADD", key, mid); err != nil {
log.Error("SADD conn.Do error(%v)", err)
return
}
return
}
// DelMonitorCache del monitor cache
func (d *Dao) DelMonitorCache(c context.Context, mid int64) (err error) {
var (
key = monitorKey()
conn = d.redis.Get(c)
)
defer conn.Close()
if _, err = redis.Int64(conn.Do("SREM", key, mid)); err != nil {
log.Error("SREM conn.Do(%s,%d) err(%v)", key, mid, err)
}
return
}
// LoadMonitorCache load monitor cache
func (d *Dao) LoadMonitorCache(c context.Context, mids []int64) (err error) {
var (
key = monitorKey()
conn = d.redis.Get(c)
)
defer conn.Close()
for _, v := range mids {
if err = conn.Send("SADD", key, v); err != nil {
log.Error("SADD conn.Do error(%v)", err)
return
}
}
if err = conn.Flush(); err != nil {
log.Error("conn.Flush error(%v)", err)
return
}
return
}
// TodayNotifyCountCache get notify count in the current day
func (d *Dao) TodayNotifyCountCache(c context.Context, mid int64) (notifyCount int64, err error) {
var (
key = dailyNotifyCount(mid, gtime.Now())
conn = d.redis.Get(c)
)
defer conn.Close()
if notifyCount, err = redis.Int64(conn.Do("HGET", key, mid)); err != nil {
if err == redis.ErrNil {
err = nil
return
}
log.Error("HGET conn.Do error(%v)", err)
return
}
if err = conn.Flush(); err != nil {
log.Error("conn.Flush error(%v)", err)
return
}
return
}
// IncrTodayNotifyCount increment the today notify count in the current day
func (d *Dao) IncrTodayNotifyCount(c context.Context, mid int64) (err error) {
var (
key = dailyNotifyCount(mid, gtime.Now())
conn = d.redis.Get(c)
)
defer conn.Close()
if err = conn.Send("HINCRBY", key, mid, 1); err != nil {
log.Error("HINCRBY conn.Do error(%v)", err)
return
}
if err = conn.Send("EXPIRE", key, _notifyCountExpire); err != nil {
log.Error("EXPIRE conn.Do error(%v)", err)
return
}
if err = conn.Flush(); err != nil {
log.Error("conn.Flush error(%v)", err)
return
}
return
}

View File

@@ -0,0 +1,249 @@
package dao
import (
"context"
"go-common/app/service/main/relation/model"
xtime "go-common/library/time"
"testing"
gtime "time"
"github.com/smartystreets/goconvey/convey"
)
func TestDaofollowingsKey(t *testing.T) {
var (
mid = int64(1)
)
convey.Convey("followingsKey", t, func(cv convey.C) {
p1 := followingsKey(mid)
cv.Convey("Then p1 should not be nil.", func(cv convey.C) {
cv.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaomonitorKey(t *testing.T) {
convey.Convey("monitorKey", t, func(cv convey.C) {
p1 := monitorKey()
cv.Convey("Then p1 should not be nil.", func(cv convey.C) {
cv.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaorecentFollower(t *testing.T) {
var (
mid = int64(1)
)
convey.Convey("recentFollower", t, func(cv convey.C) {
p1 := recentFollower(mid)
cv.Convey("Then p1 should not be nil.", func(cv convey.C) {
cv.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaorecentFollowerNotify(t *testing.T) {
var (
mid = int64(1)
)
convey.Convey("recentFollowerNotify", t, func(cv convey.C) {
p1 := recentFollowerNotify(mid)
cv.Convey("Then p1 should not be nil.", func(cv convey.C) {
cv.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaodailyNotifyCount(t *testing.T) {
var (
mid = int64(1)
date gtime.Time
)
convey.Convey("dailyNotifyCount", t, func(cv convey.C) {
p1 := dailyNotifyCount(mid, date)
cv.Convey("Then p1 should not be nil.", func(cv convey.C) {
cv.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaopingRedis(t *testing.T) {
var (
c = context.Background()
)
convey.Convey("pingRedis", t, func(cv convey.C) {
err := d.pingRedis(c)
cv.Convey("Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoFollowingsCache(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
)
convey.Convey("FollowingsCache", t, func(cv convey.C) {
err := d.SetFollowingsCache(c, mid, []*model.Following{
{Mid: 2},
})
cv.Convey("SetFollowingsCache; Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
err = d.AddFollowingCache(c, mid, &model.Following{Mid: 2})
cv.Convey("AddFollowingCache; Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
followings, err := d.FollowingsCache(c, mid)
cv.Convey("FollowingsCache; Then err should be nil.followings should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(followings, convey.ShouldNotBeNil)
})
err = d.DelFollowing(c, mid, &model.Following{Mid: 2})
cv.Convey("DelFollowing; Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoDelFollowingsCache(t *testing.T) {
var (
c = context.Background()
mid = int64(0)
)
convey.Convey("DelFollowingsCache", t, func(cv convey.C) {
err := d.DelFollowingsCache(c, mid)
cv.Convey("Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoRelationsCache(t *testing.T) {
var (
c = context.Background()
mid = int64(1)
fids = []int64{2}
)
convey.Convey("RelationsCache", t, func(cv convey.C) {
resMap, err := d.RelationsCache(c, mid, fids)
cv.Convey("Then err should be nil.resMap should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(resMap, convey.ShouldNotBeNil)
})
})
}
func TestDaoencode(t *testing.T) {
var (
attribute = uint32(0)
mtime = xtime.Time(int64(0))
tagids = []int64{}
special = int32(0)
)
convey.Convey("encode", t, func(cv convey.C) {
res, err := d.encode(attribute, mtime, tagids, special)
cv.Convey("Then err should be nil.res should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaodecode(t *testing.T) {
var (
src = []byte("")
v = &model.FollowingTags{}
)
convey.Convey("decode", t, func(cv convey.C) {
err := d.decode(src, v)
cv.Convey("Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoMonitorCache(t *testing.T) {
var (
c = context.Background()
mid = int64(0)
)
convey.Convey("MonitorCache", t, func(cv convey.C) {
exist, err := d.MonitorCache(c, mid)
cv.Convey("Then err should be nil.exist should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(exist, convey.ShouldNotBeNil)
})
})
}
func TestDaoSetMonitorCache(t *testing.T) {
var (
c = context.Background()
mid = int64(0)
)
convey.Convey("SetMonitorCache", t, func(cv convey.C) {
err := d.SetMonitorCache(c, mid)
cv.Convey("Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoDelMonitorCache(t *testing.T) {
var (
c = context.Background()
mid = int64(0)
)
convey.Convey("DelMonitorCache", t, func(cv convey.C) {
err := d.DelMonitorCache(c, mid)
cv.Convey("Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoLoadMonitorCache(t *testing.T) {
var (
c = context.Background()
mids = []int64{}
)
convey.Convey("LoadMonitorCache", t, func(cv convey.C) {
err := d.LoadMonitorCache(c, mids)
cv.Convey("Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoTodayNotifyCountCache(t *testing.T) {
var (
c = context.Background()
mid = int64(0)
)
convey.Convey("TodayNotifyCountCache", t, func(cv convey.C) {
notifyCount, err := d.TodayNotifyCountCache(c, mid)
cv.Convey("Then err should be nil.notifyCount should not be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
cv.So(notifyCount, convey.ShouldNotBeNil)
})
})
}
func TestDaoIncrTodayNotifyCountCache(t *testing.T) {
var (
c = context.Background()
mid = int64(0)
)
convey.Convey("IncrTodayNotifyCount", t, func(cv convey.C) {
err := d.IncrTodayNotifyCount(c, mid)
cv.Convey("Then err should be nil.", func(cv convey.C) {
cv.So(err, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,87 @@
package dao
import (
"context"
"go-common/app/service/main/relation/model"
"go-common/library/log"
"go-common/library/queue/databus/report"
"go-common/library/time"
)
// consts
const (
RelationLogID = 13
)
// AddFollowingLog is
func (d *Dao) AddFollowingLog(ctx context.Context, rl *model.RelationLog) {
d.addLog(ctx, RelationLogID, "log_add_following", rl)
d.addLog(ctx, RelationLogID, "log_follower_incr", rl.Reverse())
}
// DelFollowingLog is
func (d *Dao) DelFollowingLog(ctx context.Context, rl *model.RelationLog) {
d.addLog(ctx, RelationLogID, "log_del_following", rl)
d.addLog(ctx, RelationLogID, "log_follower_decr", rl.Reverse())
}
// DelFollowerLog is
func (d *Dao) DelFollowerLog(ctx context.Context, rl *model.RelationLog) {
d.addLog(ctx, RelationLogID, "log_del_follower", rl)
d.addLog(ctx, RelationLogID, "log_following_decr", rl.Reverse())
}
// AddWhisperLog is
func (d *Dao) AddWhisperLog(ctx context.Context, rl *model.RelationLog) {
d.addLog(ctx, RelationLogID, "log_add_whisper", rl)
d.addLog(ctx, RelationLogID, "log_whisper_follower_incr", rl.Reverse())
}
// DelWhisperLog is
func (d *Dao) DelWhisperLog(ctx context.Context, rl *model.RelationLog) {
d.addLog(ctx, RelationLogID, "log_del_whisper", rl)
d.addLog(ctx, RelationLogID, "log_whisper_follower_decr", rl.Reverse())
}
// AddBlackLog is
func (d *Dao) AddBlackLog(ctx context.Context, rl *model.RelationLog) {
d.addLog(ctx, RelationLogID, "log_add_black", rl)
d.addLog(ctx, RelationLogID, "log_black_incr", rl.Reverse())
}
// DelBlackLog is
func (d *Dao) DelBlackLog(ctx context.Context, rl *model.RelationLog) {
d.addLog(ctx, RelationLogID, "log_del_black", rl)
d.addLog(ctx, RelationLogID, "log_black_decr", rl.Reverse())
}
func (d *Dao) addLog(ctx context.Context, business int, action string, rl *model.RelationLog) {
t := time.Time(rl.Ts)
content := make(map[string]interface{}, len(rl.Content))
for k, v := range rl.Content {
content[k] = v
}
content["from_attr"] = rl.FromAttr
content["to_attr"] = rl.ToAttr
content["from_rev_attr"] = rl.FromRevAttr
content["to_rev_attr"] = rl.ToRevAttr
content["source"] = rl.Source
ui := &report.UserInfo{
Mid: rl.Mid,
Platform: "",
Build: 0,
Buvid: rl.Buvid,
Business: business,
Type: 0,
Oid: rl.Fid,
Action: action,
Ctime: t.Time(),
IP: rl.Ip,
// extra
Index: []interface{}{int64(rl.Source), 0, "", "", ""},
Content: content,
}
report.User(ui)
log.Info("add log to report: relationlog: %+v userinfo: %+v", rl, ui)
}

View File

@@ -0,0 +1,107 @@
package dao
import (
"context"
"go-common/app/service/main/relation/model"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoAddFollowingLog(t *testing.T) {
var (
ctx = context.Background()
rl = &model.RelationLog{}
)
convey.Convey("AddFollowingLog", t, func(cv convey.C) {
d.AddFollowingLog(ctx, rl)
cv.Convey("No return values", func(cv convey.C) {
})
})
}
func TestDaoDelFollowingLog(t *testing.T) {
var (
ctx = context.Background()
rl = &model.RelationLog{}
)
convey.Convey("DelFollowingLog", t, func(cv convey.C) {
d.DelFollowingLog(ctx, rl)
cv.Convey("No return values", func(cv convey.C) {
})
})
}
func TestDaoDelFollowerLog(t *testing.T) {
var (
ctx = context.Background()
rl = &model.RelationLog{}
)
convey.Convey("DelFollowerLog", t, func(cv convey.C) {
d.DelFollowerLog(ctx, rl)
cv.Convey("No return values", func(cv convey.C) {
})
})
}
func TestDaoAddWhisperLog(t *testing.T) {
var (
ctx = context.Background()
rl = &model.RelationLog{}
)
convey.Convey("AddWhisperLog", t, func(cv convey.C) {
d.AddWhisperLog(ctx, rl)
cv.Convey("No return values", func(cv convey.C) {
})
})
}
func TestDaoDelWhisperLog(t *testing.T) {
var (
ctx = context.Background()
rl = &model.RelationLog{}
)
convey.Convey("DelWhisperLog", t, func(cv convey.C) {
d.DelWhisperLog(ctx, rl)
cv.Convey("No return values", func(cv convey.C) {
})
})
}
func TestDaoAddBlackLog(t *testing.T) {
var (
ctx = context.Background()
rl = &model.RelationLog{}
)
convey.Convey("AddBlackLog", t, func(cv convey.C) {
d.AddBlackLog(ctx, rl)
cv.Convey("No return values", func(cv convey.C) {
})
})
}
func TestDaoDelBlackLog(t *testing.T) {
var (
ctx = context.Background()
rl = &model.RelationLog{}
)
convey.Convey("DelBlackLog", t, func(cv convey.C) {
d.DelBlackLog(ctx, rl)
cv.Convey("No return values", func(cv convey.C) {
})
})
}
func TestDaoaddLog(t *testing.T) {
var (
ctx = context.Background()
business = int(0)
action = ""
rl = &model.RelationLog{}
)
convey.Convey("addLog", t, func(cv convey.C) {
d.addLog(ctx, business, action, rl)
cv.Convey("No return values", func(cv convey.C) {
})
})
}