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,61 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["dao_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/figure-timer/conf:go_default_library",
"//app/job/main/figure-timer/model:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"hbase.go",
"mysql.go",
"redis.go",
],
importpath = "go-common/app/job/main/figure-timer/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/figure-timer/conf:go_default_library",
"//app/job/main/figure-timer/model:go_default_library",
"//library/cache/redis:go_default_library",
"//library/database/hbase.v2:go_default_library",
"//library/database/sql:go_default_library",
"//library/log:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/github.com/tsuna/gohbase/hrpc:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/job/main/figure-timer/dao/mock_dao:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,94 @@
package dao
import (
"context"
"time"
"go-common/app/job/main/figure-timer/conf"
"go-common/app/job/main/figure-timer/model"
"go-common/library/cache/redis"
"go-common/library/database/hbase.v2"
"go-common/library/database/sql"
)
// Int is dao interface
type Int interface {
HBase
Mysql
Redis
Close()
Ping(c context.Context) error
}
// HBase dao hbase interface
type HBase interface {
UserInfo(c context.Context, mid int64, weekVer int64) (userInfo *model.UserInfo, err error)
PutCalcRecord(c context.Context, record *model.FigureRecord, weekTS int64) (err error)
CalcRecords(c context.Context, mid int64, weekTSFrom, weekTSTo int64) (figureRecords []*model.FigureRecord, err error)
ActionCounter(c context.Context, mid int64, ts int64) (counter *model.ActionCounter, err error)
}
// Mysql dao mysql interface
type Mysql interface {
Figure(c context.Context, mid int64) (figure *model.Figure, err error)
Figures(c context.Context, fromMid int64, limit int) (figures []*model.Figure, end bool, err error)
UpsertFigure(c context.Context, figure *model.Figure) (id int64, err error)
InsertRankHistory(c context.Context, rank *model.Rank) (id int64, err error)
UpsertRank(c context.Context, rank *model.Rank) (id int64, err error)
}
// Redis dao redis interface
type Redis interface {
FigureCache(c context.Context, mid int64) (figure *model.Figure, err error)
SetFigureCache(c context.Context, figure *model.Figure) (err error)
PendingMidsCache(c context.Context, version int64, shard int64) (mids []int64, err error)
RemoveCache(c context.Context, mid int64) (err error)
}
// Dao struct info of Dao.
type Dao struct {
c *conf.Config
mysql *sql.DB
hbase *hbase.Client
redis *redis.Pool
redisExpire int32
}
// New new a Dao and return.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
mysql: sql.NewMySQL(c.Mysql),
hbase: hbase.NewClient(c.Hbase.Config),
redis: redis.NewPool(c.Redis.Config),
redisExpire: int32(time.Duration(c.Redis.Expire) / time.Second),
}
return
}
// Close close connections of mc, redis, db.
func (d *Dao) Close() {
if d.mysql != nil {
d.mysql.Close()
}
if d.redis != nil {
d.redis.Close()
}
if d.hbase != nil {
d.hbase.Close()
}
}
// Ping ping health of db.
func (d *Dao) Ping(c context.Context) (err error) {
if err = d.mysql.Ping(c); err != nil {
return
}
// if err = d.hbase.Ping(c); err != nil {
// return
// }
if err = d.PingRedis(c); err != nil {
return
}
return
}

View File

@@ -0,0 +1,221 @@
package dao
import (
"context"
// "encoding/binary"
"flag"
"testing"
"time"
"go-common/app/job/main/figure-timer/conf"
"go-common/app/job/main/figure-timer/model"
// "go-common/library/log"
"github.com/pkg/errors"
. "github.com/smartystreets/goconvey/convey"
)
var (
dao *Dao
ctx = context.TODO()
)
func init() {
var err error
flag.Set("conf", "../cmd/figure-timer-job-test.toml")
if err = conf.Init(); err != nil {
panic(err)
}
dao = New(conf.Conf)
}
func TestInit(t *testing.T) {
Convey("TEST init", t, func() {
var err error
So(dao.c, ShouldNotBeNil)
So(dao.mysql, ShouldNotBeNil)
So(dao.hbase, ShouldNotBeNil)
So(dao.redis, ShouldNotBeNil)
err = dao.Ping(ctx)
So(err, ShouldBeNil)
})
}
func TestMysql(t *testing.T) {
Convey("TEST figure", t, func() {
var (
figure = &model.Figure{
Mid: 100,
Score: 100,
LawfulScore: 50,
WideScore: 0,
FriendlyScore: 23,
BountyScore: 250,
CreativityScore: 0,
Ver: 0,
}
figure2 *model.Figure
figureRank = &model.Rank{
ScoreFrom: 2000,
ScoreTo: 3000,
Percentage: 50,
Ver: 233,
}
err error
)
figure.ID, err = dao.UpsertFigure(ctx, figure)
So(err, ShouldBeNil)
figure2, err = dao.Figure(ctx, figure.Mid)
So(err, ShouldBeNil)
So(figure2, ShouldNotBeNil)
So(figure2.Ctime, ShouldNotBeEmpty)
So(figure2.Ctime, ShouldHappenBefore, time.Now().Add(time.Second))
So(figure2.Mtime, ShouldNotBeEmpty)
So(figure2.Mtime, ShouldHappenBefore, time.Now().Add(time.Second))
_, err = dao.InsertRankHistory(ctx, figureRank)
So(err, ShouldBeNil)
_, err = dao.UpsertRank(ctx, figureRank)
So(err, ShouldBeNil)
})
Convey("TEST figures", t, func() {
for shard := 0; shard < 100; shard++ {
var (
end bool
fromMid = int64(shard)
figures []*model.Figure
err error
)
for !end {
figures, end, err = dao.Figures(ctx, fromMid, 100)
So(err, ShouldBeNil)
for _, f := range figures {
So(f.Mid, ShouldBeGreaterThan, 0)
if fromMid < f.Mid {
fromMid = f.Mid
}
}
}
}
})
}
func TestRedis(t *testing.T) {
Convey("TEST figure", t, func() {
var (
figure = &model.Figure{
Mid: 23,
Score: 100,
LawfulScore: 50,
WideScore: 0,
FriendlyScore: 23,
BountyScore: 250,
CreativityScore: 0,
Ver: 0,
}
figure2 *model.Figure
err error
)
err = dao.SetFigureCache(ctx, figure)
So(err, ShouldBeNil)
figure2, err = dao.FigureCache(ctx, figure.Mid)
So(err, ShouldBeNil)
So(figure2, ShouldNotBeNil)
So(figure, ShouldResemble, figure2)
})
Convey("TEST pending mids", t, func() {
var (
mid int64 = 23
ver int64
shard = mid % dao.c.Property.PendingMidShard
mids []int64
err error
)
err = dao.setPendingMidCache(ctx, mid, ver)
So(err, ShouldBeNil)
mids, err = dao.PendingMidsCache(ctx, ver, shard)
So(err, ShouldBeNil)
So(mids, ShouldNotBeEmpty)
})
}
func (d *Dao) setPendingMidCache(c context.Context, mid int64, ver int64) (err error) {
var (
key = keyPendingMids(ver, mid%d.c.Property.PendingMidShard)
conn = d.redis.Get(c)
)
defer conn.Close()
if err = conn.Send("SADD", key, mid); err != nil {
err = errors.Wrapf(err, "conn.Send(SADD,%s,%d)", key, mid)
return
}
if err = conn.Send("EXPIRE", key, d); err != nil {
err = errors.Wrapf(err, "conn.Send(EXPIRE,%s,%v)", key, d)
return
}
if err = conn.Flush(); err != nil {
err = errors.WithStack(err)
return
}
if _, err = conn.Receive(); err != nil {
err = errors.WithStack(err)
return
}
return
}
// func testHbase(t *testing.T) {
// Convey("TEST figure_activity", t, func() {
// var (
// mid int64 = 15555180
// err error
// weekVer = time.Date(2017, 10, 2, 0, 0, 0, 0, time.Local).Unix()
// weekVerFrom = time.Date(2016, 10, 3, 0, 0, 0, 0, time.Local).Unix()
// weekVerTo = time.Date(2017, 9, 25, 0, 0, 0, 0, time.Local).Unix()
// userInfo *model.UserInfo
// figureRecord = &model.FigureRecord{
// Mid: mid,
// XPosLawful: 12,
// XNegLawful: 2,
// XPosWide: 12,
// XNegWide: 13,
// XPosFriendly: 233,
// XNegFriendly: 234,
// XPosCreativity: 0,
// XNegCreativity: 1,
// XPosBounty: -250,
// XNegBounty: -251,
// }
// figureRecords []*model.FigureRecord
// )
// err = dao.putSpyScore(ctx, mid, 100)
// So(err, ShouldBeNil)
// userInfo, err = dao.UserInfo(ctx, mid, weekVer)
// So(err, ShouldBeNil)
// So(userInfo, ShouldNotBeNil)
// err = dao.PutCalcRecord(ctx, figureRecord, time.Date(2016, 12, 3, 0, 0, 0, 0, time.Local).Unix())
// So(err, ShouldBeNil)
// figureRecords, err = dao.CalcRecords(ctx, mid, weekVerFrom, weekVerTo+1)
// So(err, ShouldBeNil)
// So(figureRecords, ShouldNotBeEmpty)
// })
// }
// // PutSpyScore add spy score info.
// func (d *Dao) putSpyScore(c context.Context, mid int64, score int8) (err error) {
// var (
// key = rowKeyUserInfo(mid)
// scoreB = make([]byte, 2)
// ctx, cancel = context.WithTimeout(c, time.Duration(conf.Conf.Hbase.WriteTimeout))
// )
// defer cancel()
// binary.BigEndian.PutUint16(scoreB, uint16(score))
// values := map[string]map[string][]byte{_hbaseUserFC: map[string][]byte{_hbaseUserQSpy: scoreB}}
// if _, err = d.hbase.PutStr(ctx, _hbaseUserTable, key, values); err != nil {
// log.Error("hbase.PutStr(%s, %s, %v) error(%v)", _hbaseUserTable, key, values, err)
// return
// }
// return
// }

View File

@@ -0,0 +1,353 @@
package dao
import (
"bytes"
"context"
"encoding/binary"
"fmt"
"io"
"math"
"strconv"
"strings"
"time"
"go-common/app/job/main/figure-timer/model"
"go-common/library/log"
"github.com/pkg/errors"
"github.com/tsuna/gohbase/hrpc"
)
var (
// record
_hbaseRecordTable = "ugc:figurecalcrecord"
_hbaseRecordFC = "x"
_hbaseRecordQLawfulPosX = "pos_lawful"
_hbaseRecordQLawfulNegX = "neg_lawful"
_hbaseRecordQWidePosX = "pos_wide"
_hbaseRecordQWideNegX = "neg_wide"
_hbaseRecordQFriendlyPosX = "pos_friendly"
_hbaseRecordQFriendlyNegX = "neg_friendly"
_hbaseRecordQCreativityPosX = "pos_creativity"
_hbaseRecordQCreativityNegX = "neg_creativity"
_hbaseRecordQBountyPosX = "pos_bounty"
_hbaseRecordQBountyNegX = "neg_bounty"
// UserInfo
_hbaseUserTable = "ugc:figureuserstatus"
_hbaseUserFC = "user"
_hbaseUserQExp = "exp"
_hbaseUserQSpy = "spy_score"
_hbaseUserQArchiveViews = "archive_views"
_hbaseUserQVip = "vip_status"
_hbaseUserQDisciplineCommittee = "discipline_committee"
// ActionCounter
_hbaseActionTable = "ugc:figureactioncounter"
_hbaseActionFC = "user"
_hbaseActionQCoinCount = "coins"
_hbaseActionQReplyCount = "replies"
_hbaseActionQDanmakuCount = "danmaku"
_hbaseActionQCoinLowRisk = "coin_low_risk"
_hbaseActionQCoinHighRisk = "coin_high_risk"
_hbaseActionQReplyLowRisk = "reply_low_risk"
_hbaseActionQReplyHighRisk = "reply_high_risk"
_hbaseActionQReplyLiked = "reply_liked"
_hbaseActionQReplyUnLiked = "reply_hate"
_hbaseActionQReportReplyPassed = "report_reply_passed"
_hbaseActionQReportDanmakuPassed = "report_danmaku_passed"
_hbaseActionQPublishReplyDeleted = "publish_reply_deleted"
_hbaseActionQPublishDanmakuDeleted = "publish_danmaku_deleted"
_hbaseActionQPayMoney = "pay_money"
_hbaseActionQPayLiveMoney = "pay_live_money"
)
func rowKeyFigureRecord(mid int64, weekTS int64) (key string) {
return fmt.Sprintf("%d_%d", mid, weekTS)
}
func rowKeyUserInfo(mid int64) (key string) {
return fmt.Sprintf("%d", mid)
}
func rowKeyActionCounter(mid int64, dayTS int64) (key string) {
return fmt.Sprintf("%d_%d", mid, dayTS)
}
// UserInfo get it from hbase
func (d *Dao) UserInfo(c context.Context, mid int64, weekVer int64) (userInfo *model.UserInfo, err error) {
var (
result *hrpc.Result
key = rowKeyUserInfo(mid)
ctx, cancel = context.WithTimeout(c, time.Duration(d.c.Hbase.ReadTimeout))
)
defer cancel()
if result, err = d.hbase.GetStr(ctx, _hbaseUserTable, key); err != nil {
err = errors.Wrapf(err, "hbase.GetStr(%s,%s)", _hbaseUserTable, key)
return
}
userInfo = &model.UserInfo{Mid: mid, SpyScore: math.MaxUint64}
for _, c := range result.Cells {
if c == nil {
continue
}
if bytes.Equal([]byte(_hbaseUserFC), c.Family) {
switch string(c.Qualifier) {
case _hbaseUserQExp:
userInfo.Exp = binary.BigEndian.Uint64(c.Value)
case _hbaseUserQSpy:
userInfo.SpyScore = binary.BigEndian.Uint64(c.Value)
case _hbaseUserQArchiveViews:
userInfo.ArchiveViews = binary.BigEndian.Uint64(c.Value)
case _hbaseUserQVip:
userInfo.VIPStatus = binary.BigEndian.Uint64(c.Value)
case _hbaseUserQDisciplineCommittee:
userInfo.DisciplineCommittee = binary.BigEndian.Uint16(c.Value)
}
}
}
// 未获取到spy分值特殊处理
if userInfo.SpyScore == math.MaxUint64 {
userInfo.SpyScore = 100
}
log.Info("User Info [%+v]", userInfo)
return
}
// PutCalcRecord put record all the params x.
func (d *Dao) PutCalcRecord(c context.Context, record *model.FigureRecord, weekTS int64) (err error) {
var (
key = rowKeyFigureRecord(record.Mid, weekTS)
lawfulPosX = make([]byte, 8)
lawfulNegX = make([]byte, 8)
widePosX = make([]byte, 8)
wideNegX = make([]byte, 8)
friendlyPosX = make([]byte, 8)
friendlyNegX = make([]byte, 8)
creativityPosX = make([]byte, 8)
creativityNegX = make([]byte, 8)
bountyPosX = make([]byte, 8)
bountyNegX = make([]byte, 8)
ctx, cancel = context.WithTimeout(c, time.Duration(d.c.Hbase.WriteTimeout))
)
defer cancel()
binary.BigEndian.PutUint64(lawfulPosX, uint64(record.XPosLawful))
binary.BigEndian.PutUint64(lawfulNegX, uint64(record.XNegLawful))
binary.BigEndian.PutUint64(widePosX, uint64(record.XPosWide))
binary.BigEndian.PutUint64(wideNegX, uint64(record.XNegWide))
binary.BigEndian.PutUint64(friendlyPosX, uint64(record.XPosFriendly))
binary.BigEndian.PutUint64(friendlyNegX, uint64(record.XNegFriendly))
binary.BigEndian.PutUint64(creativityPosX, uint64(record.XPosCreativity))
binary.BigEndian.PutUint64(creativityNegX, uint64(record.XNegCreativity))
binary.BigEndian.PutUint64(bountyPosX, uint64(record.XPosBounty))
binary.BigEndian.PutUint64(bountyNegX, uint64(record.XNegBounty))
values := map[string]map[string][]byte{_hbaseRecordFC: {
_hbaseRecordQLawfulPosX: lawfulPosX,
_hbaseRecordQLawfulNegX: lawfulNegX,
_hbaseRecordQWideNegX: wideNegX,
_hbaseRecordQFriendlyPosX: friendlyPosX,
_hbaseRecordQFriendlyNegX: friendlyNegX,
_hbaseRecordQCreativityPosX: creativityPosX,
_hbaseRecordQCreativityNegX: creativityNegX,
_hbaseRecordQBountyPosX: bountyPosX,
_hbaseRecordQBountyNegX: bountyNegX,
}}
if _, err = d.hbase.PutStr(ctx, _hbaseRecordTable, key, values); err != nil {
err = errors.Wrapf(err, "hbase.Put(%s,%s,%+v) error(%v)", _hbaseRecordTable, key, values, err)
}
return
}
// CalcRecords get it from hbase
func (d *Dao) CalcRecords(c context.Context, mid int64, weekTSFrom, weekTSTo int64) (figureRecords []*model.FigureRecord, err error) {
var (
scanner hrpc.Scanner
keyFrom = rowKeyFigureRecord(mid, weekTSFrom)
keyTo = rowKeyFigureRecord(mid, weekTSTo)
ctx, cancel = context.WithTimeout(c, time.Duration(d.c.Hbase.ReadTimeout))
)
defer cancel()
if scanner, err = d.hbase.ScanRangeStr(ctx, _hbaseRecordTable, keyFrom, keyTo); err != nil {
err = errors.Wrapf(err, "hbase.ScanRangeStr(%s,%s,%s)", _hbaseRecordTable, keyFrom, keyTo)
return
}
for {
res, err := scanner.Next()
if err != nil {
if err != io.EOF {
err = errors.WithStack(err)
return nil, err
}
break
}
figureRecord := &model.FigureRecord{Mid: mid}
for i, c := range res.Cells {
if c == nil {
continue
}
if bytes.Equal([]byte(_hbaseRecordFC), c.Family) {
switch string(c.Qualifier) {
case _hbaseRecordQLawfulPosX:
figureRecord.XPosLawful = int64(binary.BigEndian.Uint64(c.Value))
case _hbaseRecordQLawfulNegX:
figureRecord.XNegLawful = int64(binary.BigEndian.Uint64(c.Value))
case _hbaseRecordQWidePosX:
figureRecord.XPosWide = int64(binary.BigEndian.Uint64(c.Value))
case _hbaseRecordQWideNegX:
figureRecord.XNegWide = int64(binary.BigEndian.Uint64(c.Value))
case _hbaseRecordQFriendlyPosX:
figureRecord.XPosFriendly = int64(binary.BigEndian.Uint64(c.Value))
case _hbaseRecordQFriendlyNegX:
figureRecord.XNegFriendly = int64(binary.BigEndian.Uint64(c.Value))
case _hbaseRecordQCreativityPosX:
figureRecord.XPosCreativity = int64(binary.BigEndian.Uint64(c.Value))
case _hbaseRecordQCreativityNegX:
figureRecord.XNegCreativity = int64(binary.BigEndian.Uint64(c.Value))
case _hbaseRecordQBountyPosX:
figureRecord.XPosBounty = int64(binary.BigEndian.Uint64(c.Value))
case _hbaseRecordQBountyNegX:
figureRecord.XNegBounty = int64(binary.BigEndian.Uint64(c.Value))
}
}
if i == 0 {
figureRecord.Version = time.Unix(parseVersion(string(c.Row), c.Timestamp), 0)
}
}
log.Info("User figure record [%+v]", figureRecord)
figureRecords = append(figureRecords, figureRecord)
}
return
}
// ActionCounter .
func (d *Dao) ActionCounter(c context.Context, mid int64, ts int64) (actionCounter *model.ActionCounter, err error) {
var (
result *hrpc.Result
key = rowKeyActionCounter(mid, ts)
ctx, cancel = context.WithTimeout(c, time.Duration(d.c.Hbase.ReadTimeout))
)
defer cancel()
log.Info("Get mid [%d] key [%s]", mid, key)
if result, err = d.hbase.GetStr(ctx, _hbaseActionTable, key); err != nil {
err = errors.Wrapf(err, "hbase.GetStr(%s,%s)", _hbaseActionTable, key)
return
}
actionCounter = &model.ActionCounter{Mid: mid}
for i, c := range result.Cells {
if c == nil {
continue
}
if bytes.Equal([]byte(_hbaseActionFC), c.Family) {
switch string(c.Qualifier) {
case _hbaseActionQCoinCount:
actionCounter.CoinCount = binary.BigEndian.Uint64(c.Value)
case _hbaseActionQReplyCount:
actionCounter.ReplyCount = int64(binary.BigEndian.Uint64(c.Value))
case _hbaseActionQDanmakuCount:
actionCounter.DanmakuCount = int64(binary.BigEndian.Uint64(c.Value))
case _hbaseActionQCoinLowRisk:
actionCounter.CoinLowRisk = binary.BigEndian.Uint64(c.Value)
case _hbaseActionQCoinHighRisk:
actionCounter.CoinHighRisk = binary.BigEndian.Uint64(c.Value)
case _hbaseActionQReplyLowRisk:
actionCounter.ReplyLowRisk = binary.BigEndian.Uint64(c.Value)
case _hbaseActionQReplyHighRisk:
actionCounter.ReplyHighRisk = binary.BigEndian.Uint64(c.Value)
case _hbaseActionQReplyLiked:
actionCounter.ReplyLiked = int64(binary.BigEndian.Uint64(c.Value))
case _hbaseActionQReplyUnLiked:
actionCounter.ReplyUnliked = int64(binary.BigEndian.Uint64(c.Value))
case _hbaseActionQReportReplyPassed:
actionCounter.ReportReplyPassed = int64(binary.BigEndian.Uint64(c.Value))
case _hbaseActionQReportDanmakuPassed:
actionCounter.ReportDanmakuPassed = int64(binary.BigEndian.Uint64(c.Value))
case _hbaseActionQPublishReplyDeleted:
actionCounter.PublishReplyDeleted = int64(binary.BigEndian.Uint64(c.Value))
case _hbaseActionQPublishDanmakuDeleted:
actionCounter.PublishDanmakuDeleted = int64(binary.BigEndian.Uint64(c.Value))
case _hbaseActionQPayMoney:
actionCounter.PayMoney = int64(binary.BigEndian.Uint64(c.Value))
case _hbaseActionQPayLiveMoney:
actionCounter.PayLiveMoney = int64(binary.BigEndian.Uint64(c.Value))
}
}
if i == 0 {
actionCounter.Version = time.Unix(parseVersion(string(c.Row), c.Timestamp), 0)
}
}
log.Info("User action counter [%+v]", actionCounter)
return
}
// // ActionCounters .
// func (d *Dao) ActionCounters(c context.Context, mid int64, tsfrom int64, tsto int64) (actionCounters []*model.ActionCounter, err error) {
// var (
// scan *hrpc.Scan
// results []*hrpc.Result
// keyFrom = rowKeyActionCounter(mid, tsfrom)
// keyTo = rowKeyActionCounter(mid, tsto)
// ctx, cancel = context.WithTimeout(c, time.Duration(d.c.Hbase.ReadTimeout))
// )
// defer cancel()
// log.Info("Scan mid [%d] keyFrom [%s] keyTo [%s]", mid, keyFrom, keyTo)
// if scan, err = hrpc.NewScanRangeStr(ctx, _hbaseActionTable, keyFrom, keyTo); err != nil {
// err = errors.Wrapf(err, "hrcp.NewScanRangeStr(%s,%s,%s)", _hbaseActionTable, keyFrom, keyTo)
// return
// }
// if results, err = d.hbase.Scan(ctx, scan); err != nil {
// err = errors.Wrapf(err, "hbase.Scan(%s,%s,%s)", _hbaseActionTable, keyFrom, keyTo)
// return
// }
// if len(results) == 0 {
// return
// }
// for _, res := range results {
// if res == nil {
// continue
// }
// actionCounter := &model.ActionCounter{Mid: mid}
// for i, c := range res.Cells {
// if c == nil {
// continue
// }
// if bytes.Equal([]byte(_hbaseActionFC), c.Family) {
// switch string(c.Qualifier) {
// case _hbaseActionQCoinCount:
// actionCounter.CoinCount = binary.BigEndian.Uint64(c.Value)
// case _hbaseActionQReplyCount:
// actionCounter.ReplyCount = int64(binary.BigEndian.Uint64(c.Value))
// case _hbaseActionQCoinLowRisk:
// actionCounter.CoinLowRisk = binary.BigEndian.Uint64(c.Value)
// case _hbaseActionQCoinHighRisk:
// actionCounter.CoinHighRisk = binary.BigEndian.Uint64(c.Value)
// case _hbaseActionQReplyLowRisk:
// actionCounter.ReplyLowRisk = binary.BigEndian.Uint64(c.Value)
// case _hbaseActionQReplyHighRisk:
// actionCounter.ReplyHighRisk = binary.BigEndian.Uint64(c.Value)
// case _hbaseActionQReplyLiked:
// actionCounter.ReplyLiked = int64(binary.BigEndian.Uint64(c.Value))
// case _hbaseActionQReplyUnLiked:
// actionCounter.ReplyUnliked = int64(binary.BigEndian.Uint64(c.Value))
// }
// }
// if i == 0 {
// actionCounter.Version = time.Unix(parseVersion(string(c.Row), c.Timestamp), 0)
// }
// }
// log.Info("User action counter [%+v]", actionCounter)
// actionCounters = append(actionCounters, actionCounter)
// }
// return
// }
func parseVersion(rowKey string, timestamp *uint64) (ts int64) {
strs := strings.Split(rowKey, "_")
if len(strs) < 2 {
return int64(*timestamp)
}
var err error
if ts, err = strconv.ParseInt(strs[1], 10, 64); err != nil {
return int64(*timestamp)
}
return ts
}

View File

@@ -0,0 +1,42 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["mock_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = ["//vendor/github.com/smartystreets/goconvey/convey:go_default_library"],
)
go_library(
name = "go_default_library",
srcs = ["mock.go"],
importpath = "go-common/app/job/main/figure-timer/dao/mock_dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/figure-timer/model:go_default_library",
"//vendor/github.com/golang/mock/gomock: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,225 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: go-common/app/job/main/figure-timer/dao (interfaces: DaoInt)
// Package mock_dao is a generated GoMock package.
package mock_dao
import (
context "context"
model "go-common/app/job/main/figure-timer/model"
reflect "reflect"
gomock "github.com/golang/mock/gomock"
)
// MockDaoInt is a mock of DaoInt interface
type MockDaoInt struct {
ctrl *gomock.Controller
recorder *MockDaoIntMockRecorder
}
// MockDaoIntMockRecorder is the mock recorder for MockDaoInt
type MockDaoIntMockRecorder struct {
mock *MockDaoInt
}
// NewMockDaoInt creates a new mock instance
func NewMockDaoInt(ctrl *gomock.Controller) *MockDaoInt {
mock := &MockDaoInt{ctrl: ctrl}
mock.recorder = &MockDaoIntMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use
func (m *MockDaoInt) EXPECT() *MockDaoIntMockRecorder {
return m.recorder
}
// ActionCounter mocks base method
func (m *MockDaoInt) ActionCounter(arg0 context.Context, arg1, arg2 int64) (*model.ActionCounter, error) {
ret := m.ctrl.Call(m, "ActionCounter", arg0, arg1, arg2)
ret0, _ := ret[0].(*model.ActionCounter)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ActionCounter indicates an expected call of ActionCounter
func (mr *MockDaoIntMockRecorder) ActionCounter(arg0, arg1, arg2 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ActionCounter", reflect.TypeOf((*MockDaoInt)(nil).ActionCounter), arg0, arg1, arg2)
}
// CalcRecords mocks base method
func (m *MockDaoInt) CalcRecords(arg0 context.Context, arg1, arg2, arg3 int64) ([]*model.FigureRecord, error) {
ret := m.ctrl.Call(m, "CalcRecords", arg0, arg1, arg2, arg3)
ret0, _ := ret[0].([]*model.FigureRecord)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// CalcRecords indicates an expected call of CalcRecords
func (mr *MockDaoIntMockRecorder) CalcRecords(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CalcRecords", reflect.TypeOf((*MockDaoInt)(nil).CalcRecords), arg0, arg1, arg2, arg3)
}
// Close mocks base method
func (m *MockDaoInt) Close() {
m.ctrl.Call(m, "Close")
}
// Close indicates an expected call of Close
func (mr *MockDaoIntMockRecorder) Close() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockDaoInt)(nil).Close))
}
// Figure mocks base method
func (m *MockDaoInt) Figure(arg0 context.Context, arg1 int64) (*model.Figure, error) {
ret := m.ctrl.Call(m, "Figure", arg0, arg1)
ret0, _ := ret[0].(*model.Figure)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Figure indicates an expected call of Figure
func (mr *MockDaoIntMockRecorder) Figure(arg0, arg1 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Figure", reflect.TypeOf((*MockDaoInt)(nil).Figure), arg0, arg1)
}
// FigureCache mocks base method
func (m *MockDaoInt) FigureCache(arg0 context.Context, arg1 int64) (*model.Figure, error) {
ret := m.ctrl.Call(m, "FigureCache", arg0, arg1)
ret0, _ := ret[0].(*model.Figure)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// FigureCache indicates an expected call of FigureCache
func (mr *MockDaoIntMockRecorder) FigureCache(arg0, arg1 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FigureCache", reflect.TypeOf((*MockDaoInt)(nil).FigureCache), arg0, arg1)
}
// Figures mocks base method
func (m *MockDaoInt) Figures(arg0 context.Context, arg1 int64, arg2 int) ([]*model.Figure, bool, error) {
ret := m.ctrl.Call(m, "Figures", arg0, arg1, arg2)
ret0, _ := ret[0].([]*model.Figure)
ret1, _ := ret[1].(bool)
ret2, _ := ret[2].(error)
return ret0, ret1, ret2
}
// Figures indicates an expected call of Figures
func (mr *MockDaoIntMockRecorder) Figures(arg0, arg1, arg2 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Figures", reflect.TypeOf((*MockDaoInt)(nil).Figures), arg0, arg1, arg2)
}
// InsertRankHistory mocks base method
func (m *MockDaoInt) InsertRankHistory(arg0 context.Context, arg1 *model.Rank) (int64, error) {
ret := m.ctrl.Call(m, "InsertRankHistory", arg0, arg1)
ret0, _ := ret[0].(int64)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// InsertRankHistory indicates an expected call of InsertRankHistory
func (mr *MockDaoIntMockRecorder) InsertRankHistory(arg0, arg1 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InsertRankHistory", reflect.TypeOf((*MockDaoInt)(nil).InsertRankHistory), arg0, arg1)
}
// PendingMidsCache mocks base method
func (m *MockDaoInt) PendingMidsCache(arg0 context.Context, arg1, arg2 int64) ([]int64, error) {
ret := m.ctrl.Call(m, "PendingMidsCache", arg0, arg1, arg2)
ret0, _ := ret[0].([]int64)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// PendingMidsCache indicates an expected call of PendingMidsCache
func (mr *MockDaoIntMockRecorder) PendingMidsCache(arg0, arg1, arg2 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PendingMidsCache", reflect.TypeOf((*MockDaoInt)(nil).PendingMidsCache), arg0, arg1, arg2)
}
// Ping mocks base method
func (m *MockDaoInt) Ping(arg0 context.Context) error {
ret := m.ctrl.Call(m, "Ping", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// Ping indicates an expected call of Ping
func (mr *MockDaoIntMockRecorder) Ping(arg0 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Ping", reflect.TypeOf((*MockDaoInt)(nil).Ping), arg0)
}
// PutCalcRecord mocks base method
func (m *MockDaoInt) PutCalcRecord(arg0 context.Context, arg1 *model.FigureRecord, arg2 int64) error {
ret := m.ctrl.Call(m, "PutCalcRecord", arg0, arg1, arg2)
ret0, _ := ret[0].(error)
return ret0
}
// PutCalcRecord indicates an expected call of PutCalcRecord
func (mr *MockDaoIntMockRecorder) PutCalcRecord(arg0, arg1, arg2 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutCalcRecord", reflect.TypeOf((*MockDaoInt)(nil).PutCalcRecord), arg0, arg1, arg2)
}
// RemoveCache mocks base method
func (m *MockDaoInt) RemoveCache(arg0 context.Context, arg1 int64) error {
ret := m.ctrl.Call(m, "RemoveCache", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// RemoveCache indicates an expected call of RemoveCache
func (mr *MockDaoIntMockRecorder) RemoveCache(arg0, arg1 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveCache", reflect.TypeOf((*MockDaoInt)(nil).RemoveCache), arg0, arg1)
}
// SetFigureCache mocks base method
func (m *MockDaoInt) SetFigureCache(arg0 context.Context, arg1 *model.Figure) error {
ret := m.ctrl.Call(m, "SetFigureCache", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// SetFigureCache indicates an expected call of SetFigureCache
func (mr *MockDaoIntMockRecorder) SetFigureCache(arg0, arg1 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetFigureCache", reflect.TypeOf((*MockDaoInt)(nil).SetFigureCache), arg0, arg1)
}
// UpsertFigure mocks base method
func (m *MockDaoInt) UpsertFigure(arg0 context.Context, arg1 *model.Figure) (int64, error) {
ret := m.ctrl.Call(m, "UpsertFigure", arg0, arg1)
ret0, _ := ret[0].(int64)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// UpsertFigure indicates an expected call of UpsertFigure
func (mr *MockDaoIntMockRecorder) UpsertFigure(arg0, arg1 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertFigure", reflect.TypeOf((*MockDaoInt)(nil).UpsertFigure), arg0, arg1)
}
// UpsertRank mocks base method
func (m *MockDaoInt) UpsertRank(arg0 context.Context, arg1 *model.Rank) (int64, error) {
ret := m.ctrl.Call(m, "UpsertRank", arg0, arg1)
ret0, _ := ret[0].(int64)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// UpsertRank indicates an expected call of UpsertRank
func (mr *MockDaoIntMockRecorder) UpsertRank(arg0, arg1 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertRank", reflect.TypeOf((*MockDaoInt)(nil).UpsertRank), arg0, arg1)
}
// UserInfo mocks base method
func (m *MockDaoInt) UserInfo(arg0 context.Context, arg1, arg2 int64) (*model.UserInfo, error) {
ret := m.ctrl.Call(m, "UserInfo", arg0, arg1, arg2)
ret0, _ := ret[0].(*model.UserInfo)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// UserInfo indicates an expected call of UserInfo
func (mr *MockDaoIntMockRecorder) UserInfo(arg0, arg1, arg2 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UserInfo", reflect.TypeOf((*MockDaoInt)(nil).UserInfo), arg0, arg1, arg2)
}

View File

@@ -0,0 +1,13 @@
package mock_dao
import (
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestFake(t *testing.T) {
Convey("Test fake", t, func() {
t.Log("nothing here")
})
}

View File

@@ -0,0 +1,119 @@
package dao
import (
"context"
"database/sql"
"fmt"
"time"
"go-common/app/job/main/figure-timer/model"
xsql "go-common/library/database/sql"
"github.com/pkg/errors"
)
const (
_shard = 100
_selFigure = `SELECT id,mid,score,lawful_score,wide_score,friendly_score,bounty_score,creativity_score,ver,ctime,mtime FROM figure_user_%02d WHERE mid=? LIMIT 1`
_selFigures = `SELECT id,mid,score,lawful_score,wide_score,friendly_score,bounty_score,creativity_score,ver,ctime,mtime FROM figure_user_%02d WHERE mid>? LIMIT ?`
_upsertFigure = `INSERT INTO figure_user_%02d (mid,score,lawful_score,wide_score,friendly_score,bounty_score,creativity_score,ver,ctime,mtime) VALUES (?,?,?,?,?,?,?,?,?,?) ON DUPLICATE KEY UPDATE score=?,lawful_score=?,wide_score=?,friendly_score=?,bounty_score=?,creativity_score=?,ver=?,mtime=?`
_insertRank = `INSERT INTO figure_rank (score_from,score_to,percentage) VALUES(?,?,?) ON DUPLICATE KEY UPDATE score_from=?,score_to=?,percentage=?`
_insertRankHistory = `INSERT INTO figure_rank_history (score_from,score_to,percentage,ver) VALUES(?,?,?,?)`
)
func hit(mid int64) int64 {
return mid % _shard
}
// Figure get Figure from db
func (d *Dao) Figure(c context.Context, mid int64) (figure *model.Figure, err error) {
row := d.mysql.QueryRow(c, fmt.Sprintf(_selFigure, hit(mid)), mid)
figure = &model.Figure{}
if err = row.Scan(&figure.ID, &figure.Mid, &figure.Score, &figure.LawfulScore, &figure.WideScore, &figure.FriendlyScore, &figure.BountyScore, &figure.CreativityScore, &figure.Ver, &figure.Ctime, &figure.Mtime); err != nil {
if err == xsql.ErrNoRows {
err = nil
figure = nil
return
}
err = errors.WithStack(err)
return
}
return
}
// Figures get all figure info from formMid
func (d *Dao) Figures(c context.Context, fromMid int64, limit int) (figures []*model.Figure, end bool, err error) {
if limit <= 0 {
return
}
var (
rows *xsql.Rows
)
if rows, err = d.mysql.Query(c, fmt.Sprintf(_selFigures, hit(fromMid)), fromMid, limit); err != nil {
err = errors.WithStack(err)
return
}
defer rows.Close()
for rows.Next() {
figure := &model.Figure{}
if err = rows.Scan(&figure.ID, &figure.Mid, &figure.Score, &figure.LawfulScore, &figure.WideScore, &figure.FriendlyScore, &figure.BountyScore, &figure.CreativityScore, &figure.Ver, &figure.Ctime, &figure.Mtime); err != nil {
if err == xsql.ErrNoRows {
err = nil
end = true
return
}
return
}
figures = append(figures, figure)
}
if len(figures) < limit {
end = true
}
err = errors.WithStack(rows.Err())
return
}
// UpsertFigure insert or update(if mid duplicated) Figure
func (d *Dao) UpsertFigure(c context.Context, figure *model.Figure) (id int64, err error) {
var (
result sql.Result
now = time.Now()
)
if result, err = d.mysql.Exec(c, fmt.Sprintf(_upsertFigure, hit(figure.Mid)), figure.Mid, figure.Score, figure.LawfulScore, figure.WideScore, figure.FriendlyScore, figure.BountyScore, figure.CreativityScore, figure.Ver, now, now, figure.Score, figure.LawfulScore, figure.WideScore, figure.FriendlyScore, figure.BountyScore, figure.CreativityScore, figure.Ver, now); err != nil {
return
}
if id, err = result.LastInsertId(); err != nil {
err = errors.WithStack(err)
}
return
}
// InsertRankHistory insert figure rank history to db
func (d *Dao) InsertRankHistory(c context.Context, rank *model.Rank) (id int64, err error) {
var (
res sql.Result
)
if res, err = d.mysql.Exec(c, _insertRankHistory, rank.ScoreFrom, rank.ScoreTo, rank.Percentage, rank.Ver); err != nil {
return
}
if id, err = res.LastInsertId(); err != nil {
err = errors.WithStack(err)
return
}
return
}
// UpsertRank insert or update figure rank to db
func (d *Dao) UpsertRank(c context.Context, rank *model.Rank) (id int64, err error) {
var (
res sql.Result
)
if res, err = d.mysql.Exec(c, _insertRank, rank.ScoreFrom, rank.ScoreTo, rank.Percentage, rank.ScoreFrom, rank.ScoreTo, rank.Percentage); err != nil {
return
}
if id, err = res.LastInsertId(); err != nil {
err = errors.WithStack(err)
return
}
return
}

View File

@@ -0,0 +1,99 @@
package dao
import (
"context"
"encoding/json"
"fmt"
"go-common/app/job/main/figure-timer/model"
"go-common/library/cache/redis"
"go-common/library/log"
"github.com/pkg/errors"
)
func keyFigure(mid int64) string {
return fmt.Sprintf("f:%d", mid)
}
func keyPendingMids(ver int64, shard int64) string {
return fmt.Sprintf("w:u%d%d", ver, shard)
}
// PingRedis check redis connection
func (d *Dao) PingRedis(c context.Context) (err error) {
conn := d.redis.Get(c)
defer conn.Close()
_, err = conn.Do("SET", "PING", "PONG")
return
}
// FigureCache get FigureUser from cache
func (d *Dao) FigureCache(c context.Context, mid int64) (figure *model.Figure, err error) {
key := keyFigure(mid)
conn := d.redis.Get(c)
defer conn.Close()
item, err := redis.Bytes(conn.Do("GET", key))
if err != nil {
if err == redis.ErrNil {
err = nil
}
return
}
figure = &model.Figure{}
if err = json.Unmarshal(item, &figure); err != nil {
log.Error("json.Unmarshal(%v) err(%v)", item, err)
}
return
}
// SetFigureCache set FigureUser to cache
func (d *Dao) SetFigureCache(c context.Context, figure *model.Figure) (err error) {
key := keyFigure(figure.Mid)
conn := d.redis.Get(c)
defer conn.Close()
values, err := json.Marshal(figure)
if err != nil {
return
}
if err = conn.Send("SET", key, values); err != nil {
log.Error("conn.Send(SET, %s, %v) error(%v)", key, values, err)
return
}
if err = conn.Send("EXPIRE", key, d.redisExpire); err != nil {
log.Error("conn.Send(Expire, %s, %d) error(%v)", key, d.redisExpire, err)
return
}
return
}
// PendingMidsCache get PendingUser set from cache
func (d *Dao) PendingMidsCache(c context.Context, version int64, shard int64) (mids []int64, err error) {
var (
conn = d.redis.Get(c)
key = keyPendingMids(version, shard)
)
defer conn.Close()
if mids, err = redis.Int64s(conn.Do("SMEMBERS", key)); err != nil {
if err == redis.ErrNil {
err = nil
return
}
err = errors.Wrapf(err, "redis.Int64s(conn.Do(SMEMEBERS,%s))", key)
return
}
return
}
// RemoveCache remove figure cache
func (d *Dao) RemoveCache(c context.Context, mid int64) (err error) {
key := keyFigure(mid)
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
}
return
}