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,84 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"cache_test.go",
"dao.cache_test.go",
"dao_test.go",
"databus_test.go",
"log_test.go",
"mc.cache_test.go",
"mysql_coin_test.go",
"mysql_test.go",
"redis_test.go",
"relation_test.go",
"tag_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/coin/conf: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 = [
"cache.go",
"dao.cache.go",
"dao.go",
"databus.go",
"log.go",
"mc.cache.go",
"mysql.go",
"mysql_coin.go",
"redis.go",
"relation.go",
"tag.go",
],
importpath = "go-common/app/service/main/coin/dao",
tags = ["automanaged"],
deps = [
"//app/service/main/coin/api:go_default_library",
"//app/service/main/coin/conf:go_default_library",
"//app/service/main/coin/model:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/cache/redis:go_default_library",
"//library/database/elastic: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/net/metadata:go_default_library",
"//library/queue/databus:go_default_library",
"//library/queue/databus/report:go_default_library",
"//library/stat/prom:go_default_library",
"//library/sync/pipeline/fanout:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/golang.org/x/sync/singleflight: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,56 @@
package dao
import (
"context"
"fmt"
"strconv"
"time"
)
func countKey(mid int64) string {
return "uct2_" + strconv.FormatInt(mid, 10)
}
func (d *Dao) cacheSFUserCoin(mid int64) string {
return "uct_" + strconv.FormatInt(mid, 10)
}
func itemCoinKey(aid, tp int64) string {
return fmt.Sprintf("itc_%d_%d", tp, aid)
}
func (d *Dao) cacheSFItemCoin(aid int64, tp int64) string {
return fmt.Sprintf("itc_%d_%d", aid, tp)
}
func expKey(mid int64) (key string) {
now := time.Now()
key = fmt.Sprintf("exp_%d_%02d%02d", mid, now.Month(), now.Day())
return
}
//go:generate $GOPATH/src/go-common/app/tool/cache/mc
type _mc interface {
// get user coin count.
// mc: -key=countKey
CacheUserCoin(c context.Context, mid int64) (count float64, err error)
// set user coin count
// mc: -key=countKey -expire=d.mcExpire
AddCacheUserCoin(c context.Context, mid int64, count float64) (err error)
// mc: -key=itemCoinKey
CacheItemCoin(c context.Context, aid int64, tp int64) (count int64, err error)
// mc: -key=itemCoinKey -expire=d.mcExpire
AddCacheItemCoin(c context.Context, aid int64, count int64, tp int64) (err error)
// mc: -key=expKey -type=get
Exp(c context.Context, mid int64) (exp int64, err error)
// mc: -key=expKey -expire=d.expireExp
SetTodayExpCache(c context.Context, mid int64, exp int64) (err error)
}
//go:generate $GOPATH/src/go-common/app/tool/cache/gen
type _cache interface {
// cache: -nullcache=-1 -check_null_code=$==-1 -singleflight=true
UserCoin(c context.Context, mid int64) (count float64, err error)
// cache: -nullcache=-1 -check_null_code=$==-1 -singleflight=true
ItemCoin(c context.Context, aid int64, tp int64) (count int64, err error)
}

View File

@@ -0,0 +1,69 @@
package dao
import (
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaocountKey(t *testing.T) {
var (
mid = int64(123)
)
convey.Convey("countKey", t, func(ctx convey.C) {
p1 := countKey(mid)
ctx.Convey("p1 should not be nil", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeEmpty)
})
})
}
func TestDaocacheSFUserCoin(t *testing.T) {
var (
mid = int64(123)
)
convey.Convey("cacheSFUserCoin", t, func(ctx convey.C) {
p1 := d.cacheSFUserCoin(mid)
ctx.Convey("p1 should not be nil", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeEmpty)
})
})
}
func TestDaoitemCoinKey(t *testing.T) {
var (
aid = int64(1)
tp = int64(60)
)
convey.Convey("itemCoinKey", t, func(ctx convey.C) {
p1 := itemCoinKey(aid, tp)
ctx.Convey("p1 should not be nil", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeEmpty)
})
})
}
func TestDaocacheSFItemCoin(t *testing.T) {
var (
aid = int64(1)
tp = int64(60)
)
convey.Convey("cacheSFItemCoin", t, func(ctx convey.C) {
p1 := d.cacheSFItemCoin(aid, tp)
ctx.Convey("p1 should not be nil", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeEmpty)
})
})
}
func TestDaoexpKey(t *testing.T) {
var (
mid = int64(123)
)
convey.Convey("expKey", t, func(ctx convey.C) {
key := expKey(mid)
ctx.Convey("key should not be nil", func(ctx convey.C) {
ctx.So(key, convey.ShouldNotBeEmpty)
})
})
}

View File

@@ -0,0 +1,107 @@
// Code generated by $GOPATH/src/go-common/app/tool/cache/gen. DO NOT EDIT.
/*
Package dao is a generated cache proxy package.
It is generated from:
type _cache interface {
// cache: -nullcache=-1 -check_null_code=$==-1 -singleflight=true
UserCoin(c context.Context, mid int64) (count float64, err error)
// cache: -nullcache=-1 -check_null_code=$==-1 -singleflight=true
ItemCoin(c context.Context, aid int64, tp int64) (count int64, err error)
}
*/
package dao
import (
"context"
"go-common/library/stat/prom"
"golang.org/x/sync/singleflight"
)
var _ _cache
var cacheSingleFlights = [2]*singleflight.Group{{}, {}}
// UserCoin get data from cache if miss will call source method, then add to cache.
func (d *Dao) UserCoin(c context.Context, id int64) (res float64, err error) {
addCache := true
res, err = d.CacheUserCoin(c, id)
if err != nil {
addCache = false
err = nil
}
defer func() {
if res == -1 {
res = 0
}
}()
if res != 0 {
prom.CacheHit.Incr("UserCoin")
return
}
var rr interface{}
sf := d.cacheSFUserCoin(id)
rr, err, _ = cacheSingleFlights[0].Do(sf, func() (r interface{}, e error) {
prom.CacheMiss.Incr("UserCoin")
r, e = d.RawUserCoin(c, id)
return
})
res = rr.(float64)
if err != nil {
return
}
miss := res
if miss == 0 {
miss = -1
}
if !addCache {
return
}
d.cache.Do(c, func(c context.Context) {
d.AddCacheUserCoin(c, id, miss)
})
return
}
// ItemCoin get data from cache if miss will call source method, then add to cache.
func (d *Dao) ItemCoin(c context.Context, id int64, tp int64) (res int64, err error) {
addCache := true
res, err = d.CacheItemCoin(c, id, tp)
if err != nil {
addCache = false
err = nil
}
defer func() {
if res == -1 {
res = 0
}
}()
if res != 0 {
prom.CacheHit.Incr("ItemCoin")
return
}
var rr interface{}
sf := d.cacheSFItemCoin(id, tp)
rr, err, _ = cacheSingleFlights[1].Do(sf, func() (r interface{}, e error) {
prom.CacheMiss.Incr("ItemCoin")
r, e = d.RawItemCoin(c, id, tp)
return
})
res = rr.(int64)
if err != nil {
return
}
miss := res
if miss == 0 {
miss = -1
}
if !addCache {
return
}
d.cache.Do(c, func(c context.Context) {
d.AddCacheItemCoin(c, id, miss, tp)
})
return
}

View File

@@ -0,0 +1,41 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoUserCoin(t *testing.T) {
var (
c = context.TODO()
id = int64(123)
)
convey.Convey("UserCoin", t, func(ctx convey.C) {
res, err := d.UserCoin(c, id)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
ctx.Convey("res should not be nil", func(ctx convey.C) {
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoItemCoin(t *testing.T) {
var (
c = context.TODO()
id = int64(123)
tp = int64(60)
)
convey.Convey("ItemCoin", t, func(ctx convey.C) {
res, err := d.ItemCoin(c, id, tp)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
ctx.Convey("res should not be nil", func(ctx convey.C) {
ctx.So(res, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,83 @@
package dao
import (
"context"
"time"
"go-common/app/service/main/coin/conf"
"go-common/app/service/main/coin/model"
"go-common/library/cache/memcache"
"go-common/library/cache/redis"
"go-common/library/database/elastic"
"go-common/library/database/sql"
bm "go-common/library/net/http/blademaster"
"go-common/library/queue/databus"
"go-common/library/stat/prom"
"go-common/library/sync/pipeline/fanout"
)
// Dao dao config.
type Dao struct {
c *conf.Config
// databus stat
stat *databus.Databus
// coin
coin *sql.DB
//http
httpClient *bm.Client
// databus
dbBigData *databus.Databus
// databus for coin-job
dbCoinJob *databus.Databus
// redis
redis *redis.Pool
expireAdded int32
expireExp int32
// tag url
tagURI string
mc *memcache.Pool
mcExpire int32
cache *fanout.Fanout
Businesses map[int64]*model.Business
BusinessNames map[string]*model.Business
es *elastic.Elastic
}
// New new a Dao and return.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
coin: sql.NewMySQL(c.DB.Coin),
httpClient: bm.NewClient(c.HTTPClient),
tagURI: c.TagURL,
redis: redis.NewPool(c.Redis.Config),
mc: memcache.NewPool(c.Memcache.Config),
mcExpire: int32(time.Duration(c.Memcache.Expire) / time.Second),
expireExp: int32(time.Duration(c.Memcache.ExpExpire) / time.Second),
dbBigData: databus.New(c.DbBigData),
dbCoinJob: databus.New(c.DbCoinJob),
stat: databus.New(c.Stat.Databus),
expireAdded: int32(time.Duration(c.Redis.Expire) / time.Second),
cache: fanout.New("cache", fanout.Buffer(10240)),
Businesses: make(map[int64]*model.Business),
BusinessNames: make(map[string]*model.Business),
es: elastic.NewElastic(nil),
}
if len(c.Businesses) > 0 {
for _, b := range c.Businesses {
d.Businesses[b.ID] = b
d.BusinessNames[b.Name] = b
}
}
return
}
// PromError .
func PromError(name string) {
prom.BusinessErrCount.Incr(name)
}
// Ping check service health.
func (dao *Dao) Ping(c context.Context) (err error) {
return dao.coin.Ping(c)
}

View File

@@ -0,0 +1,47 @@
package dao
import (
"flag"
"os"
"strings"
"testing"
"go-common/app/service/main/coin/conf"
"gopkg.in/h2non/gock.v1"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.account.coin-service")
flag.Set("conf_appid", "coin-service")
flag.Set("conf_token", "G1Rp73FzNnV0k2EdGdL7BZO5YL49n1Mt")
flag.Set("tree_id", "2131")
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/coin-service-test.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
d.httpClient.SetTransport(gock.DefaultTransport)
m.Run()
os.Exit(0)
}
func httpMock(method, url string) *gock.Request {
r := gock.New(url)
r.Method = strings.ToUpper(method)
return r
}

View File

@@ -0,0 +1,57 @@
package dao
import (
"context"
"strconv"
"time"
"go-common/library/log"
)
// PubBigData pub msg into databus.
func (d *Dao) PubBigData(c context.Context, aid int64, msg interface{}) (err error) {
key := strconv.FormatInt(aid, 10)
if err = d.dbBigData.Send(c, key, msg); err != nil {
log.Error("dbBigData.Pub(%s, %v) error (%v)", key, msg, err)
PromError("dbus:PubBigData")
}
return
}
// PubCoinJob pub job msg into databus.
func (d *Dao) PubCoinJob(c context.Context, aid int64, msg interface{}) (err error) {
key := strconv.FormatInt(aid, 10)
for i := 0; i < 3; i++ {
if err = d.dbCoinJob.Send(c, key, msg); err != nil {
log.Error("d.dbCoinJob.Pub(%s, %v) error (%v) times: %v", key, msg, err, i+1)
PromError("dbus:PubCoinJob")
time.Sleep(time.Millisecond * 50)
continue
}
break
}
return
}
// PubStat pub stat msg into databus.
func (d *Dao) PubStat(c context.Context, aid, tp, count int64) (err error) {
var s = &struct {
Type string `json:"type"`
ID int64 `json:"id"`
Count int64 `json:"count"`
Timestamp int64 `json:"timestamp"`
}{
ID: aid,
Count: count,
Timestamp: time.Now().Unix(),
}
// double write new databus.
if b, ok := d.Businesses[tp]; ok {
s.Type = b.Name
if err = d.stat.Send(c, strconv.FormatInt(aid, 10), s); err != nil {
log.Error("d.stat.Pub(%+v) error(%v)", s, err)
PromError("dbus:stat")
}
}
return
}

View File

@@ -0,0 +1,51 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoPubBigData(t *testing.T) {
var (
c = context.TODO()
aid = int64(1)
msg = interface{}("PubBigData")
)
convey.Convey("PubBigData", t, func(ctx convey.C) {
err := d.PubBigData(c, aid, msg)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoPubCoinJob(t *testing.T) {
var (
c = context.TODO()
aid = int64(1)
msg = interface{}("PubCoinJob")
)
convey.Convey("PubCoinJob", t, func(ctx convey.C) {
err := d.PubCoinJob(c, aid, msg)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoPubStat(t *testing.T) {
var (
c = context.TODO()
aid = int64(1)
tp = int64(2)
count = int64(10)
)
convey.Convey("PubStat", t, func(ctx convey.C) {
err := d.PubStat(c, aid, tp, count)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,73 @@
package dao
import (
"context"
"encoding/json"
"time"
pb "go-common/app/service/main/coin/api"
"go-common/app/service/main/coin/model"
"go-common/library/database/elastic"
"go-common/library/log"
"go-common/library/queue/databus/report"
)
// AddLog .
func (d *Dao) AddLog(mid, ts int64, from, to float64, reason, ip, operator string, oid int64, typ int) {
report.User(&report.UserInfo{
Mid: mid,
Business: model.ReportType,
IP: ip,
Type: typ,
Ctime: time.Unix(ts, 0),
Index: []interface{}{operator},
Oid: oid,
Content: map[string]interface{}{
"from": int64(from * _multi),
"to": int64(to * _multi),
"reason": reason,
},
})
}
// CoinLog .
func (d *Dao) CoinLog(c context.Context, mid int64) (ls []*pb.ModelLog, err error) {
t := time.Now()
from := t.Add(-time.Hour * 24 * 7)
var res struct {
Page struct {
Num int `json:"num"`
Size int `json:"size"`
Total int `json:"total"`
} `json:"page"`
Result []*report.UserActionLog `json:"result"`
}
err = d.es.NewRequest("log_user_action").
IndexByTime("log_user_action_21", elastic.IndexTypeWeek, from, time.Now()).
WhereEq("mid", mid).
WhereRange("ctime", from.Format("2006-01-02 15:04:05"), "", elastic.RangeScopeLcRc).
Pn(1).Ps(1000).Order("ctime", elastic.OrderDesc).
Scan(c, &res)
if err != nil {
log.Error("coineslog mid: %v, err: %v", mid, err)
PromError("log:es")
return
}
for _, r := range res.Result {
ts, _ := time.ParseInLocation("2006-01-02 15:04:05", r.Ctime, time.Local)
var ex struct {
From int64
To int64
Reason string
}
json.Unmarshal([]byte(r.Extra), &ex)
ls = append(ls, &pb.ModelLog{
From: float64(ex.From) / _multi,
To: float64(ex.To) / _multi,
IP: r.IP,
Desc: ex.Reason,
TimeStamp: ts.Unix(),
})
}
return
}

View File

@@ -0,0 +1,25 @@
package dao
import (
"context"
"testing"
"time"
. "github.com/smartystreets/goconvey/convey"
)
func TestAddLog(t *testing.T) {
Convey("log", t, func() {
d.AddLog(1, time.Now().Unix(), 1, 2, "test", "127.0.0.1", "", 0, 0)
})
}
func TestLogs(t *testing.T) {
var (
c = context.TODO()
)
Convey("work", t, func() {
_, err := d.CoinLog(c, 88888929)
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,177 @@
// Code generated by $GOPATH/src/go-common/app/tool/cache/mc. DO NOT EDIT.
/*
Package dao is a generated mc cache package.
It is generated from:
type _mc interface {
// get user coin count.
// mc: -key=countKey
CacheUserCoin(c context.Context, mid int64) (count float64, err error)
// set user coin count
// mc: -key=countKey -expire=d.mcExpire
AddCacheUserCoin(c context.Context, mid int64, count float64) (err error)
// mc: -key=itemCoinKey
CacheItemCoin(c context.Context, aid int64, tp int64) (count int64, err error)
// mc: -key=itemCoinKey -expire=d.mcExpire
AddCacheItemCoin(c context.Context, aid int64, count int64, tp int64) (err error)
// mc: -key=expKey -type=get
Exp(c context.Context, mid int64) (exp int64, err error)
// mc: -key=expKey -expire=d.expireExp
SetTodayExpCache(c context.Context, mid int64, exp int64) (err error)
}
*/
package dao
import (
"context"
"fmt"
"strconv"
"go-common/library/cache/memcache"
"go-common/library/log"
"go-common/library/stat/prom"
)
var _ _mc
// CacheUserCoin get user coin count.
func (d *Dao) CacheUserCoin(c context.Context, id int64) (res float64, err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := countKey(id)
reply, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:CacheUserCoin")
log.Errorv(c, log.KV("CacheUserCoin", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
var v string
err = conn.Scan(reply, &v)
if err != nil {
prom.BusinessErrCount.Incr("mc:CacheUserCoin")
log.Errorv(c, log.KV("CacheUserCoin", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
r, err := strconv.ParseFloat(v, 64)
if err != nil {
prom.BusinessErrCount.Incr("mc:CacheUserCoin")
log.Errorv(c, log.KV("CacheUserCoin", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
res = float64(r)
return
}
// AddCacheUserCoin set user coin count
func (d *Dao) AddCacheUserCoin(c context.Context, id int64, val float64) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := countKey(id)
bs := []byte(strconv.FormatFloat(val, 'E', -1, 64))
item := &memcache.Item{Key: key, Value: bs, Expiration: d.mcExpire, Flags: memcache.FlagRAW}
if err = conn.Set(item); err != nil {
prom.BusinessErrCount.Incr("mc:AddCacheUserCoin")
log.Errorv(c, log.KV("AddCacheUserCoin", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// CacheItemCoin get data from mc
func (d *Dao) CacheItemCoin(c context.Context, id int64, tp int64) (res int64, err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := itemCoinKey(id, tp)
reply, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:CacheItemCoin")
log.Errorv(c, log.KV("CacheItemCoin", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
var v string
err = conn.Scan(reply, &v)
if err != nil {
prom.BusinessErrCount.Incr("mc:CacheItemCoin")
log.Errorv(c, log.KV("CacheItemCoin", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
r, err := strconv.ParseInt(v, 10, 64)
if err != nil {
prom.BusinessErrCount.Incr("mc:CacheItemCoin")
log.Errorv(c, log.KV("CacheItemCoin", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
res = int64(r)
return
}
// AddCacheItemCoin Set data to mc
func (d *Dao) AddCacheItemCoin(c context.Context, id int64, val int64, tp int64) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := itemCoinKey(id, tp)
bs := []byte(strconv.FormatInt(int64(val), 10))
item := &memcache.Item{Key: key, Value: bs, Expiration: d.mcExpire, Flags: memcache.FlagRAW}
if err = conn.Set(item); err != nil {
prom.BusinessErrCount.Incr("mc:AddCacheItemCoin")
log.Errorv(c, log.KV("AddCacheItemCoin", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// Exp get data from mc
func (d *Dao) Exp(c context.Context, id int64) (res int64, err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := expKey(id)
reply, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:Exp")
log.Errorv(c, log.KV("Exp", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
var v string
err = conn.Scan(reply, &v)
if err != nil {
prom.BusinessErrCount.Incr("mc:Exp")
log.Errorv(c, log.KV("Exp", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
r, err := strconv.ParseInt(v, 10, 64)
if err != nil {
prom.BusinessErrCount.Incr("mc:Exp")
log.Errorv(c, log.KV("Exp", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
res = int64(r)
return
}
// SetTodayExpCache Set data to mc
func (d *Dao) SetTodayExpCache(c context.Context, id int64, val int64) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := expKey(id)
bs := []byte(strconv.FormatInt(int64(val), 10))
item := &memcache.Item{Key: key, Value: bs, Expiration: d.expireExp, Flags: memcache.FlagRAW}
if err = conn.Set(item); err != nil {
prom.BusinessErrCount.Incr("mc:SetTodayExpCache")
log.Errorv(c, log.KV("SetTodayExpCache", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}

View File

@@ -0,0 +1,100 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoCacheUserCoin(t *testing.T) {
var (
c = context.TODO()
id = int64(1)
)
convey.Convey("CacheUserCoin", t, func(ctx convey.C) {
res, err := d.CacheUserCoin(c, id)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
ctx.Convey("res should not be nil", func(ctx convey.C) {
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoAddCacheUserCoin(t *testing.T) {
var (
c = context.TODO()
id = int64(10)
val = float64(10)
)
convey.Convey("AddCacheUserCoin", t, func(ctx convey.C) {
err := d.AddCacheUserCoin(c, id, val)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoCacheItemCoin(t *testing.T) {
var (
c = context.TODO()
id = int64(1)
tp = int64(60)
)
convey.Convey("CacheItemCoin", t, func(ctx convey.C) {
res, err := d.CacheItemCoin(c, id, tp)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
ctx.Convey("res should not be nil", func(ctx convey.C) {
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoAddCacheItemCoin(t *testing.T) {
var (
c = context.TODO()
id = int64(1)
val = int64(10)
tp = int64(60)
)
convey.Convey("AddCacheItemCoin", t, func(ctx convey.C) {
err := d.AddCacheItemCoin(c, id, val, tp)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoExp(t *testing.T) {
var (
c = context.TODO()
id = int64(1)
)
convey.Convey("Exp", t, func(ctx convey.C) {
res, err := d.Exp(c, id)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
ctx.Convey("res should not be nil", func(ctx convey.C) {
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDaoSetTodayExpCache(t *testing.T) {
var (
c = context.TODO()
id = int64(1)
val = int64(10)
)
convey.Convey("SetTodayExpCache", t, func(ctx convey.C) {
err := d.SetTodayExpCache(c, id, val)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,267 @@
package dao
import (
"context"
"fmt"
"time"
pb "go-common/app/service/main/coin/api"
"go-common/library/database/sql"
"go-common/library/log"
)
const (
_dayOfEachMonth = 25
_sharding = 50
_getTotalCoins = "SELECT aid,type,SUM(multiply) FROM coin_member_%d WHERE mid = ? GROUP BY aid,type ORDER BY cid desc LIMIT 20"
_getTotalCoinsByMid = "SELECT IFNULL(SUM(multiply),0) FROM coin_member_%d WHERE mid=? AND aid=? AND type=?"
_getTotalCoinsByMidAndUpMid = "SELECT IFNULL(coin_count,0) FROM coin_user_count_%02d WHERE mid=? AND up_mid=?"
_getCoinCount = "SELECT IFNULL(count,0) FROM coin_count WHERE aid=? AND type=?"
_updateCoinCount = "INSERT INTO coin_count(aid, type, `count`, ctime, mtime) VALUES(?,?,?,?,?) ON DUPLICATE KEY UPDATE count=count+?,mtime=?"
_insertCoinArchive = "INSERT LOW_PRIORITY INTO coin_archive_%d (aid,type,mid,timestamp,multiply) VALUES (?,?,?,?,?)"
_insertCoinMember = "INSERT LOW_PRIORITY INTO coin_member_%d (aid,type,mid,timestamp,multiply,up_mid) VALUES (?,?,?,?,?,?)"
_updateCoinMemberCount = "INSERT INTO coin_user_count_%02d(mid, up_mid, coin_count, ctime) VALUES(?,?,?,?) ON DUPLICATE KEY UPDATE coin_count=coin_count+?"
_getMemberVideoList = "SELECT aid,ip,timestamp,multiply FROM coin_member_%d WHERE mid = ? AND type=? AND timestamp > ? ORDER BY cid DESC LIMIT ?"
// coin settle
_hitSettlePeriod = "SELECT id FROM coin_settle_period WHERE to_year=? AND to_month=?"
_updateSettleBD = "UPDATE coin_settle_%d SET exp_sub=?,description=?,itime=?,mtime=? WHERE aid=? and type=?" // update for bigdata
_updateArchiveCoinsBD = "UPDATE coin_count SET count=?, mtime=? WHERE aid=? AND type=?" // update for bigdata
)
func (dao *Dao) midHit(mid int64) int64 {
return mid % _sharding
}
func (dao *Dao) aidHit(aid int64) int64 {
return aid % _sharding
}
func (dao *Dao) hitCoinPeriod(c context.Context, now time.Time) (id int64, err error) {
year, month, day := now.Year(), now.Month(), now.Day()
if now.Day() < _dayOfEachMonth {
err = fmt.Errorf("opreation from bigdata must after the %dth of each month, today is (%d)", _dayOfEachMonth, day)
log.Error("%v", err)
return
}
row := dao.coin.QueryRow(c, _hitSettlePeriod, year, month)
if err != nil {
log.Error("dao.hitCoinPeriodStmt.QueryRow(%d, %d) error(%v)", year, month, err)
return
}
if err = row.Scan(&id); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
return
}
if id == 0 {
err = fmt.Errorf("zero id at(%s)", now.String())
log.Error("%v", err)
}
return
}
// UpdateCoinSettleBD update table coin_settle_%d.
func (dao *Dao) UpdateCoinSettleBD(c context.Context, aid, tp, expSub int64, describe string, now time.Time) (affect int64, err error) {
id, err := dao.hitCoinPeriod(c, now)
if err != nil {
return
}
sqlStr := fmt.Sprintf(_updateSettleBD, id)
result, err := dao.coin.Exec(c, sqlStr, expSub, describe, now, now, aid, tp)
if err != nil {
log.Error("dao.coin.Exec(%s, %d, %s, %v, %v, %d) error(%v)", sqlStr, expSub, describe, now, now, aid, err)
return
}
affect, err = result.LastInsertId()
return
}
// CoinList return video list of coin added in one month
func (dao *Dao) CoinList(c context.Context, mid, tp, ts, size int64) (rcs []*pb.ModelList, err error) {
var rows *sql.Rows
if rows, err = dao.coin.Query(c, fmt.Sprintf(_getMemberVideoList, dao.midHit(mid)), mid, tp, ts, size); err != nil {
log.Error("dao.getMemberVideoList.Query() error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
var rc = &pb.ModelList{}
if err = rows.Scan(&rc.Aid, &rc.IP, &rc.Ts, &rc.Number); err != nil {
log.Error("row.Scan(),error(%v)", err)
rcs = nil
return
}
rcs = append(rcs, rc)
}
return
}
// CoinsAddedByMid get coin added by mid of aid&tp.
func (dao *Dao) CoinsAddedByMid(c context.Context, mid, aid, tp int64) (added int64, err error) {
row := dao.coin.QueryRow(c, fmt.Sprintf(_getTotalCoinsByMid, dao.midHit(mid)), mid, aid, tp)
if err = row.Scan(&added); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
PromError("mysql:CoinsAddedByMid")
log.Errorv(c,
log.KV("log", "row.Scan"),
log.KV("err", err),
log.KV("mid", mid),
log.KV("aid", aid),
)
}
}
return
}
// AddedCoins get coins added to up_mid.
func (dao *Dao) AddedCoins(c context.Context, mid, upMid int64) (added int64, err error) {
row := dao.coin.QueryRow(c, fmt.Sprintf(_getTotalCoinsByMidAndUpMid, dao.midHit(mid)), mid, upMid)
if err = row.Scan(&added); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// UserCoinsAdded get user coin added.
func (dao *Dao) UserCoinsAdded(c context.Context, mid int64) (addeds map[int64]int64, err error) {
var rows *sql.Rows
addeds = make(map[int64]int64)
if rows, err = dao.coin.Query(c, fmt.Sprintf(_getTotalCoins, dao.midHit(mid)), mid); err != nil {
log.Errorv(c,
log.KV("log", "dao.getTotalCoins"),
log.KV("err", err),
log.KV("mid", mid),
)
PromError("db:UserCoinsAdded")
return
}
defer rows.Close()
for rows.Next() {
var (
added, aid, tp int64
)
if err = rows.Scan(&aid, &tp, &added); err != nil {
log.Errorv(c,
log.KV("log", "row.Scan"),
log.KV("err", err),
log.KV("mid", mid),
)
PromError("db:UserCoinsAdded")
addeds = nil
return
}
addeds[hashField(aid, tp)] = added
}
return
}
// InsertCoinArchive .
func (dao *Dao) InsertCoinArchive(c context.Context, aid, tp, mid, timestamp, multiply int64) (err error) {
if _, err = dao.coin.Exec(c, fmt.Sprintf(_insertCoinArchive, dao.aidHit(aid)), aid, tp, mid, timestamp, multiply); err != nil {
log.Errorv(c,
log.KV("log", "coin.Exec"),
log.KV("err", err),
log.KV("mid", mid),
log.KV("aid", aid),
)
PromError("db:InsertCoinArchive")
}
return
}
// InsertCoinMember .
func (dao *Dao) InsertCoinMember(c context.Context, aid, tp, mid, timestamp, multiply int64, upMid int64) (err error) {
if _, err = dao.coin.Exec(c, fmt.Sprintf(_insertCoinMember, dao.midHit(mid)), aid, tp, mid, timestamp, multiply, upMid); err != nil {
log.Errorv(c,
log.KV("log", "coin.Exec"),
log.KV("err", err),
log.KV("mid", mid),
log.KV("aid", aid),
)
PromError("db:InsertCoinMember")
}
return
}
// UpdateItemCoinCount update coin_count.
func (dao *Dao) UpdateItemCoinCount(c context.Context, aid, tp, count int64) (err error) {
now := time.Now()
if _, err = dao.coin.Exec(c, _updateCoinCount, aid, tp, count, now, now, count, now); err != nil {
log.Errorv(c,
log.KV("log", "UpdateItemCoinCount("),
log.KV("err", err),
log.KV("count", count),
log.KV("aid", aid),
)
PromError("db:UpdateItemCoinCount")
}
return
}
// RawItemCoin get count by aid.
func (dao *Dao) RawItemCoin(c context.Context, aid, tp int64) (count int64, err error) {
row := dao.coin.QueryRow(c, _getCoinCount, aid, tp)
if err = row.Scan(&count); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Errorv(c,
log.KV("log", "row.Scan"),
log.KV("err", err),
)
PromError("db:RawItemCoin")
}
}
return
}
// UpdateCoinMemberCount for archive
func (dao *Dao) UpdateCoinMemberCount(c context.Context, mid, upMid, count int64) (err error) {
if _, err = dao.coin.Exec(c, fmt.Sprintf(_updateCoinMemberCount, dao.midHit(mid)), mid, upMid, count, time.Now(), count); err != nil {
log.Errorv(c,
log.KV("log", "updateCoinMemberCount"),
log.KV("mid", mid),
log.KV("upmid", upMid),
log.KV("count", count),
log.KV("err", err),
)
PromError("db:UpdateCoinMemberCount")
}
return
}
// BeginTran begin a tx.
func (dao *Dao) BeginTran(c context.Context) (t *sql.Tx, err error) {
t, err = dao.coin.Begin(c)
if err != nil {
PromError("db:BeginTran")
log.Errorv(c,
log.KV("log", "d.BeginTran"),
log.KV("err", err),
)
}
return
}
// UpdateItemCoins update table coin_archive
func (dao *Dao) UpdateItemCoins(c context.Context, aid, tp, coins int64, now time.Time) (affect int64, err error) {
if err != nil {
return
}
result, err := dao.coin.Exec(c, _updateArchiveCoinsBD, coins, now, aid, tp)
if err != nil {
log.Error("dao.coin.Exec(%s, %d, %s, %d) error(%v)", _updateArchiveCoinsBD, coins, now, aid, err)
return
}
affect, err = result.RowsAffected()
return
}

View File

@@ -0,0 +1,72 @@
package dao
import (
"context"
"database/sql"
"fmt"
xsql "go-common/library/database/sql"
"go-common/library/log"
)
const (
_shard = 50
_multi = 100
_selCoin = "SELECT coins FROM coins_%02d where mid=?"
_txUpdateCoins = "INSERT INTO coins_%02d(mid,coins) VALUES(?,?) ON DUPLICATE KEY UPDATE coins=coins+?"
)
// UpdateCoin update user coins.
func (d *Dao) UpdateCoin(c context.Context, mid int64, coin float64) (err error) {
count := int64(coin * _multi)
if _, err = d.coin.Exec(c, fmt.Sprintf(_txUpdateCoins, mid%_shard), mid, count, count); err != nil {
PromError("db:UpdateCoin")
log.Errorv(c, log.KV("log", "UpdateCoin"), log.KV("err", err))
return
}
return
}
// TxUpdateCoins update coins
func (d *Dao) TxUpdateCoins(c context.Context, tx *xsql.Tx, mid int64, coin float64) (err error) {
count := int64(coin * _multi)
_, err = tx.Exec(fmt.Sprintf(_txUpdateCoins, mid%_shard), mid, count, count)
if err != nil {
PromError("db:TxUpdateCoins")
log.Errorv(c, log.KV("log", "TxUpdateCoins"), log.KV("err", err), log.KV("mid", mid))
return
}
return
}
// TxUserCoin tx user coin
func (d *Dao) TxUserCoin(c context.Context, tx *xsql.Tx, mid int64) (count float64, err error) {
var coin int64
row := tx.QueryRow(fmt.Sprintf(_selCoin, mid%_shard), mid)
if err = row.Scan(&coin); err != nil {
if err == sql.ErrNoRows {
err = nil
return
}
PromError("db:TxUserCoin")
log.Errorv(c, log.KV("log", "TxUserCoin"), log.KV("err", err))
}
count = float64(coin) / _multi
return
}
// RawUserCoin get user coins.
func (d *Dao) RawUserCoin(c context.Context, mid int64) (res float64, err error) {
var count int64
row := d.coin.QueryRow(c, fmt.Sprintf(_selCoin, mid%_shard), mid)
if err = row.Scan(&count); err != nil {
if err == sql.ErrNoRows {
err = nil
return
}
PromError("db:Coins")
log.Errorv(c, log.KV("log", "Coins"), log.KV("err", err))
}
res = float64(count) / _multi
return
}

View File

@@ -0,0 +1,81 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoUpdateCoin(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
coin = float64(0)
)
convey.Convey("UpdateCoin", t, func(ctx convey.C) {
err := d.UpdateCoin(c, mid, coin)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoTxUpdateCoins(t *testing.T) {
var (
c = context.TODO()
tx, _ = d.BeginTran(c)
mid = int64(1)
coin = float64(20)
)
convey.Convey("TxUpdateCoins", t, func(ctx convey.C) {
err := d.TxUpdateCoins(c, tx, mid, coin)
ctx.Convey("Error should be nil", func(ctx convey.C) {
if err != nil {
tx.Rollback()
}
ctx.So(err, convey.ShouldBeNil)
tx.Commit()
})
})
}
func TestDaoTxUserCoin(t *testing.T) {
var (
c = context.TODO()
tx, _ = d.BeginTran(c)
mid = int64(0)
)
convey.Convey("TxUserCoin", t, func(ctx convey.C) {
count, err := d.TxUserCoin(c, tx, mid)
ctx.Convey("Error should be nil", func(ctx convey.C) {
if err != nil {
tx.Rollback()
}
ctx.So(err, convey.ShouldBeNil)
})
ctx.Convey("count should not be nil", func(ctx convey.C) {
if count != 0 {
tx.Commit()
}
ctx.So(count, convey.ShouldNotBeNil)
})
})
}
func TestDaoRawUserCoin(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
)
convey.Convey("RawUserCoin", t, func(ctx convey.C) {
res, err := d.RawUserCoin(c, mid)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
ctx.Convey("res should not be nil", func(ctx convey.C) {
ctx.So(res, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,259 @@
package dao
import (
"context"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestDaomidHit(t *testing.T) {
var (
mid = int64(0)
)
convey.Convey("midHit", t, func(ctx convey.C) {
p1 := d.midHit(mid)
ctx.Convey("p1 should not be nil", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoaidHit(t *testing.T) {
var (
aid = int64(0)
)
convey.Convey("aidHit", t, func(ctx convey.C) {
p1 := d.aidHit(aid)
ctx.Convey("p1 should not be nil", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaohitCoinPeriod(t *testing.T) {
var (
c = context.TODO()
now, _ = time.Parse("2006-01-02 15:04:05", "2018-01-26 00:00:00")
)
convey.Convey("hitCoinPeriod", t, func(ctx convey.C) {
id, err := d.hitCoinPeriod(c, now)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
ctx.Convey("id should not be nil", func(ctx convey.C) {
ctx.So(id, convey.ShouldNotBeNil)
})
})
}
func TestDaoUpdateCoinSettleBD(t *testing.T) {
var (
c = context.TODO()
aid = int64(4051951)
tp = int64(1)
expSub = int64(20)
describe = "UpdateCoinSettleBD"
now = time.Now()
)
convey.Convey("UpdateCoinSettleBD", t, func(ctx convey.C) {
currentYear, currentMonth, _ := now.Date()
curTime := now.Location()
firstDay := time.Date(currentYear, currentMonth, 1, 0, 0, 0, 0, curTime)
now = firstDay.AddDate(0, 1, -1)
affect, err := d.UpdateCoinSettleBD(c, aid, tp, expSub, describe, now)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
ctx.Convey("affect should not be nil", func(ctx convey.C) {
ctx.So(affect, convey.ShouldNotBeNil)
})
})
}
func TestDaoCoinList(t *testing.T) {
var (
c = context.TODO()
mid = int64(4051951)
tp = int64(1)
ts = int64(time.Now().Unix())
size = int64(1024)
)
convey.Convey("CoinList", t, func(ctx convey.C) {
_, err := d.CoinList(c, mid, tp, ts, size)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
// ctx.Convey("rcs should not be nil", func(ctx convey.C) {
// ctx.So(rcs, convey.ShouldNotBeEmpty)
// })
})
}
func TestDaoCoinsAddedByMid(t *testing.T) {
var (
c = context.TODO()
mid = int64(4051951)
aid = int64(12)
tp = int64(20)
)
convey.Convey("CoinsAddedByMid", t, func(ctx convey.C) {
added, err := d.CoinsAddedByMid(c, mid, aid, tp)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
ctx.Convey("added should not be nil", func(ctx convey.C) {
ctx.So(added, convey.ShouldNotBeNil)
})
})
}
func TestDaoAddedCoins(t *testing.T) {
var (
c = context.TODO()
mid = int64(4051951)
upMid = int64(4051950)
)
convey.Convey("AddedCoins", t, func(ctx convey.C) {
added, err := d.AddedCoins(c, mid, upMid)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
ctx.Convey("added should not be nil", func(ctx convey.C) {
ctx.So(added, convey.ShouldNotBeNil)
})
})
}
func TestDaoUserCoinsAdded(t *testing.T) {
var (
c = context.TODO()
mid = int64(1)
)
convey.Convey("UserCoinsAdded", t, func(ctx convey.C) {
addeds, err := d.UserCoinsAdded(c, mid)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
ctx.Convey("addeds should not be nil", func(ctx convey.C) {
ctx.So(addeds, convey.ShouldNotBeNil)
})
})
}
func TestDaoInsertCoinArchive(t *testing.T) {
var (
c = context.TODO()
aid = int64(1)
tp = int64(21)
mid = int64(4051951)
timestamp = int64(time.Now().Unix())
multiply = int64(0)
)
convey.Convey("InsertCoinArchive", t, func(ctx convey.C) {
err := d.InsertCoinArchive(c, aid, tp, mid, timestamp, multiply)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoInsertCoinMember(t *testing.T) {
var (
c = context.TODO()
aid = int64(1)
tp = int64(2)
mid = int64(4051951)
timestamp = int64(time.Now().Unix())
multiply = int64(21)
upMid = int64(1)
)
convey.Convey("InsertCoinMember", t, func(ctx convey.C) {
err := d.InsertCoinMember(c, aid, tp, mid, timestamp, multiply, upMid)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoUpdateItemCoinCount(t *testing.T) {
var (
c = context.TODO()
aid = int64(0)
tp = int64(0)
count = int64(0)
)
convey.Convey("UpdateItemCoinCount", t, func(ctx convey.C) {
err := d.UpdateItemCoinCount(c, aid, tp, count)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoRawItemCoin(t *testing.T) {
var (
c = context.TODO()
aid = int64(0)
tp = int64(0)
)
convey.Convey("RawItemCoin", t, func(ctx convey.C) {
count, err := d.RawItemCoin(c, aid, tp)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
ctx.Convey("count should not be nil", func(ctx convey.C) {
ctx.So(count, convey.ShouldNotBeNil)
})
})
}
func TestDaoUpdateCoinMemberCount(t *testing.T) {
var (
c = context.TODO()
mid = int64(4051951)
upMid = int64(1)
count = int64(2)
)
convey.Convey("UpdateCoinMemberCount", t, func(ctx convey.C) {
err := d.UpdateCoinMemberCount(c, mid, upMid, count)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoBeginTran(t *testing.T) {
var (
c = context.TODO()
)
convey.Convey("BeginTran", t, func(ctx convey.C) {
no, err := d.BeginTran(c)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
ctx.Convey("no should not be nil", func(ctx convey.C) {
ctx.So(no, convey.ShouldNotBeNil)
})
})
}
func TestDaoUpdateItemCoins(t *testing.T) {
var (
c = context.TODO()
aid = int64(1)
tp = int64(20)
coins = int64(20)
now = time.Now()
)
convey.Convey("UpdateItemCoins", t, func(ctx convey.C) {
affect, err := d.UpdateItemCoins(c, aid, tp, coins, now)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
ctx.Convey("affect should not be nil", func(ctx convey.C) {
ctx.So(affect, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,142 @@
package dao
import (
"context"
"strconv"
"go-common/library/cache/redis"
"go-common/library/log"
)
const (
_addPrefix2 = "nca_"
)
func hashField(aid, tp int64) int64 {
return aid*1000 + tp
}
func addKey2(mid int64) (key string) {
key = _addPrefix2 + strconv.FormatInt(mid, 10)
return
}
// CoinsAddedCache get coin added of archive.
func (d *Dao) CoinsAddedCache(c context.Context, mid, aid, tp int64) (added int64, err error) {
conn := d.redis.Get(c)
defer conn.Close()
key := addKey2(mid)
if added, err = redis.Int64(conn.Do("HGET", key, hashField(aid, tp))); err != nil {
if err == redis.ErrNil {
err = nil
return
}
PromError("redis:CoinsAddedCache")
log.Errorv(c, log.KV("log", "redis.Do(HGET)"), log.KV("err", err), log.KV("mid", mid))
}
return
}
// SetCoinAddedCache set coin added of archive
func (d *Dao) SetCoinAddedCache(c context.Context, mid, aid, tp, count int64) (err error) {
conn := d.redis.Get(c)
defer conn.Close()
key := addKey2(mid)
defer func() {
if err != nil {
PromError("redis:SetCoinAddedCache")
log.Errorv(c,
log.KV("log", "s.coinDao.SetCoinAdded()"),
log.KV("mid", mid),
log.KV("aid", aid),
log.KV("err", err),
)
}
}()
if err = conn.Send("HSETNX", key, hashField(aid, tp), count); err != nil {
return
}
if err = conn.Send("EXPIRE", key, d.expireAdded); err != nil {
return
}
if err = conn.Flush(); err != nil {
return
}
if _, err = redis.Bool(conn.Receive()); err != nil {
return
}
conn.Receive()
return
}
// SetCoinAddedsCache multiset added cache
func (d *Dao) SetCoinAddedsCache(c context.Context, mid int64, counts map[int64]int64) (err error) {
if len(counts) == 0 {
// 空缓存
counts = map[int64]int64{-1: -1}
}
key := addKey2(mid)
conn := d.redis.Get(c)
defer conn.Close()
for field, count := range counts {
if err = conn.Send("HSETNX", key, field, count); err != nil {
log.Errorv(c,
log.KV("log", "conn.Send(HSETNX)"),
log.KV("err", err),
log.KV("mid", mid),
)
PromError("redis:SetCoinAddedsCache")
return
}
}
if err = conn.Send("EXPIRE", key, d.expireAdded); err != nil {
log.Errorv(c,
log.KV("log", "conn.Send(EXPIRE)"),
log.KV("err", err),
log.KV("mid", mid),
)
PromError("redis:SetCoinAddedsCache")
return
}
if err = conn.Flush(); err != nil {
log.Errorv(c, log.KV("log", "conn.Flush()"), log.KV("err", err), log.KV("mid", mid))
PromError("redis:SetCoinAddedsCache")
return
}
for i := 0; i < len(counts)+1; i++ {
if _, err = conn.Receive(); err != nil {
log.Errorv(c, log.KV("log", "conn.Recive()"), log.KV("err", err), log.KV("mid", mid))
PromError("redis:SetCoinAddedsCache")
return
}
}
return
}
// IncrCoinAddedCache Incr coin added
func (d *Dao) IncrCoinAddedCache(c context.Context, mid, aid, tp, count int64) (err error) {
conn := d.redis.Get(c)
defer conn.Close()
key := addKey2(mid)
if _, err = conn.Do("HINCRBY", key, hashField(aid, tp), count); err != nil {
PromError("redis:IncrCoinAdded")
log.Errorv(c, log.KV("log", "conn.Do(HINCRBY) error"), log.KV("err", err), log.KV("mid", mid), log.KV("aid", aid))
}
return
}
// ExpireCoinAdded set expire time for coinadded
func (d *Dao) ExpireCoinAdded(c context.Context, mid int64) (ok bool, err error) {
conn := d.redis.Get(c)
defer conn.Close()
key := addKey2(mid)
if ok, err = redis.Bool(conn.Do("EXPIRE", key, d.expireAdded)); err != nil {
if err == redis.ErrNil {
err = nil
return
}
PromError("redis:ExpireCoinAdded")
log.Errorv(c, log.KV("log", "conn.Do(EXPIRE)"), log.KV("err", err))
}
return
}

View File

@@ -0,0 +1,113 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaohashField(t *testing.T) {
var (
aid = int64(1)
tp = int64(1)
)
convey.Convey("hashField", t, func(ctx convey.C) {
p1 := hashField(aid, tp)
ctx.Convey("p1 should not be nil", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDaoaddKey2(t *testing.T) {
var (
mid = int64(123)
)
convey.Convey("addKey2", t, func(ctx convey.C) {
key := addKey2(mid)
ctx.Convey("key should not be nil", func(ctx convey.C) {
ctx.So(key, convey.ShouldNotBeNil)
})
})
}
func TestDaoCoinsAddedCache(t *testing.T) {
var (
c = context.TODO()
mid = int64(123)
aid = int64(1)
tp = int64(60)
)
convey.Convey("CoinsAddedCache", t, func(ctx convey.C) {
added, err := d.CoinsAddedCache(c, mid, aid, tp)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
ctx.Convey("added should not be nil", func(ctx convey.C) {
ctx.So(added, convey.ShouldNotBeNil)
})
})
}
func TestDaoSetCoinAddedCache(t *testing.T) {
var (
c = context.TODO()
mid = int64(123)
aid = int64(1)
tp = int64(60)
count = int64(20)
)
convey.Convey("SetCoinAddedCache", t, func(ctx convey.C) {
err := d.SetCoinAddedCache(c, mid, aid, tp, count)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoSetCoinAddedsCache(t *testing.T) {
var (
c = context.TODO()
mid = int64(123)
counts = map[int64]int64{10: 20, 20: 30, 30: 40}
)
convey.Convey("SetCoinAddedsCache", t, func(ctx convey.C) {
err := d.SetCoinAddedsCache(c, mid, counts)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoIncrCoinAddedCache(t *testing.T) {
var (
c = context.TODO()
mid = int64(123)
aid = int64(1)
tp = int64(60)
count = int64(20)
)
convey.Convey("IncrCoinAddedCache", t, func(ctx convey.C) {
err := d.IncrCoinAddedCache(c, mid, aid, tp, count)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoExpireCoinAdded(t *testing.T) {
var (
c = context.TODO()
mid = int64(123)
)
convey.Convey("ExpireCoinAdded", t, func(ctx convey.C) {
ok, err := d.ExpireCoinAdded(c, mid)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
ctx.Convey("ok should not be nil", func(ctx convey.C) {
ctx.So(ok, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,50 @@
package dao
import (
"context"
"net/url"
"strconv"
"go-common/library/ecode"
"go-common/library/net/metadata"
"github.com/pkg/errors"
)
const _passportURL = "http://passport.bilibili.co/intranet/acc/bindDetail"
// PassportDetail .
type PassportDetail struct {
BindEmail bool `json:"bind_email"`
BindTel bool `json:"bind_tel"`
Mid int64 `json:"mid"`
}
// PassportDetail get detail.
func (d *Dao) PassportDetail(c context.Context, mid int64) (res *PassportDetail, err error) {
ip := metadata.String(c, metadata.RemoteIP)
params := url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
var resp struct {
Code int `json:"code"`
Info *PassportDetail `json:"data"`
}
req, err := d.httpClient.NewRequest("GET", _passportURL, ip, params)
if err != nil {
err = errors.Wrap(err, "dao passport detail")
return
}
// req.Header.Set("Cookie", cookie)
req.Header.Set("X-BACKEND-BILI-REAL-IP", ip)
if err = d.httpClient.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.Info
return
}

View File

@@ -0,0 +1,18 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoGetPassportDetail(t *testing.T) {
convey.Convey("passport", t, func() {
var mid int64 = 27515586
httpMock("GET", _passportURL).Reply(200).BodyString(`{"code":0}`)
res, err := d.PassportDetail(context.TODO(), mid)
convey.So(err, convey.ShouldBeNil)
convey.So(res, convey.ShouldBeNil)
})
}

View File

@@ -0,0 +1,34 @@
package dao
import (
"context"
"net/url"
"strconv"
"go-common/library/log"
)
// TagIds get tag ids from tag
func (dao *Dao) TagIds(c context.Context, aid int64) (ids []int64, err error) {
params := url.Values{}
params.Set("aid", strconv.FormatInt(aid, 10))
var res struct {
Code int
Data []*struct {
ID int64 `json:"tag_id"`
}
}
if err = dao.httpClient.Get(c, dao.tagURI, "", params, &res); err != nil {
log.Error("dao.Ding api(%s) fail,err(%v)", dao.tagURI+"?"+params.Encode(), err)
return
}
if res.Code != 0 {
log.Error("dao.Ding api(%s) fail Code(%v)", dao.tagURI+"?"+params.Encode(), res.Code)
return
}
ids = make([]int64, 0, len(res.Data))
for _, d := range res.Data {
ids = append(ids, d.ID)
}
return
}

View File

@@ -0,0 +1,24 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoTagIds(t *testing.T) {
var (
c = context.TODO()
aid = int64(1)
)
convey.Convey("TagIds", t, func(ctx convey.C) {
_, err := d.TagIds(c, aid)
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
// ctx.Convey("ids should not be nil", func(ctx convey.C) {
// ctx.So(ids, convey.ShouldNotBeNil)
// })
})
}