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,47 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["utils_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 = ["utils.go"],
importpath = "go-common/app/service/main/up/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/service/main/up/dao/archive:all-srcs",
"//app/service/main/up/dao/card:all-srcs",
"//app/service/main/up/dao/data:all-srcs",
"//app/service/main/up/dao/global:all-srcs",
"//app/service/main/up/dao/manager:all-srcs",
"//app/service/main/up/dao/monitor:all-srcs",
"//app/service/main/up/dao/up:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,64 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"archive_test.go",
"dao_test.go",
"upper_rds_test.go",
"upper_staff_test.go",
"upper_test.go",
],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//app/service/main/up/conf:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"archive.go",
"dao.go",
"upper.go",
"upper_rds.go",
"upper_staff.go",
],
importpath = "go-common/app/service/main/up/dao/archive",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/up/conf:go_default_library",
"//app/service/main/up/model:go_default_library",
"//library/cache/redis:go_default_library",
"//library/database/sql:go_default_library",
"//library/log:go_default_library",
"//library/stat/prom:go_default_library",
"//library/time:go_default_library",
"//library/xstr:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,45 @@
package archive
import (
"context"
"fmt"
"go-common/app/service/main/up/model"
"go-common/library/database/sql"
"go-common/library/time"
"go-common/library/xstr"
)
const (
_arcsAidsSQL = "SELECT aid,pubtime,copyright FROM archive WHERE aid IN (%s) AND state>=0 ORDER BY pubtime DESC"
)
// ArcsAids get archives by aids.
func (d *Dao) ArcsAids(c context.Context, ids []int64) (aids []int64, ptimes []time.Time, copyrights []int8, aptm map[int64]*model.AidPubTime, err error) {
d.infoProm.Incr("ArcAids")
rows, err := d.resultDB.Query(c, fmt.Sprintf(_arcsAidsSQL, xstr.JoinInts(ids)))
if err != nil {
return
}
defer rows.Close()
aptm = make(map[int64]*model.AidPubTime, len(ids))
for rows.Next() {
var (
aid int64
ptime time.Time
copyright int8
)
if err = rows.Scan(&aid, &ptime, &copyright); err != nil {
if err == sql.ErrNoRows {
err = nil
return
}
return
}
aptm[aid] = &model.AidPubTime{Aid: aid, PubDate: ptime, Copyright: copyright}
aids = append(aids, aid)
ptimes = append(ptimes, ptime)
copyrights = append(copyrights, copyright)
}
return
}

View File

@@ -0,0 +1,27 @@
package archive
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestArchiveArcsAids(t *testing.T) {
convey.Convey("ArcsAids", t, func(ctx convey.C) {
var (
c = context.Background()
ids = []int64{10110188}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
aids, ptimes, copyrights, aptm, err := d.ArcsAids(c, ids)
ctx.Convey("Then err should be nil.aids,ptimes,copyrights,aptm should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(aptm, convey.ShouldNotBeNil)
ctx.So(copyrights, convey.ShouldNotBeNil)
ctx.So(ptimes, convey.ShouldNotBeNil)
ctx.So(aids, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,38 @@
package archive
import (
"time"
"go-common/app/service/main/up/conf"
"go-common/library/cache/redis"
"go-common/library/database/sql"
"go-common/library/stat/prom"
)
// Dao is archive dao.
type Dao struct {
c *conf.Config
resultDB *sql.DB
archiveDB *sql.DB
// redis
upRds *redis.Pool
upExpire int32
errProm *prom.Prom
infoProm *prom.Prom
}
// New new a Dao and return.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
// db
resultDB: sql.NewMySQL(c.DB.ArcResult),
archiveDB: sql.NewMySQL(c.DB.Archive),
// redis
upRds: redis.NewPool(c.Redis.Up.Config),
upExpire: int32(time.Duration(c.Redis.Up.UpExpire) / time.Second),
errProm: prom.BusinessErrCount,
infoProm: prom.BusinessInfoCount,
}
return
}

View File

@@ -0,0 +1,39 @@
package archive
import (
"flag"
"os"
"testing"
"go-common/app/service/main/up/conf"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.up-service")
flag.Set("conf_token", "5f1660060bb011e8865c66d44b23cda7")
flag.Set("tree_id", "15572")
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/up-service.toml")
}
if os.Getenv("UT_LOCAL_TEST") != "" {
flag.Set("conf", "../../cmd/up-service.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
m.Run()
os.Exit(0)
}

View File

@@ -0,0 +1,107 @@
package archive
import (
"context"
"fmt"
"go-common/library/log"
"go-common/library/time"
"go-common/library/xstr"
"github.com/pkg/errors"
)
const (
_upCntSQL = "SELECT COUNT(*) FROM archive WHERE mid=? AND (state>=0 or state=-6)"
_upsCntSQL = "SELECT mid,COUNT(*) FROM archive WHERE mid IN(%s) AND (state>=0 or state=-6) GROUP BY mid"
_upPasSQL = "SELECT aid,pubtime,copyright FROM archive WHERE mid=? AND state>=0 ORDER BY pubtime DESC"
_upsPasSQL = "SELECT aid,mid,pubtime,copyright FROM archive WHERE mid IN (%s) AND state>=0 ORDER BY pubtime DESC"
)
// UppersCount get mids count
func (d *Dao) UppersCount(c context.Context, mids []int64) (uc map[int64]int64, err error) {
rows, err := d.resultDB.Query(c, fmt.Sprintf(_upsCntSQL, xstr.JoinInts(mids)))
if err != nil {
err = errors.WithStack(err)
return
}
uc = make(map[int64]int64, len(mids))
defer rows.Close()
for rows.Next() {
var (
mid int64
cnt int64
)
if err = rows.Scan(&mid, &cnt); err != nil {
err = errors.WithStack(err)
return
}
uc[mid] = cnt
}
return
}
// UpperCount get the count of archives by mid of Up.
func (d *Dao) UpperCount(c context.Context, mid int64) (count int64, err error) {
d.infoProm.Incr("UpperCount")
row := d.resultDB.QueryRow(c, _upCntSQL, mid)
if err = row.Scan(&count); err != nil {
log.Error("row.Scan error(%v)", err)
}
return
}
// UpperPassed get upper passed archives.
func (d *Dao) UpperPassed(c context.Context, mid int64) (aids []int64, ptimes []time.Time, copyrights []int8, err error) {
d.infoProm.Incr("UpperPassed")
rows, err := d.resultDB.Query(c, _upPasSQL, mid)
if err != nil {
log.Error("getUpPasStmt.Query(%d) error(%v)", mid, err)
return
}
defer rows.Close()
for rows.Next() {
var (
aid int64
ptime time.Time
copyright int8
)
if err = rows.Scan(&aid, &ptime, &copyright); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
aids = append(aids, aid)
ptimes = append(ptimes, ptime)
copyrights = append(copyrights, copyright)
}
return
}
// UppersPassed get uppers passed archives.
func (d *Dao) UppersPassed(c context.Context, mids []int64) (aidm map[int64][]int64, ptimes map[int64][]time.Time, copyrights map[int64][]int8, err error) {
d.infoProm.Incr("UppersPassed")
rows, err := d.resultDB.Query(c, fmt.Sprintf(_upsPasSQL, xstr.JoinInts(mids)))
if err != nil {
log.Error("UpsPassed error(%v)", err)
return
}
defer rows.Close()
aidm = make(map[int64][]int64, len(mids))
ptimes = make(map[int64][]time.Time, len(mids))
copyrights = make(map[int64][]int8, len(mids))
for rows.Next() {
var (
aid, mid int64
ptime time.Time
copyright int8
)
if err = rows.Scan(&aid, &mid, &ptime, &copyright); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
aidm[mid] = append(aidm[mid], aid)
ptimes[mid] = append(ptimes[mid], ptime)
copyrights[mid] = append(copyrights[mid], copyright)
}
return
}

View File

@@ -0,0 +1,316 @@
package archive
import (
"context"
"strconv"
"go-common/app/service/main/up/model"
"go-common/library/cache/redis"
"go-common/library/log"
"go-common/library/time"
)
const (
_prefixUpCnt = "uc_"
_prefixUpPas = "up_"
)
func upCntKey(mid int64) string {
return _prefixUpCnt + strconv.FormatInt(mid, 10)
}
func upPasKey(mid int64) string {
return _prefixUpPas + strconv.FormatInt(mid, 10)
}
// AddUpperCountCache the count of up's archives
func (d *Dao) AddUpperCountCache(c context.Context, mid int64, count int64) (err error) {
var (
key = upCntKey(mid)
conn = d.upRds.Get(c)
expireTime = d.upExpire
)
defer conn.Close()
if count == 0 {
expireTime = 600
}
if _, err = conn.Do("SETEX", key, expireTime, count); err != nil {
log.Error("conn.Do(SETEX, %s, %d, %d)", key, expireTime, count)
return
}
return
}
// UpperCountCache get up count from cache.
func (d *Dao) UpperCountCache(c context.Context, mid int64) (count int64, err error) {
var (
key = upCntKey(mid)
conn = d.upRds.Get(c)
)
defer conn.Close()
if count, err = redis.Int64(conn.Do("GET", key)); err != nil {
if err == redis.ErrNil {
count = -1
err = nil
} else {
d.errProm.Incr("upper_redis")
log.Error("conn.Do(GET, %s) error(%v)", key, err)
}
}
return
}
// UppersCountCache return uppers count cache
func (d *Dao) UppersCountCache(c context.Context, mids []int64) (cached map[int64]int64, missed []int64, err error) {
conn := d.upRds.Get(c)
defer conn.Close()
cached = make(map[int64]int64)
for _, mid := range mids {
key := upCntKey(mid)
if err = conn.Send("GET", key); err != nil {
missed = mids
continue
}
}
if err = conn.Flush(); err != nil {
missed = mids
return
}
for _, mid := range mids {
var cnt int64
if cnt, err = redis.Int64(conn.Receive()); err != nil {
if err == redis.ErrNil {
missed = append(missed, mid)
err = nil
continue
}
}
cached[mid] = int64(cnt)
}
return
}
// UpperPassedCache get upper passed archives from cache.
func (d *Dao) UpperPassedCache(c context.Context, mid int64, start, end int) (aids []int64, err error) {
var (
key = upPasKey(mid)
conn = d.upRds.Get(c)
)
defer conn.Close()
if aids, err = redis.Int64s(conn.Do("ZREVRANGE", key, start, end)); err != nil {
d.errProm.Incr("upper_redis")
log.Error("conn.Do(ZRANGE, %s, 0, -1) error(%v)", key, err)
}
return
}
// UppersPassedCacheWithScore get uppers passed archive from cache with score
func (d *Dao) UppersPassedCacheWithScore(c context.Context, mids []int64, start, end int) (aidm map[int64][]*model.AidPubTime, err error) {
conn := d.upRds.Get(c)
defer conn.Close()
aidm = make(map[int64][]*model.AidPubTime, len(mids))
for _, mid := range mids {
key := upPasKey(mid)
if err = conn.Send("ZREVRANGE", key, start, end, "WITHSCORES"); err != nil {
d.errProm.Incr("upper_redis")
log.Error("conn.Send(ZREVRANGE, %s) error(%v)", key, err)
return
}
}
if err = conn.Flush(); err != nil {
log.Error("conn.Flush error(%v)", err)
return
}
for _, mid := range mids {
aidScores, err := redis.Int64s(conn.Receive())
if err != nil {
d.errProm.Incr("upper_redis")
log.Error("conn.Do(GET, %d) error(%v)", mid, err)
continue
}
for i := 0; i < len(aidScores); i += 2 {
var (
score int64
ptime int64
copyright int8
)
score = aidScores[i+1]
if score > 1000000000 {
ptime = score >> 2
copyright = int8(score & 3)
aidm[mid] = append(aidm[mid], &model.AidPubTime{Aid: aidScores[i], PubDate: time.Time(ptime), Copyright: copyright})
} else {
aidm[mid] = append(aidm[mid], &model.AidPubTime{Aid: aidScores[i], PubDate: time.Time(score)})
}
}
}
return
}
// UppersPassedCache get uppers passed archives from cache.
func (d *Dao) UppersPassedCache(c context.Context, mids []int64, start, end int) (aidm map[int64][]int64, err error) {
conn := d.upRds.Get(c)
defer conn.Close()
aidm = make(map[int64][]int64, len(mids))
for _, mid := range mids {
key := upPasKey(mid)
if err = conn.Send("ZREVRANGE", key, start, end); err != nil {
d.errProm.Incr("upper_redis")
log.Error("conn.Send(ZREVRANGE, %s) error(%v)", key, err)
return
}
}
if err = conn.Flush(); err != nil {
log.Error("conn.Flush error(%v)", err)
return
}
for _, mid := range mids {
aids, err := redis.Int64s(conn.Receive())
if err != nil {
d.errProm.Incr("upper_redis")
log.Error("conn.Do(GET, %d) error(%v)", mid, err)
continue
}
aidm[mid] = aids
}
return
}
// ExpireUpperPassedCache expire up passed cache.
func (d *Dao) ExpireUpperPassedCache(c context.Context, mid int64) (ok bool, err error) {
var (
key = upPasKey(mid)
conn = d.upRds.Get(c)
)
defer conn.Close()
if ok, err = redis.Bool(conn.Do("EXPIRE", key, d.upExpire)); err != nil {
d.errProm.Incr("upper_redis")
log.Error("conn.Do(EXPIRE, %s, %d) error(%v)", key, d.upExpire, err)
}
return
}
// ExpireUppersCountCache expire ups count cache
func (d *Dao) ExpireUppersCountCache(c context.Context, mids []int64) (cachedUp, missed []int64, err error) {
var conn = d.upRds.Get(c)
defer conn.Close()
defer func() {
if err != nil {
d.errProm.Incr("upper_redis")
}
}()
for _, mid := range mids {
var key = upCntKey(mid)
if err = conn.Send("GET", key); err != nil {
log.Error("conn.Send(GET, %s) error(%v)", key, err)
return
}
}
for _, mid := range mids {
var key = upCntKey(mid)
if err = conn.Send("EXPIRE", key, d.upExpire); err != nil {
log.Error("conn.Send(GET, %s) error(%v)", key, err)
return
}
}
if err = conn.Flush(); err != nil {
log.Error("conn.Flush error(%v)", err)
return
}
cachedUp = make([]int64, 0)
missed = make([]int64, 0)
for _, mid := range mids {
var cnt int
if cnt, err = redis.Int(conn.Receive()); err != nil {
if err == redis.ErrNil {
err = nil
missed = append(missed, mid)
} else {
log.Error("conn.Receive error(%v)", err)
return
}
} else if cnt > 0 {
cachedUp = append(cachedUp, mid)
}
}
for _, mid := range mids {
if _, err = redis.Bool(conn.Receive()); err != nil {
log.Error("conn.Receive mid(%d) error(%v)", mid, err)
return
}
}
return
}
// ExpireUppersPassedCache expire uppers passed cache.
func (d *Dao) ExpireUppersPassedCache(c context.Context, mids []int64) (res map[int64]bool, err error) {
conn := d.upRds.Get(c)
defer conn.Close()
res = make(map[int64]bool, len(mids))
for _, mid := range mids {
key := upPasKey(mid)
if err = conn.Send("EXPIRE", key, d.upExpire); err != nil {
d.errProm.Incr("upper_redis")
log.Error("conn.Send(%s) error(%v)", key, err)
return
}
}
if err = conn.Flush(); err != nil {
log.Error("conn.Flush error(%v)", err)
return
}
var ok bool
for _, mid := range mids {
if ok, err = redis.Bool(conn.Receive()); err != nil {
d.errProm.Incr("upper_redis")
log.Error("conn.Receive() error(%v)", err)
return
}
res[mid] = ok
}
return
}
// AddUpperPassedCache add up paassed cache.
func (d *Dao) AddUpperPassedCache(c context.Context, mid int64, aids []int64, ptimes []time.Time, copyrights []int8) (err error) {
var (
key = upPasKey(mid)
conn = d.upRds.Get(c)
)
defer conn.Close()
for k, aid := range aids {
score := int64(ptimes[k]<<2) | int64(copyrights[k])
if err = conn.Send("ZADD", key, score, aid); err != nil {
d.errProm.Incr("upper_redis")
log.Error("conn.Send(ZADD, %s, %d, %d) error(%v)", key, aid, ptimes[k], err)
return
}
}
if err = conn.Flush(); err != nil {
d.errProm.Incr("upper_redis")
log.Error("conn.Flush error(%v)", err)
return
}
for i := 0; i < len(aids); i++ {
if _, err = conn.Receive(); err != nil {
d.errProm.Incr("upper_redis")
log.Error("conn.Receive error(%v)", err)
return
}
}
return
}
// DelUpperPassedCache delete up passed cache.
func (d *Dao) DelUpperPassedCache(c context.Context, mid, aid int64) (err error) {
var (
key = upPasKey(mid)
conn = d.upRds.Get(c)
)
defer conn.Close()
if _, err = conn.Do("ZREM", key, aid); err != nil {
d.errProm.Incr("upper_redis")
log.Error("conn.Do(ZERM, %s, %d) error(%v)", key, aid, err)
}
return
}

View File

@@ -0,0 +1,197 @@
package archive
import (
"context"
"testing"
"go-common/library/time"
"github.com/smartystreets/goconvey/convey"
)
func TestArchiveupCntKey(t *testing.T) {
var (
mid = int64(1)
)
convey.Convey("upCntKey", t, func(ctx convey.C) {
p1 := upCntKey(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestArchiveupPasKey(t *testing.T) {
var (
mid = int64(1)
)
convey.Convey("upPasKey", t, func(ctx convey.C) {
p1 := upPasKey(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestArchiveAddUpperCountCache(t *testing.T) {
var (
c = context.TODO()
mid = int64(1)
count = int64(10)
)
convey.Convey("AddUpperCountCache", t, func(ctx convey.C) {
err := d.AddUpperCountCache(c, mid, count)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestArchiveUpperCountCache(t *testing.T) {
var (
c = context.TODO()
mid = int64(1)
)
convey.Convey("UpperCountCache", t, func(ctx convey.C) {
count, err := d.UpperCountCache(c, mid)
ctx.Convey("Then err should be nil.count should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(count, convey.ShouldNotBeNil)
})
})
}
func TestArchiveUppersCountCache(t *testing.T) {
var (
c = context.TODO()
mids = []int64{1, 2}
)
convey.Convey("UppersCountCache", t, func(ctx convey.C) {
cached, missed, err := d.UppersCountCache(c, mids)
ctx.Convey("Then err should be nil.cached,missed should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(missed, convey.ShouldNotBeNil)
ctx.So(cached, convey.ShouldNotBeNil)
})
})
}
func TestArchiveUpperPassedCache(t *testing.T) {
var (
c = context.TODO()
mid = int64(1)
start = int(0)
end = int(10)
)
convey.Convey("UpperPassedCache", t, func(ctx convey.C) {
_, err := d.UpperPassedCache(c, mid, start, end)
ctx.Convey("Then err should be nil.aids should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestArchiveUppersPassedCacheWithScore(t *testing.T) {
var (
c = context.TODO()
mids = []int64{1, 2}
start = int(0)
end = int(10)
)
convey.Convey("UppersPassedCacheWithScore", t, func(ctx convey.C) {
aidm, err := d.UppersPassedCacheWithScore(c, mids, start, end)
ctx.Convey("Then err should be nil.aidm should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(aidm, convey.ShouldNotBeNil)
})
})
}
func TestArchiveUppersPassedCache(t *testing.T) {
var (
c = context.TODO()
mids = []int64{1, 2}
start = int(0)
end = int(10)
)
convey.Convey("UppersPassedCache", t, func(ctx convey.C) {
aidm, err := d.UppersPassedCache(c, mids, start, end)
ctx.Convey("Then err should be nil.aidm should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(aidm, convey.ShouldNotBeNil)
})
})
}
func TestArchiveExpireUpperPassedCache(t *testing.T) {
var (
c = context.TODO()
mid = int64(1)
)
convey.Convey("ExpireUpperPassedCache", t, func(ctx convey.C) {
ok, err := d.ExpireUpperPassedCache(c, mid)
ctx.Convey("Then err should be nil.ok should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(ok, convey.ShouldNotBeNil)
})
})
}
func TestArchiveExpireUppersCountCache(t *testing.T) {
var (
c = context.TODO()
mids = []int64{1, 2}
)
convey.Convey("ExpireUppersCountCache", t, func(ctx convey.C) {
cachedUp, missed, err := d.ExpireUppersCountCache(c, mids)
ctx.Convey("Then err should be nil.cachedUp,missed should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(missed, convey.ShouldNotBeNil)
ctx.So(cachedUp, convey.ShouldNotBeNil)
})
})
}
func TestArchiveExpireUppersPassedCache(t *testing.T) {
var (
c = context.TODO()
mids = []int64{1, 2}
)
convey.Convey("ExpireUppersPassedCache", t, func(ctx convey.C) {
res, err := d.ExpireUppersPassedCache(c, mids)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestArchiveAddUpperPassedCache(t *testing.T) {
var (
c = context.TODO()
mid = int64(1)
aids = []int64{1}
ptimes = []time.Time{1531553274}
copyrights = []int8{1}
)
convey.Convey("AddUpperPassedCache", t, func(ctx convey.C) {
err := d.AddUpperPassedCache(c, mid, aids, ptimes, copyrights)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestArchiveDelUpperPassedCache(t *testing.T) {
var (
c = context.TODO()
mid = int64(1)
aid = int64(1)
)
convey.Convey("DelUpperPassedCache", t, func(ctx convey.C) {
err := d.DelUpperPassedCache(c, mid, aid)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,85 @@
package archive
import (
"context"
"fmt"
"go-common/library/database/sql"
"go-common/library/xstr"
)
const (
_staffSQL = "SELECT aid FROM archive_staff WHERE staff_mid = ? AND state = 1"
_staffsSQL = "SELECT aid, staff_mid FROM archive_staff WHERE staff_mid IN (%s) AND state = 1"
_staffAidSQL = "SELECT staff_mid FROM archive_staff WHERE aid = ? AND state = 1"
)
// Staff get upper staff aids by mid.
func (d *Dao) Staff(c context.Context, mid int64) (aids []int64, err error) {
d.infoProm.Incr("Staff")
rows, err := d.archiveDB.Query(c, _staffSQL, mid)
if err != nil {
return
}
defer rows.Close()
for rows.Next() {
var aid int64
if err = rows.Scan(&aid); err != nil {
if err == sql.ErrNoRows {
err = nil
return
}
return
}
aids = append(aids, aid)
}
return
}
// Staffs get uppers staff aids by mids.
func (d *Dao) Staffs(c context.Context, mids []int64) (aidm map[int64][]int64, err error) {
d.infoProm.Incr("Staffs")
rows, err := d.archiveDB.Query(c, fmt.Sprintf(_staffsSQL, xstr.JoinInts(mids)))
if err != nil {
return
}
defer rows.Close()
aidm = make(map[int64][]int64, len(mids))
for rows.Next() {
var (
aid int64
staffMid int64
)
if err = rows.Scan(&aid, &staffMid); err != nil {
if err == sql.ErrNoRows {
err = nil
return
}
return
}
aidm[staffMid] = append(aidm[staffMid], aid)
}
return
}
// StaffAid get uppers staff mid-list by aid.
func (d *Dao) StaffAid(c context.Context, aid int64) (mids []int64, err error) {
d.infoProm.Incr("StaffAid")
rows, err := d.archiveDB.Query(c, _staffAidSQL, aid)
if err != nil {
return
}
defer rows.Close()
for rows.Next() {
var mid int64
if err = rows.Scan(&mid); err != nil {
if err == sql.ErrNoRows {
err = nil
return
}
return
}
mids = append(mids, mid)
}
return
}

View File

@@ -0,0 +1,56 @@
package archive
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestArchiveStaff(t *testing.T) {
convey.Convey("Staff", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(27515258)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
aids, err := d.Staff(c, mid)
ctx.Convey("Then err should be nil.aids should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(len(aids), convey.ShouldBeGreaterThanOrEqualTo, 0)
})
})
})
}
func TestArchiveStaffs(t *testing.T) {
convey.Convey("Staffs", t, func(ctx convey.C) {
var (
c = context.Background()
mids = []int64{27515258}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
aidm, err := d.Staffs(c, mids)
ctx.Convey("Then err should be nil.aidm should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(aidm, convey.ShouldNotBeNil)
})
})
})
}
func TestArchiveStaffAid(t *testing.T) {
convey.Convey("StaffAid", t, func(ctx convey.C) {
var (
c = context.Background()
aid = int64(10110188)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
mids, err := d.StaffAid(c, aid)
ctx.Convey("Then err should be nil.mids should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(mids, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,65 @@
package archive
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestArchiveUppersCount(t *testing.T) {
var (
c = context.TODO()
mids = []int64{1, 2}
)
convey.Convey("UppersCount", t, func(ctx convey.C) {
uc, err := d.UppersCount(c, mids)
ctx.Convey("Then err should be nil.uc should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(uc, convey.ShouldNotBeNil)
})
})
}
func TestArchiveUpperCount(t *testing.T) {
var (
c = context.TODO()
mid = int64(1)
)
convey.Convey("UpperCount", t, func(ctx convey.C) {
count, err := d.UpperCount(c, mid)
ctx.Convey("Then err should be nil.count should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(count, convey.ShouldNotBeNil)
})
})
}
func TestArchiveUpperPassed(t *testing.T) {
var (
c = context.TODO()
mid = int64(1)
)
convey.Convey("UpperPassed", t, func(ctx convey.C) {
_, _, _, err := d.UpperPassed(c, mid)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestArchiveUppersPassed(t *testing.T) {
var (
c = context.TODO()
mids = []int64{1}
)
convey.Convey("UppersPassed", t, func(ctx convey.C) {
aidm, ptimes, copyrights, err := d.UppersPassed(c, mids)
ctx.Convey("Then err should be nil.aidm,ptimes,copyrights should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(copyrights, convey.ShouldNotBeNil)
ctx.So(ptimes, convey.ShouldNotBeNil)
ctx.So(aidm, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,65 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"card.go",
"dao.go",
"rpc.go",
"up_base.go",
],
importpath = "go-common/app/service/main/up/dao/card",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/archive/api:go_default_library",
"//app/service/main/up/conf:go_default_library",
"//app/service/main/up/dao:go_default_library",
"//app/service/main/up/dao/global:go_default_library",
"//app/service/main/up/model:go_default_library",
"//library/database/sql:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/sync/errgroup:go_default_library",
"//library/xstr: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 = [
"card_test.go",
"dao_test.go",
"rpc_test.go",
"up_base_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/up/conf:go_default_library",
"//app/service/main/up/dao:go_default_library",
"//app/service/main/up/dao/global:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,282 @@
package card
import (
"context"
"fmt"
"go-common/app/service/main/up/model"
"go-common/library/database/sql"
"go-common/library/log"
"go-common/library/xstr"
)
const (
_UpInfoBaseColumn = `mid, name_cn, name_en, name_alias, signature, content, nationality,
nation, gender, blood_type, constellation, height, weight, birth_place, birth_date, occupation,
tags, masterpieces, school, location, interests, platform, platform_account`
_countUpSQL = "SELECT count(distinct mid) FROM card_up"
_listUpMidSQL = "SELECT mid FROM card_up order BY mtime DESC"
_listUpInfoSQL = "SELECT " + _UpInfoBaseColumn + " FROM card_up limit ? offset ?"
_getUpInfoByMidSQL = "SELECT " + _UpInfoBaseColumn + " FROM card_up WHERE mid=?"
_listUpVideoIDSQL = "SELECT avid FROM card_up_video WHERE mid=? ORDER BY id DESC"
_listUpImageSQL = "SELECT url, height, width FROM card_up_image WHERE mid=? ORDER BY id DESC"
_listUpAccountSQL = "SELECT url, title, picture, abstract FROM card_up_account WHERE mid = ?"
_listUpInfoByMidsSQL = "SELECT " + _UpInfoBaseColumn + " FROM card_up WHERE mid IN (%s)"
_listUpVideoIDByMidsSQL = "SELECT mid, avid FROM card_up_video WHERE mid IN (%s) ORDER BY id DESC"
_listUpImageByMidsSQL = "SELECT mid, url, height, width FROM card_up_image WHERE mid IN (%s) ORDER BY id DESC"
_listUpAccountByMidsSQL = "SELECT mid, url, title, picture, abstract FROM card_up_account WHERE mid IN (%s)"
)
// CountUpCard count up num
func (d *Dao) CountUpCard(ctx context.Context) (total int, err error) {
row := d.db.QueryRow(ctx, _countUpSQL)
err = row.Scan(&total)
if err != nil {
log.Error("CountUpCard row.Scan error(%v)", err)
}
return
}
// ListUpInfo page list up mids
func (d *Dao) ListUpInfo(ctx context.Context, offset uint, size uint) (infos []*model.UpCardInfo, err error) {
rows, err := d.db.Query(ctx, _listUpInfoSQL, size, offset)
if err != nil {
log.Error("ListUpInfo d.db.Query error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
info := &model.UpCardInfo{}
err = rows.Scan(&info.MID,
&info.NameCN, &info.NameEN, &info.NameAlias,
&info.Signature,
&info.Content, &info.Nationality, &info.Nation,
&info.Gender, &info.BloodType, &info.Constellation,
&info.Height, &info.Weight, &info.BirthPlace,
&info.BirthDate, &info.Occupation, &info.Tags,
&info.Masterpieces, &info.School, &info.Location,
&info.Interests, &info.Platform, &info.PlatformAccount)
if err != nil {
log.Error("ListUpInfo rows.Scan error(%v)", err)
return
}
infos = append(infos, info)
}
return
}
// MidUpInfoMap get <mid, UpInfo> map by mids
func (d *Dao) MidUpInfoMap(ctx context.Context, mids []int64) (midUpInfoMap map[int64]*model.UpCardInfo, err error) {
midUpInfoMap = make(map[int64]*model.UpCardInfo)
rows, err := d.db.Query(ctx, fmt.Sprintf(_listUpInfoByMidsSQL, xstr.JoinInts(mids)))
if err != nil {
log.Error("MidUpInfoMap d.db.Query error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
info := &model.UpCardInfo{}
err = rows.Scan(&info.MID,
&info.NameCN, &info.NameEN, &info.NameAlias,
&info.Signature,
&info.Content, &info.Nationality, &info.Nation,
&info.Gender, &info.BloodType, &info.Constellation,
&info.Height, &info.Weight, &info.BirthPlace,
&info.BirthDate, &info.Occupation, &info.Tags,
&info.Masterpieces, &info.School, &info.Location,
&info.Interests, &info.Platform, &info.PlatformAccount)
if err != nil {
log.Error("MidUpInfoMap rows.Scan error(%v)", err)
return
}
midUpInfoMap[info.MID] = info
}
return
}
// MidAccountsMap get <mid, Accounts> map by mids
func (d *Dao) MidAccountsMap(ctx context.Context, mids []int64) (midAccountsMap map[int64][]*model.UpCardAccount, err error) {
midAccountsMap = make(map[int64][]*model.UpCardAccount)
rows, err := d.db.Query(ctx, fmt.Sprintf(_listUpAccountByMidsSQL, xstr.JoinInts(mids)))
if err != nil {
log.Error("MidAccountsMap d.db.Query error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
var mid int64
account := new(model.UpCardAccount)
err = rows.Scan(&mid, &account.URL, &account.Title, &account.Picture, &account.Desc)
if err != nil {
log.Error("MidAccountsMap row.Scan error(%v)", err)
return
}
midAccountsMap[mid] = append(midAccountsMap[mid], account)
}
return
}
// MidImagesMap get <mid, Images> map by mids
func (d *Dao) MidImagesMap(ctx context.Context, mids []int64) (midImagesMap map[int64][]*model.UpCardImage, err error) {
midImagesMap = make(map[int64][]*model.UpCardImage)
rows, err := d.db.Query(ctx, fmt.Sprintf(_listUpImageByMidsSQL, xstr.JoinInts(mids)))
if err != nil {
log.Error("MidImagesMap d.db.Query error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
var mid int64
image := new(model.UpCardImage)
err = rows.Scan(&mid, &image.URL, &image.Height, &image.Width)
if err != nil {
log.Error("MidImagesMap row.Scan error(%v)", err)
return
}
midImagesMap[mid] = append(midImagesMap[mid], image)
}
return
}
// MidAvidsMap get <mid, Avids> map by mids
func (d *Dao) MidAvidsMap(ctx context.Context, mids []int64) (midAvidsMap map[int64][]int64, err error) {
midAvidsMap = make(map[int64][]int64)
rows, err := d.db.Query(ctx, fmt.Sprintf(_listUpVideoIDByMidsSQL, xstr.JoinInts(mids)))
if err != nil {
log.Error("MidAvidsMap d.db.Query error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
var mid int64
var avid int64
err = rows.Scan(&mid, &avid)
if err != nil {
log.Error("MidAvidsMap row.Scan error(%v)", err)
return
}
midAvidsMap[mid] = append(midAvidsMap[mid], avid)
}
return
}
// ListUpMID list up mids
func (d *Dao) ListUpMID(ctx context.Context) (mids []int64, err error) {
rows, err := d.db.Query(ctx, _listUpMidSQL)
if err != nil {
log.Error("ListCardBase d.db.Query error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
var mid int64
err = rows.Scan(&mid)
if err != nil {
log.Error("ListCardBase row.Scan error(%v)", err)
return
}
mids = append(mids, mid)
}
return
}
// GetUpInfo get up info by mid
func (d *Dao) GetUpInfo(ctx context.Context, mid int64) (card *model.UpCardInfo, err error) {
row := d.db.QueryRow(ctx, _getUpInfoByMidSQL, mid)
card = &model.UpCardInfo{}
if err = row.Scan(&card.MID,
&card.NameCN, &card.NameEN, &card.NameAlias,
&card.Signature,
&card.Content, &card.Nationality, &card.Nation,
&card.Gender, &card.BloodType, &card.Constellation,
&card.Height, &card.Weight, &card.BirthPlace,
&card.BirthDate, &card.Occupation, &card.Tags,
&card.Masterpieces, &card.School, &card.Location,
&card.Interests, &card.Platform, &card.PlatformAccount); err != nil {
if err == sql.ErrNoRows {
card = nil
err = nil
} else {
log.Error("GetUpCard row.Scan error(%v)", err)
return
}
}
return
}
// ListUpAccount list up accounts by mid
func (d *Dao) ListUpAccount(ctx context.Context, mid int64) (accounts []*model.UpCardAccount, err error) {
rows, err := d.db.Query(ctx, _listUpAccountSQL, mid)
if err != nil {
log.Error("listUpAccount d.db.Query error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
account := new(model.UpCardAccount)
err = rows.Scan(&account.URL, &account.Title, &account.Picture, &account.Desc)
if err != nil {
log.Error("listUpAccount row.Scan error(%v)", err)
return
}
accounts = append(accounts, account)
}
return
}
// ListUpImage list up images by mid
func (d *Dao) ListUpImage(ctx context.Context, mid int64) (images []*model.UpCardImage, err error) {
rows, err := d.db.Query(ctx, _listUpImageSQL, mid)
if err != nil {
log.Error("listUpImage d.db.Query error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
image := new(model.UpCardImage)
err = rows.Scan(&image.URL, &image.Height, &image.Width)
if err != nil {
log.Error("listUpImage row.Scan error(%v)", err)
return
}
images = append(images, image)
}
return
}
// ListAVID list avids by mid
func (d *Dao) ListAVID(ctx context.Context, mid int64) (avids []int64, err error) {
rows, err := d.db.Query(ctx, _listUpVideoIDSQL, mid)
if err != nil {
log.Error("listUpVideo d.db.Query error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
var avid int64
err = rows.Scan(&avid)
if err != nil {
log.Error("listUpVideo row.Scan error(%v)", err)
return
}
avids = append(avids, avid)
}
return
}

View File

@@ -0,0 +1,148 @@
package card
import (
"context"
"github.com/smartystreets/goconvey/convey"
"testing"
)
func TestCountUpCard(t *testing.T) {
var c = context.Background()
convey.Convey("CountUpCard", t, func(ctx convey.C) {
total, err := d.CountUpCard(c)
ctx.Convey("Then err should be nil.total should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(total, convey.ShouldNotBeNil)
})
})
}
func TestPageListUpInfo(t *testing.T) {
var (
c = context.Background()
offset = uint(1)
size = uint(1)
)
convey.Convey("ListUpInfo", t, func(ctx convey.C) {
infos, err := d.ListUpInfo(c, offset, size)
ctx.Convey("Then err should be nil.infos should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(infos, convey.ShouldNotBeNil)
})
})
}
func TestListUpMID(t *testing.T) {
var c = context.Background()
convey.Convey("ListUpMID", t, func(ctx convey.C) {
mids, err := d.ListUpMID(c)
ctx.Convey("Then err should be nil.mids should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(mids, convey.ShouldNotBeNil)
})
})
}
func TestGetUpInfo(t *testing.T) {
var (
c = context.Background()
mid = int64(1532165)
)
convey.Convey("GetUpInfo", t, func(ctx convey.C) {
upInfo, err := d.GetUpInfo(c, mid)
ctx.Convey("Then err should be nil.upInfo should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(upInfo, convey.ShouldNotBeNil)
})
})
}
func TestListUpAccount(t *testing.T) {
var (
c = context.Background()
mid = int64(1532165)
)
convey.Convey("ListUpAccount", t, func(ctx convey.C) {
accounts, err := d.ListUpAccount(c, mid)
ctx.Convey("Then err should be nil.accounts should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(accounts, convey.ShouldNotBeNil)
})
})
}
func TestListUpImage(t *testing.T) {
var (
c = context.Background()
mid = int64(1532165)
)
convey.Convey("ListUpImage", t, func(ctx convey.C) {
images, err := d.ListUpImage(c, mid)
ctx.Convey("Then err should be nil.images should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(images, convey.ShouldNotBeNil)
})
})
}
func TestListAVID(t *testing.T) {
var (
c = context.Background()
mid = int64(1532165)
)
convey.Convey("ListAVID", t, func(ctx convey.C) {
avids, err := d.ListAVID(c, mid)
ctx.Convey("Then err should be nil.avids should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(avids, convey.ShouldNotBeNil)
})
})
}
func TestMidUpInfoMap(t *testing.T) {
var (
c = context.Background()
mids = []int64{1532165}
)
convey.Convey("MidUpInfoMap", t, func(ctx convey.C) {
res, err := d.MidUpInfoMap(c, mids)
ctx.Convey("Then err should be nil.res should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestMidAccountsMap(t *testing.T) {
var (
c = context.Background()
mids = []int64{1532165}
)
convey.Convey("MidAccountsMap", t, func(ctx convey.C) {
res, err := d.MidAccountsMap(c, mids)
ctx.Convey("Then err should be nil.res should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestMidImagesMap(t *testing.T) {
var (
c = context.Background()
mids = []int64{1532165}
)
convey.Convey("MidImagesMap", t, func(ctx convey.C) {
res, err := d.MidImagesMap(c, mids)
ctx.Convey("Then err should be nil.res should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestMidAvidsMap(t *testing.T) {
var (
c = context.Background()
mids = []int64{1532165}
)
convey.Convey("MidAvidsMap", t, func(ctx convey.C) {
res, err := d.MidAvidsMap(c, mids)
ctx.Convey("Then err should be nil.res should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,36 @@
package card
import (
"context"
"go-common/app/service/main/up/conf"
"go-common/app/service/main/up/dao/global"
"go-common/library/database/sql"
)
// Dao is redis dao.
type Dao struct {
c *conf.Config
db *sql.DB
}
// New fn
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
db: global.GetUpCrmDB(),
}
return d
}
// Close fn
func (d *Dao) Close() {
if d.db != nil {
d.db.Close()
}
}
// Ping ping cpdb
func (d *Dao) Ping(c context.Context) (err error) {
return d.db.Ping(c)
}

View File

@@ -0,0 +1,42 @@
package card
import (
"flag"
"os"
"testing"
"go-common/app/service/main/up/conf"
"go-common/app/service/main/up/dao"
"go-common/app/service/main/up/dao/global"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", dao.AppID)
flag.Set("conf_token", dao.UatToken)
flag.Set("tree_id", dao.TreeID)
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/up-service.toml")
}
if os.Getenv("UT_LOCAL_TEST") != "" {
flag.Set("conf", "../../cmd/up-service.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
global.Init(conf.Conf)
d = New(conf.Conf)
m.Run()
os.Exit(0)
}

View File

@@ -0,0 +1,97 @@
package card
import (
"context"
"fmt"
"sync"
arcgrpc "go-common/app/service/main/archive/api"
"go-common/app/service/main/up/dao"
"go-common/app/service/main/up/dao/global"
"go-common/app/service/main/up/model"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/sync/errgroup"
)
const _avURL = "http://www.bilibili.com/video/av%d"
//ListVideoArchive list videos by avids
func (d *Dao) ListVideoArchive(ctx context.Context, avids []int64) (videos []*model.UpCardVideo, err error) {
archives, err := d.listArchives(ctx, avids)
if err != nil {
log.Error("d.listArchives error(%v) arg(%v)", err, avids)
err = ecode.CreativeArcServiceErr
return
}
for avid, data := range archives {
video := transfer(avid, data)
videos = append(videos, video)
}
return
}
//AvidVideoMap get <avid, video> map by avids
func (d *Dao) AvidVideoMap(ctx context.Context, avids []int64) (avidVideoMap map[int64]*model.UpCardVideo, err error) {
avidVideoMap = make(map[int64]*model.UpCardVideo)
archives, err := d.listArchives(ctx, avids)
if err != nil {
log.Error("d.listArchives error(%v) arg(%v)", err, avids)
err = ecode.CreativeArcServiceErr
return
}
for avid, data := range archives {
video := transfer(avid, data)
avidVideoMap[avid] = video
}
return
}
func (d *Dao) listArchives(ctx context.Context, avids []int64) (archives map[int64]*arcgrpc.Arc, err error) {
archives = make(map[int64]*arcgrpc.Arc)
var (
g errgroup.Group
m sync.Mutex
)
dao.Split(0, len(avids), 300, func(start int, end int) {
g.Go(func() (err error) {
var (
arg = &arcgrpc.ArcsRequest{
Aids: avids[start:end],
}
res *arcgrpc.ArcsReply
)
if res, err = global.GetArcClient().Arcs(ctx, arg); err != nil {
log.Error("d.acc.Archives3 arg(%v) error(%v)", arg, err)
err = nil
} else {
for k, v := range res.Arcs {
m.Lock()
archives[k] = v
m.Unlock()
}
}
return
})
})
if err = g.Wait(); err != nil {
log.Error("g.Wait() error(%v)", err)
}
return
}
func transfer(avid int64, archive *arcgrpc.Arc) (video *model.UpCardVideo) {
return &model.UpCardVideo{
URL: fmt.Sprintf(_avURL, avid),
Title: archive.Title,
Picture: archive.Pic,
Duration: archive.Duration,
CTime: archive.Ctime,
}
}

View File

@@ -0,0 +1,35 @@
package card
import (
"context"
"github.com/smartystreets/goconvey/convey"
"testing"
)
func TestListVideoArchive(t *testing.T) {
var (
c = context.TODO()
avids = []int64{31908629}
)
convey.Convey("Info", t, func(ctx convey.C) {
videos, err := d.ListVideoArchive(c, avids)
ctx.Convey("Then err should be nil.videos should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(videos, convey.ShouldNotBeNil)
})
})
}
func TestAvidVideoMap(t *testing.T) {
var (
c = context.TODO()
avids = []int64{31908629}
)
convey.Convey("Info", t, func(ctx convey.C) {
avidVideoMap, err := d.AvidVideoMap(c, avids)
ctx.Convey("Then err should be nil.midVideosMap should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(avidVideoMap, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,34 @@
package card
import (
"context"
"fmt"
"go-common/library/log"
)
const _listUpBaseSQL = "SELECT id, mid FROM up_base_info WHERE id > ? AND business_type = 1 %s LIMIT ?"
// ListUpBase list <id, mid> k-v pairs
func (d *Dao) ListUpBase(c context.Context, size int, lastID int64, where string) (idMids map[int64]int64, err error) {
idMids = make(map[int64]int64)
rows, err := d.db.Query(c, fmt.Sprintf(_listUpBaseSQL, where), lastID, size)
if err != nil {
log.Error("ListUpBase d.db.Query error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
var mid int64
var id int64
err = rows.Scan(&id, &mid)
if err != nil {
log.Error("ListUpBase rows.Scan error(%v)", err)
return
}
idMids[id] = mid
}
return
}

View File

@@ -0,0 +1,26 @@
package card
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestCardListUpBase(t *testing.T) {
convey.Convey("ListUpBase", t, func(ctx convey.C) {
var (
c = context.Background()
size = int(3)
lastID = int64(1)
where = "AND activity = 1"
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
idMids, err := d.ListUpBase(c, size, lastID, where)
ctx.Convey("Then err should be nil.idMids should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(idMids, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,60 @@
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",
"field_test.go",
"hbase_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/up/conf:go_default_library",
"//app/service/main/up/dao:go_default_library",
"//library/database/hbase.v2:go_default_library",
"//vendor/github.com/bouk/monkey:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
"//vendor/github.com/tsuna/gohbase/hrpc:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"field.go",
"hbase.go",
],
importpath = "go-common/app/service/main/up/dao/data",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/up/conf:go_default_library",
"//app/service/main/up/model/data:go_default_library",
"//library/database/hbase.v2:go_default_library",
"//library/ecode:go_default_library",
"//library/log: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,24 @@
package data
import (
"go-common/app/service/main/up/conf"
"go-common/library/database/hbase.v2"
"time"
)
//Dao hbase dao
type Dao struct {
c *conf.Config
hbase *hbase.Client
hbaseTimeOut time.Duration
}
//New create dao
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
hbase: hbase.NewClient(&c.HBase.Config),
hbaseTimeOut: time.Millisecond * 500,
}
return
}

View File

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

View File

@@ -0,0 +1,94 @@
package data
var (
//HBaseVideoTablePrefix 播放流失分布
HBaseVideoTablePrefix = "video_play_churn_"
//HBaseArchiveTablePrefix 分类分端播放
HBaseArchiveTablePrefix = "video_play_category_"
//HBaseAreaTablePrefix 地区播放
HBaseAreaTablePrefix = "video_play_area_"
//HBaseUpStatTablePrefix up主概况
HBaseUpStatTablePrefix = "up_stats_"
//HBaseUpViewerBase 观众数据,性别年龄分布 + 设备分布
HBaseUpViewerBase = "up_viewer_base_"
//HBaseUpViewerArea 地区分布
HBaseUpViewerArea = "up_viewer_area_"
//HBaseUpViewerTrend 内容倾向
HBaseUpViewerTrend = "up_viewer_trend_"
//HBaseUpViewerActionHour 行为时间分布
HBaseUpViewerActionHour = "up_viewer_action_hour_"
//HBaseUpRelationFansDay 日维度 最近30天 只保留31天
HBaseUpRelationFansDay = "up_relation_fans_day"
// HBaseUpRelationFansHistory 日维度 各月份每日数据,日更,永久保存
HBaseUpRelationFansHistory = "up_relation_fans_history"
//HBaseUpRelationFansMonth 年维度 2017.8月以后的数据永久保存
HBaseUpRelationFansMonth = "up_relation_fans_month"
//HBaseUpPlayInc 我的概况 播放相关
HBaseUpPlayInc = "up_play_inc_"
//HBaseUpDmInc 弹幕相关
HBaseUpDmInc = "up_dm_inc_"
//HBaseUpReplyInc 评论相关
HBaseUpReplyInc = "up_reply_inc_"
//HBaseUpShareInc 分享相关
HBaseUpShareInc = "up_share_inc_"
//HBaseUpCoinInc 投币相关
HBaseUpCoinInc = "up_coin_inc_"
//HBaseUpFavInc 收藏相关
HBaseUpFavInc = "up_fav_inc_"
//HBaseUpElecInc 充电相关
HBaseUpElecInc = "up_elec_inc_"
//HBaseUpFansAnalysis 粉丝管理
HBaseUpFansAnalysis = "up_fans_analysis"
//HBaseUpPlaySourceAnalysis 播放来源
HBaseUpPlaySourceAnalysis = "up_play_analysis"
//HBaseUpArcPlayAnalysis 平均观看时长、播放用户数、留存率
HBaseUpArcPlayAnalysis = "up_archive_play_analysis"
//HBaseUpArcQuery 稿件索引表
HBaseUpArcQuery = "up_archive_query"
//HBasePlayArc 播放相关 archive for 30 days
HBasePlayArc = "up_play_trend"
//HBaseDmArc 弹幕相关
HBaseDmArc = "up_dm_trend"
//HBaseReplyArc 评论相关
HBaseReplyArc = "up_reply_trend"
//HBaseShareArc 分享相关
HBaseShareArc = "up_share_trend"
//HBaseCoinArc 投币相关
HBaseCoinArc = "up_coin_trend"
//HBaseFavArc 收藏相关
HBaseFavArc = "up_fav_trend"
//HBaseElecArc 充电相关
HBaseElecArc = "up_elec_trend"
//HBaseFamilyPlat family
HBaseFamilyPlat = []byte("v")
//HBaseColumnAid aid
HBaseColumnAid = []byte("avid")
//HBaseColumnWebPC pc
HBaseColumnWebPC = []byte("plat0")
//HBaseColumnWebH5 h5
HBaseColumnWebH5 = []byte("plat1")
//HBaseColumnOutsite out
HBaseColumnOutsite = []byte("plat2")
//HBaseColumnIOS ios
HBaseColumnIOS = []byte("plat3")
//HBaseColumnAndroid android
HBaseColumnAndroid = []byte("plat4")
//HBaseColumnElse else
HBaseColumnElse = []byte("else")
//HBaseColumnFans fans
HBaseColumnFans = []byte("fans")
//HBaseColumnGuest guest
HBaseColumnGuest = []byte("guest")
//HBaseColumnAll all
HBaseColumnAll = []byte("all")
//HBaseColumnCoin coin
HBaseColumnCoin = []byte("coin")
//HBaseColumnElec elec
HBaseColumnElec = []byte("elec")
//HBaseColumnFav fav
HBaseColumnFav = []byte("fav")
//HBaseColumnShare share
HBaseColumnShare = []byte("share")
)

View File

@@ -0,0 +1 @@
package data

View File

@@ -0,0 +1,62 @@
package data
import (
"bytes"
"context"
"crypto/md5"
"encoding/hex"
"go-common/app/service/main/up/model/data"
"go-common/library/ecode"
"go-common/library/log"
"strconv"
)
func hbaseMd5Key(aid int64) []byte {
hasher := md5.New()
hasher.Write([]byte(strconv.Itoa(int(aid))))
return []byte(hex.EncodeToString(hasher.Sum(nil)))
}
// BaseUpStat get base up stat.
func (d *Dao) BaseUpStat(c context.Context, mid int64, date string) (stat *data.UpBaseStat, err error) {
var (
ctx, cancel = context.WithTimeout(c, d.hbaseTimeOut)
tableName = HBaseUpStatTablePrefix + date // change table at 12:00am
)
defer cancel()
result, err := d.hbase.Get(ctx, []byte(tableName), hbaseMd5Key(mid))
if err != nil {
log.Error("BaseUpStat d.hbase.Get BackupTable(%s, %d) error(%v)", tableName, mid, err)
err = ecode.ServerErr
return
}
if result == nil {
log.Error("BaseUpStat d.hbase.Get BackupTable(%s, %d) result nil", tableName, mid)
return
}
stat = &data.UpBaseStat{}
for _, c := range result.Cells {
if c == nil {
continue
}
v, _ := strconv.ParseInt(string(c.Value[:]), 10, 64)
if !bytes.Equal(c.Family, []byte("u")) {
continue
}
switch {
case bytes.Equal(c.Qualifier, []byte("play")):
stat.View = v
case bytes.Equal(c.Qualifier, []byte("dm")):
stat.Dm = v
case bytes.Equal(c.Qualifier, []byte("reply")):
stat.Reply = v
case bytes.Equal(c.Qualifier, []byte("fans")):
stat.Fans = v
case bytes.Equal(c.Qualifier, []byte("fav")):
stat.Fav = v
case bytes.Equal(c.Qualifier, []byte("like")):
stat.Like = v
}
}
return
}

View File

@@ -0,0 +1,53 @@
package data
import (
"context"
"github.com/bouk/monkey"
"github.com/tsuna/gohbase/hrpc"
"go-common/library/database/hbase.v2"
"reflect"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDatahbaseMd5Key(t *testing.T) {
var (
aid = int64(0)
)
convey.Convey("hbaseMd5Key", t, func(ctx convey.C) {
p1 := hbaseMd5Key(aid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestDataBaseUpStat(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
date = ""
)
// Hbase never ok
convey.Convey("BaseUpStat", t, func(ctx convey.C) {
guard := monkey.PatchInstanceMethod(reflect.TypeOf(d.hbase), "Get", func(_ *hbase.Client, _ context.Context, _ []byte, _ []byte, _ ...func(hrpc.Call) error) (*hrpc.Result, error) {
cells := make([]*hrpc.Cell, 5)
for i := range cells {
cell := new(hrpc.Cell)
cell.Value = []byte("test")
cells[i] = cell
}
res := &hrpc.Result{
Cells: cells,
}
return res, nil
})
defer guard.Unpatch()
stat, err := d.BaseUpStat(c, mid, date)
ctx.Convey("Then err should be nil.stat should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(stat, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,48 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["resource_test.go"],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//app/service/main/up/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["resource.go"],
importpath = "go-common/app/service/main/up/dao/global",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/account/api:go_default_library",
"//app/service/main/archive/api:go_default_library",
"//app/service/main/up/conf:go_default_library",
"//library/database/sql:go_default_library",
"//library/sync/pipeline/fanout:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,59 @@
package global
import (
"runtime"
accgrpc "go-common/app/service/main/account/api"
arcgrpc "go-common/app/service/main/archive/api"
"go-common/app/service/main/up/conf"
"go-common/library/database/sql"
"go-common/library/sync/pipeline/fanout"
"github.com/pkg/errors"
)
var (
upCrmDB *sql.DB
worker *fanout.Fanout
arcCli arcgrpc.ArchiveClient
accCli accgrpc.AccountClient
)
// GetArcClient .
func GetArcClient() arcgrpc.ArchiveClient {
return arcCli
}
// GetAccClient .
func GetAccClient() accgrpc.AccountClient {
return accCli
}
// GetWorker .
func GetWorker() *fanout.Fanout {
return worker
}
// GetUpCrmDB .
func GetUpCrmDB() *sql.DB {
return upCrmDB
}
//Init init global
func Init(c *conf.Config) {
var err error
if arcCli, err = arcgrpc.NewClient(c.GRPCClient.Archive); err != nil {
panic(errors.WithMessage(err, "Failed to dial archive service"))
}
if accCli, err = accgrpc.NewClient(c.GRPCClient.Account); err != nil {
panic(errors.WithMessage(err, "Failed to dial account service"))
}
upCrmDB = sql.NewMySQL(c.DB.UpCRM)
worker = fanout.New("cache", fanout.Worker(runtime.NumCPU()), fanout.Buffer(1024))
}
// Close .
func Close() {
upCrmDB.Close()
worker.Close()
}

View File

@@ -0,0 +1,100 @@
package global
import (
"flag"
"os"
"testing"
"go-common/app/service/main/up/conf"
"github.com/smartystreets/goconvey/convey"
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.up-service")
flag.Set("conf_token", "5f1660060bb011e8865c66d44b23cda7")
flag.Set("tree_id", "15572")
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/up-service.toml")
}
if os.Getenv("UT_LOCAL_TEST") != "" {
flag.Set("conf", "../../cmd/up-service.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
Init(conf.Conf)
os.Exit(m.Run())
}
func TestGlobalGetArcClient(t *testing.T) {
convey.Convey("GetArcClient", t, func(convCtx convey.C) {
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
p1 := GetArcClient()
convCtx.Convey("Then p1 should not be nil.", func(convCtx convey.C) {
convCtx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestGlobalGetAccClient(t *testing.T) {
convey.Convey("GetAccClient", t, func(convCtx convey.C) {
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
p1 := GetAccClient()
convCtx.Convey("Then p1 should not be nil.", func(convCtx convey.C) {
convCtx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestGlobalGetWorker(t *testing.T) {
convey.Convey("GetWorker", t, func(convCtx convey.C) {
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
p1 := GetWorker()
convCtx.Convey("Then p1 should not be nil.", func(convCtx convey.C) {
convCtx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestGlobalGetUpCrmDB(t *testing.T) {
convey.Convey("GetUpCrmDB", t, func(convCtx convey.C) {
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
p1 := GetUpCrmDB()
convCtx.Convey("Then p1 should not be nil.", func(convCtx convey.C) {
convCtx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestGlobalInit(t *testing.T) {
convey.Convey("Init", t, func(convCtx convey.C) {
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
Init(conf.Conf)
convCtx.Convey("No return values", func(convCtx convey.C) {
})
})
})
}
func TestGlobalClose(t *testing.T) {
convey.Convey("Close", t, func(convCtx convey.C) {
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
Close()
convCtx.Convey("No return values", func(convCtx convey.C) {
})
})
})
}

View File

@@ -0,0 +1,75 @@
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.cache_test.go",
"dao_test.go",
"mc.cache_test.go",
"up_group_test.go",
"up_mc_test.go",
"up_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/up/api/v1:go_default_library",
"//app/service/main/up/conf:go_default_library",
"//app/service/main/up/dao:go_default_library",
"//app/service/main/up/dao/global:go_default_library",
"//app/service/main/up/model:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"dao.cache.go",
"dao.go",
"mc.cache.go",
"up.go",
"up_group.go",
"up_mc.go",
],
importpath = "go-common/app/service/main/up/dao/manager",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/up/api/v1:go_default_library",
"//app/service/main/up/conf:go_default_library",
"//app/service/main/up/dao:go_default_library",
"//app/service/main/up/dao/global:go_default_library",
"//app/service/main/up/model:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/database/sql:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/stat/prom:go_default_library",
"//library/sync/errgroup:go_default_library",
"//library/sync/pipeline/fanout:go_default_library",
"//library/xstr: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,139 @@
// Code generated by $GOPATH/src/go-common/app/tool/cache/gen. DO NOT EDIT.
/*
Package manager is a generated cache proxy package.
It is generated from:
type _cache interface {
// cache: -nullcache=&upgrpc.UpSpecial{GroupIDs:[]int64{-1}} -check_null_code=$!=nil&&len($.GroupIDs)>0&&$.GroupIDs[0]==-1
UpSpecial(c context.Context, mid int64) (us *upgrpc.UpSpecial, err error)
// cache: -batch=100 -max_group=1 -batch_err=break -nullcache=&upgrpc.UpSpecial{GroupIDs:[]int64{-1}} -check_null_code=$!=nil&&len($.GroupIDs)>0&&$.GroupIDs[0]==-1
UpsSpecial(c context.Context, mids []int64) (map[int64]*upgrpc.UpSpecial, error)
}
*/
package manager
import (
"context"
"sync"
upgrpc "go-common/app/service/main/up/api/v1"
"go-common/library/stat/prom"
"go-common/library/sync/errgroup"
)
var _ _cache
// UpSpecial get data from cache if miss will call source method, then add to cache.
func (d *Dao) UpSpecial(c context.Context, id int64) (res *upgrpc.UpSpecial, err error) {
addCache := true
res, err = d.CacheUpSpecial(c, id)
if err != nil {
addCache = false
err = nil
}
defer func() {
if res != nil && len(res.GroupIDs) > 0 && res.GroupIDs[0] == -1 {
res = nil
}
}()
if res != nil {
prom.CacheHit.Incr("UpSpecial")
return
}
prom.CacheMiss.Incr("UpSpecial")
res, err = d.RawUpSpecial(c, id)
if err != nil {
return
}
miss := res
if miss == nil {
miss = &upgrpc.UpSpecial{GroupIDs: []int64{-1}}
}
if !addCache {
return
}
d.cache.Do(c, func(c context.Context) {
d.AddCacheUpSpecial(c, id, miss)
})
return
}
// UpsSpecial get data from cache if miss will call source method, then add to cache.
func (d *Dao) UpsSpecial(c context.Context, keys []int64) (res map[int64]*upgrpc.UpSpecial, err error) {
if len(keys) == 0 {
return
}
addCache := true
if res, err = d.CacheUpsSpecial(c, keys); err != nil {
addCache = false
res = nil
err = nil
}
var miss []int64
for _, key := range keys {
if (res == nil) || (res[key] == nil) {
miss = append(miss, key)
}
}
prom.CacheHit.Add("UpsSpecial", int64(len(keys)-len(miss)))
for k, v := range res {
if v != nil && len(v.GroupIDs) > 0 && v.GroupIDs[0] == -1 {
delete(res, k)
}
}
missLen := len(miss)
if missLen == 0 {
return
}
missData := make(map[int64]*upgrpc.UpSpecial, missLen)
prom.CacheMiss.Add("UpsSpecial", int64(missLen))
var mutex sync.Mutex
group, ctx := errgroup.WithContext(c)
if missLen > 1 {
group.GOMAXPROCS(1)
}
var run = func(ms []int64) {
group.Go(func() (err error) {
data, err := d.RawUpsSpecial(ctx, ms)
mutex.Lock()
for k, v := range data {
missData[k] = v
}
mutex.Unlock()
return
})
}
var (
i int
n = missLen / 100
)
for i = 0; i < n; i++ {
run(miss[i*n : (i+1)*n])
}
if len(miss[i*n:]) > 0 {
run(miss[i*n:])
}
err = group.Wait()
if res == nil {
res = make(map[int64]*upgrpc.UpSpecial, len(keys))
}
for k, v := range missData {
res[k] = v
}
if err != nil {
return
}
for _, key := range miss {
if res[key] == nil {
missData[key] = &upgrpc.UpSpecial{GroupIDs: []int64{-1}}
}
}
if !addCache {
return
}
d.cache.Do(c, func(c context.Context) {
d.AddCacheUpsSpecial(c, missData)
})
return
}

View File

@@ -0,0 +1,40 @@
package manager
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestManagerUpSpecial(t *testing.T) {
convey.Convey("UpSpecial", t, func(convCtx convey.C) {
var (
c = context.Background()
id = int64(27515256)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := d.UpSpecial(c, id)
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestManagerUpsSpecial(t *testing.T) {
convey.Convey("UpsSpecial", t, func(convCtx convey.C) {
var (
c = context.Background()
keys = []int64{27515256}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := d.UpsSpecial(c, keys)
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,146 @@
package manager
import (
"context"
gosql "database/sql"
"net/url"
"strings"
"time"
"go-common/app/service/main/up/conf"
"go-common/app/service/main/up/dao/global"
"go-common/library/cache/memcache"
"go-common/library/database/sql"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/sync/pipeline/fanout"
"go-common/library/xstr"
)
const (
//URLUNames url for names
URLUNames = "/x/admin/manager/users/unames"
//URLUids url for uids
URLUids = "/x/admin/manager/users/uids"
)
// Dao is redis dao.
type Dao struct {
c *conf.Config
managerDB *sql.DB
HTTPClient *bm.Client
// cache tool
cache *fanout.Fanout
// mc
mc *memcache.Pool
// upSpecial expiration
upSpecialExpire int32
}
// New fn
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
managerDB: sql.NewMySQL(c.DB.Manager),
// http client
HTTPClient: bm.NewClient(c.HTTPClient.Normal),
mc: memcache.NewPool(c.Memcache.Up),
upSpecialExpire: int32(time.Duration(c.Memcache.UpSpecialExpire) / time.Second),
cache: global.GetWorker(),
}
return d
}
// Close fn
func (d *Dao) Close() {
if d.managerDB != nil {
d.managerDB.Close()
}
}
// Ping ping cpdb
func (d *Dao) Ping(c context.Context) (err error) {
return d.managerDB.Ping(c)
}
func prepareAndExec(c context.Context, db *sql.DB, sqlstr string, args ...interface{}) (res gosql.Result, err error) {
var stmt *sql.Stmt
stmt, err = db.Prepare(sqlstr)
if err != nil {
log.Error("stmt prepare fail, error(%v), sql=%s", err, sqlstr)
return
}
defer stmt.Close()
res, err = stmt.Exec(c, args...)
if err != nil {
log.Error("data base fail, err=%v", err)
return
}
return
}
func prepareAndQuery(c context.Context, db *sql.DB, sqlstr string, args ...interface{}) (rows *sql.Rows, err error) {
var stmt *sql.Stmt
stmt, err = db.Prepare(sqlstr)
if err != nil {
log.Error("stmt prepare fail, error(%v), sql=%s", err, sqlstr)
return
}
defer stmt.Close()
rows, err = stmt.Query(c, args...)
if err != nil {
log.Error("data base fail, err=%v", err)
return
}
return
}
//GetUNamesByUids get uname by uid
func (d *Dao) GetUNamesByUids(c context.Context, uids []int64) (res map[int64]string, err error) {
var param = url.Values{}
var uidStr = xstr.JoinInts(uids)
param.Set("uids", uidStr)
var httpRes struct {
Code int `json:"code"`
Data map[int64]string `json:"data"`
Message string `json:"message"`
}
err = d.HTTPClient.Get(c, d.c.Host.Manager+URLUNames, "", param, &httpRes)
if err != nil {
log.Error("d.client.Get(%s) error(%v)", d.c.Host.Manager+URLUNames+"?"+param.Encode(), err)
return
}
if httpRes.Code != 0 {
log.Error("url(%s) error(%v), code(%d), message(%s)", d.c.Host.Manager+URLUNames+"?"+param.Encode(), err, httpRes.Code, httpRes.Message)
}
res = httpRes.Data
return
}
//GetUIDByNames get uid by uname
func (d *Dao) GetUIDByNames(c context.Context, names []string) (res map[string]int64, err error) {
var param = url.Values{}
var namesStr = strings.Join(names, ",")
param.Set("unames", namesStr)
var httpRes struct {
Code int `json:"code"`
Data map[string]int64 `json:"data"`
Message string `json:"message"`
}
err = d.HTTPClient.Get(c, d.c.Host.Manager+URLUids, "", param, &httpRes)
if err != nil {
log.Error("d.client.Get(%s) error(%v)", d.c.Host.Manager+URLUids+"?"+param.Encode(), err)
return
}
if httpRes.Code != 0 {
log.Error("url(%s) error(%v), code(%d), message(%s)", d.c.Host.Manager+URLUids+"?"+param.Encode(), err, httpRes.Code, httpRes.Message)
}
res = httpRes.Data
return
}

View File

@@ -0,0 +1,119 @@
package manager
import (
"context"
"flag"
"os"
"testing"
"go-common/app/service/main/up/conf"
"go-common/app/service/main/up/dao"
"go-common/app/service/main/up/dao/global"
"go-common/library/net/http/blademaster"
"github.com/smartystreets/goconvey/convey"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", dao.AppID)
flag.Set("conf_token", dao.UatToken)
flag.Set("tree_id", dao.TreeID)
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/up-service.toml")
}
if os.Getenv("UT_LOCAL_TEST") != "" {
flag.Set("conf", "../../cmd/up-service.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
global.Init(conf.Conf)
d = New(conf.Conf)
d.HTTPClient = blademaster.NewClient(conf.Conf.HTTPClient.Normal)
m.Run()
os.Exit(0)
}
func TestManagerPing(t *testing.T) {
var (
c = context.TODO()
)
convey.Convey("Ping", t, func(ctx convey.C) {
err := d.Ping(c)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestManagerprepareAndExec(t *testing.T) {
var (
c = context.TODO()
db = d.managerDB
sqlstr = _selectByID
args = interface{}(0)
)
convey.Convey("prepareAndExec", t, func(ctx convey.C) {
res, err := prepareAndExec(c, db, sqlstr, args)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestManagerprepareAndQuery(t *testing.T) {
var (
c = context.TODO()
db = d.managerDB
sqlstr = _selectByID
args = interface{}(0)
)
convey.Convey("prepareAndQuery", t, func(ctx convey.C) {
rows, err := prepareAndQuery(c, db, sqlstr, args)
ctx.Convey("Then err should be nil.rows should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(rows, convey.ShouldNotBeNil)
})
})
}
func TestManagerGetUNamesByUids(t *testing.T) {
var (
c = context.TODO()
uids = []int64{100}
)
convey.Convey("GetUNamesByUids", t, func(ctx convey.C) {
res, err := d.GetUNamesByUids(c, uids)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestManagerGetUIDByNames(t *testing.T) {
var (
c = context.TODO()
names = []string{"wangzhe01"}
)
convey.Convey("GetUIDByNames", t, func(ctx convey.C) {
res, err := d.GetUIDByNames(c, names)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,172 @@
// Code generated by $GOPATH/src/go-common/app/tool/cache/mc. DO NOT EDIT.
/*
Package manager is a generated mc cache package.
It is generated from:
type _mc interface {
// mc: -key=upSpecialCacheKey -expire=d.upSpecialExpire -encode=pb
AddCacheUpSpecial(c context.Context, mid int64, us *upgrpc.UpSpecial) (err error)
// mc: -key=upSpecialCacheKey
CacheUpSpecial(c context.Context, mid int64) (res *upgrpc.UpSpecial, err error)
// mc: -key=upSpecialCacheKey
DelCacheUpSpecial(c context.Context, mid int64) (err error)
// mc: -key=upSpecialCacheKey -expire=d.upSpecialExpire -encode=pb
AddCacheUpsSpecial(c context.Context, mu map[int64]*upgrpc.UpSpecial) (err error)
// mc: -key=upSpecialCacheKey
CacheUpsSpecial(c context.Context, mid []int64) (res map[int64]*upgrpc.UpSpecial, err error)
// mc: -key=upSpecialCacheKey
DelCacheUpsSpecial(c context.Context, mids []int64) (err error)
}
*/
package manager
import (
"context"
"fmt"
upgrpc "go-common/app/service/main/up/api/v1"
"go-common/library/cache/memcache"
"go-common/library/log"
"go-common/library/stat/prom"
)
var _ _mc
// AddCacheUpSpecial Set data to mc
func (d *Dao) AddCacheUpSpecial(c context.Context, id int64, val *upgrpc.UpSpecial) (err error) {
if val == nil {
return
}
conn := d.mc.Get(c)
defer conn.Close()
key := upSpecialCacheKey(id)
item := &memcache.Item{Key: key, Object: val, Expiration: d.upSpecialExpire, Flags: memcache.FlagProtobuf}
if err = conn.Set(item); err != nil {
prom.BusinessErrCount.Incr("mc:AddCacheUpSpecial")
log.Errorv(c, log.KV("AddCacheUpSpecial", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// CacheUpSpecial get data from mc
func (d *Dao) CacheUpSpecial(c context.Context, id int64) (res *upgrpc.UpSpecial, err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := upSpecialCacheKey(id)
reply, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:CacheUpSpecial")
log.Errorv(c, log.KV("CacheUpSpecial", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
res = &upgrpc.UpSpecial{}
err = conn.Scan(reply, res)
if err != nil {
prom.BusinessErrCount.Incr("mc:CacheUpSpecial")
log.Errorv(c, log.KV("CacheUpSpecial", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// DelCacheUpSpecial delete data from mc
func (d *Dao) DelCacheUpSpecial(c context.Context, id int64) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := upSpecialCacheKey(id)
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:DelCacheUpSpecial")
log.Errorv(c, log.KV("DelCacheUpSpecial", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// AddCacheUpsSpecial Set data to mc
func (d *Dao) AddCacheUpsSpecial(c context.Context, values map[int64]*upgrpc.UpSpecial) (err error) {
if len(values) == 0 {
return
}
conn := d.mc.Get(c)
defer conn.Close()
for id, val := range values {
key := upSpecialCacheKey(id)
item := &memcache.Item{Key: key, Object: val, Expiration: d.upSpecialExpire, Flags: memcache.FlagProtobuf}
if err = conn.Set(item); err != nil {
prom.BusinessErrCount.Incr("mc:AddCacheUpsSpecial")
log.Errorv(c, log.KV("AddCacheUpsSpecial", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
}
return
}
// CacheUpsSpecial get data from mc
func (d *Dao) CacheUpsSpecial(c context.Context, ids []int64) (res map[int64]*upgrpc.UpSpecial, err error) {
l := len(ids)
if l == 0 {
return
}
keysMap := make(map[string]int64, l)
keys := make([]string, 0, l)
for _, id := range ids {
key := upSpecialCacheKey(id)
keysMap[key] = id
keys = append(keys, key)
}
conn := d.mc.Get(c)
defer conn.Close()
replies, err := conn.GetMulti(keys)
if err != nil {
prom.BusinessErrCount.Incr("mc:CacheUpsSpecial")
log.Errorv(c, log.KV("CacheUpsSpecial", fmt.Sprintf("%+v", err)), log.KV("keys", keys))
return
}
for key, reply := range replies {
var v *upgrpc.UpSpecial
v = &upgrpc.UpSpecial{}
err = conn.Scan(reply, v)
if err != nil {
prom.BusinessErrCount.Incr("mc:CacheUpsSpecial")
log.Errorv(c, log.KV("CacheUpsSpecial", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
if res == nil {
res = make(map[int64]*upgrpc.UpSpecial, len(keys))
}
res[keysMap[key]] = v
}
return
}
// DelCacheUpsSpecial delete data from mc
func (d *Dao) DelCacheUpsSpecial(c context.Context, ids []int64) (err error) {
if len(ids) == 0 {
return
}
conn := d.mc.Get(c)
defer conn.Close()
for _, id := range ids {
key := upSpecialCacheKey(id)
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
continue
}
prom.BusinessErrCount.Incr("mc:DelCacheUpsSpecial")
log.Errorv(c, log.KV("DelCacheUpsSpecial", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
}
return
}

View File

@@ -0,0 +1,102 @@
package manager
import (
"context"
upgrpc "go-common/app/service/main/up/api/v1"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestManagerAddCacheUpSpecial(t *testing.T) {
convey.Convey("AddCacheUpSpecial", t, func(convCtx convey.C) {
var (
c = context.Background()
id = int64(0)
val = &upgrpc.UpSpecial{}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
err := d.AddCacheUpSpecial(c, id, val)
convCtx.Convey("Then err should be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestManagerCacheUpSpecial(t *testing.T) {
convey.Convey("CacheUpSpecial", t, func(convCtx convey.C) {
var (
c = context.Background()
id = int64(0)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := d.CacheUpSpecial(c, id)
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestManagerDelCacheUpSpecial(t *testing.T) {
convey.Convey("DelCacheUpSpecial", t, func(convCtx convey.C) {
var (
c = context.Background()
id = int64(0)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
err := d.DelCacheUpSpecial(c, id)
convCtx.Convey("Then err should be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestManagerAddCacheUpsSpecial(t *testing.T) {
convey.Convey("AddCacheUpsSpecial", t, func(convCtx convey.C) {
var (
c = context.Background()
values map[int64]*upgrpc.UpSpecial
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
err := d.AddCacheUpsSpecial(c, values)
convCtx.Convey("Then err should be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestManagerCacheUpsSpecial(t *testing.T) {
convey.Convey("CacheUpsSpecial", t, func(convCtx convey.C) {
var (
c = context.Background()
ids = []int64{27515256}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := d.CacheUpsSpecial(c, ids)
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestManagerDelCacheUpsSpecial(t *testing.T) {
convey.Convey("DelCacheUpsSpecial", t, func(convCtx convey.C) {
var (
c = context.Background()
ids = []int64{}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
err := d.DelCacheUpsSpecial(c, ids)
convCtx.Convey("Then err should be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,372 @@
package manager
import (
"context"
"database/sql"
"errors"
"fmt"
"strings"
"time"
upgrpc "go-common/app/service/main/up/api/v1"
"go-common/app/service/main/up/dao"
"go-common/app/service/main/up/model"
xsql "go-common/library/database/sql"
"go-common/library/log"
"go-common/library/xstr"
)
const (
_upsWithGroupBase = "SELECT ups.id,mid,up_group.id as group_id ,up_group.short_tag as group_tag,up_group.name as group_name,ups.note,ups.ctime, ups.mtime, ups.uid FROM ups INNER JOIN up_group on ups.type=up_group.id "
_upsWithGroupBaseWithColor = "SELECT ups.id,mid,up_group.id as group_id ,up_group.short_tag as group_tag,up_group.name as group_name,ups.note,ups.ctime, ups.mtime, ups.uid, up_group.colors FROM ups INNER JOIN up_group on ups.type=up_group.id "
_upsWithGroup = _upsWithGroupBaseWithColor + "limit ? offset ? "
_upsWithGroupByMtime = _upsWithGroupBaseWithColor + "where ups.mtime >= ?"
_delByMid = "DELETE FROM ups where id = ?"
_insertMidType = "INSERT INTO ups (mid, type, note, ctime, mtime, uid) values "
_selectByMidTypeWithGroup = _upsWithGroupBase + "where mid = ? and type = ?"
_updateByID = "update ups set type=?, note=?, uid=?, mtime=? where id = ?"
//MysqlTimeFormat mysql time format
MysqlTimeFormat = "2006-01-02 15:04:05"
_selectByID = _upsWithGroupBase + "where ups.id = ?"
_selectCount = "SELECT COUNT(0) FROM ups INNER JOIN up_group on ups.type=up_group.id "
_upSpecialSQL = "SELECT type FROM ups WHERE mid = ?"
_upsSpecialSQL = "SELECT mid, type FROM ups WHERE mid IN (%s)"
_upGroupsMidsSQL = "SELECT id, mid, type FROM ups WHERE id > ? AND type IN (%s) LIMIT ?"
)
// UpSpecials load all ups with group info
func (d *Dao) UpSpecials(c context.Context) (ups []*model.UpSpecial, err error) {
log.Info("start refresh ups table")
stmt, err := d.managerDB.Prepare(_upsWithGroup)
if err != nil {
log.Error("d.managerDB.Prepare error(%v)", err)
return
}
defer stmt.Close()
var offset = 0
var limit = 1000
var cnt = 0
var isFirst = true
for isFirst || cnt == limit {
isFirst = false
rows, err1 := stmt.Query(c, limit, offset)
if err1 != nil {
err = err1
log.Error("stmt.Query error(%v)", err1)
return
}
cnt = 0
for rows.Next() {
cnt++
var up *model.UpSpecial
up, err = parseUpGroupWithColor(rows)
ups = append(ups, up)
}
rows.Close()
if err != nil {
return
}
log.Info("reading data from table, read count=%d", cnt)
offset += cnt
}
log.Info("end refresh ups table, read count=%d", offset)
return
}
//RefreshUpSpecialIncremental refresh cache incrementally
func (d *Dao) RefreshUpSpecialIncremental(c context.Context, lastMTime time.Time) (ups []*model.UpSpecial, err error) {
var timeStr = lastMTime.Format(MysqlTimeFormat)
log.Info("start refresh ups table mtime>%s", timeStr)
stmt, err := d.managerDB.Prepare(_upsWithGroupByMtime)
if err != nil {
log.Error("d.managerDB.Prepare error(%v)", err)
return
}
defer stmt.Close()
var cnt = 0
rows, err1 := stmt.Query(c, timeStr)
if err1 != nil {
err = err1
log.Error("stmt.Query error(%v)", err1)
return
}
cnt = 0
for rows.Next() {
cnt++
var up *model.UpSpecial
up, err = parseUpGroupWithColor(rows)
if err != nil {
log.Error("scan row err, %v", err)
break
}
ups = append(ups, up)
}
rows.Close()
if err != nil {
return
}
log.Info("reading data from table, read count=%d", cnt)
return
}
//DelSpecialByID delete special by id
func (d *Dao) DelSpecialByID(c context.Context, id int64) (res sql.Result, err error) {
var stmt *xsql.Stmt
stmt, err = d.managerDB.Prepare(_delByMid)
if err != nil {
log.Error("stmt prepare fail, error(%v), sql=%s", err, _delByMid)
return
}
defer stmt.Close()
res, err = stmt.Exec(c, id)
if err != nil {
log.Error("delete mid from ups fail, id=%d, err=%v", id, err)
}
return
}
//InsertSpecial insert special
func (d *Dao) InsertSpecial(c context.Context, special *model.UpSpecial, mids ...int64) (res sql.Result, err error) {
var count = len(mids)
if count == 0 {
err = errors.New("no data need update")
return
}
var insertSchema []string
var vals []interface{}
var nowStr = time.Now().Format(MysqlTimeFormat)
for _, mid := range mids {
insertSchema = append(insertSchema, "(?,?,?,?,?,?)")
vals = append(vals, mid, special.GroupID, special.Note, nowStr, nowStr, special.UID)
}
var insertSQL = _insertMidType + strings.Join(insertSchema, ",")
var stmt *xsql.Stmt
stmt, err = d.managerDB.Prepare(insertSQL)
if err != nil {
log.Error("stmt prepare fail, error(%v), sql=%s", err, insertSQL)
return
}
defer stmt.Close()
res, err = stmt.Exec(c, vals...)
if err != nil {
log.Error("insert ups fail, err=%v, groupid=%d, note=%s, mid=%v", err, special.GroupID, special.Note, mids)
}
return
}
//UpdateSpecialByID update special by id
func (d *Dao) UpdateSpecialByID(c context.Context, id int64, special *model.UpSpecial) (res sql.Result, err error) {
var stmt *xsql.Stmt
stmt, err = d.managerDB.Prepare(_updateByID)
if err != nil {
log.Error("stmt prepare fail, error(%v), sql=%s", err, _updateByID)
return
}
defer stmt.Close()
var timeStr = time.Now().Format(MysqlTimeFormat)
res, err = stmt.Exec(c, special.GroupID, special.Note, special.UID, timeStr, id)
if err != nil {
log.Error("update ups fail, err=%v, groupid=%d, note=%s, id=%d", err, special.GroupID, special.Note, id)
}
return
}
//GetSpecialByMidGroup get special by mid and group
func (d *Dao) GetSpecialByMidGroup(c context.Context, mid int64, groupID int64) (res *model.UpSpecial, err error) {
var stmt *xsql.Stmt
stmt, err = d.managerDB.Prepare(_selectByMidTypeWithGroup)
if err != nil {
log.Error("stmt prepare fail, error(%v), sql=%s", err, _selectByMidTypeWithGroup)
return
}
defer stmt.Close()
row := stmt.QueryRow(c, mid, groupID)
var note sql.NullString
var up = model.UpSpecial{}
switch err = row.Scan(&up.ID, &up.Mid, &up.GroupID, &up.GroupTag, &up.GroupName, &note, &up.CTime, &up.MTime, &up.UID); err {
case sql.ErrNoRows:
err = nil
return
case nil:
up.Note = note.String
res = &up
default:
log.Error("rows.Scan error(%v)", err)
return
}
return
}
//GetSpecialByID get special by id
func (d *Dao) GetSpecialByID(c context.Context, id int64) (res *model.UpSpecial, err error) {
rows, err := prepareAndQuery(c, d.managerDB, _selectByID, id)
if err != nil {
return
}
defer rows.Close()
var note sql.NullString
for rows.Next() {
var up = &model.UpSpecial{}
err = rows.Scan(&up.ID, &up.Mid, &up.GroupID, &up.GroupTag, &up.GroupName, &note, &up.CTime, &up.MTime, &up.UID)
up.Note = note.String
res = up
break
}
return
}
//GetSepcialCount get special count
func (d *Dao) GetSepcialCount(c context.Context, conditions ...dao.Condition) (count int, err error) {
var conditionStr, args, hasOperator = dao.ConcatCondition(conditions...)
var where = " WHERE "
if !hasOperator {
where = ""
}
rows, err := prepareAndQuery(c, d.managerDB, _selectCount+where+conditionStr, args...)
if err != nil {
log.Error("get special db fail, err=%+v", err)
return
}
defer rows.Close()
for rows.Next() {
rows.Scan(&count)
}
return
}
func parseUpGroupWithColor(rows *xsql.Rows) (up *model.UpSpecial, err error) {
var note sql.NullString
var colors sql.NullString
up = &model.UpSpecial{}
err = rows.Scan(&up.ID, &up.Mid, &up.GroupID, &up.GroupTag, &up.GroupName, &note, &up.CTime, &up.MTime, &up.UID, &colors)
if err != nil {
log.Error("scan row err, %v", err)
return
}
up.Note = note.String
if colors.Valid {
var colors = strings.Split(colors.String, "|")
if len(colors) >= 2 {
up.FontColor = colors[0]
up.BgColor = colors[1]
}
}
return
}
//GetSpecial get special from db
func (d *Dao) GetSpecial(c context.Context, conditions ...dao.Condition) (res []*model.UpSpecial, err error) {
var conditionStr, args, hasOperator = dao.ConcatCondition(conditions...)
var where = " WHERE "
if !hasOperator {
where = ""
}
rows, err := prepareAndQuery(c, d.managerDB, _upsWithGroupBaseWithColor+where+conditionStr, args...)
if err != nil {
log.Error("get special db fail, err=%+v", err)
return
}
defer rows.Close()
for rows.Next() {
var up *model.UpSpecial
up, err = parseUpGroupWithColor(rows)
if err != nil {
log.Error("scan row err, %v", err)
break
}
res = append(res, up)
}
return
}
//GetSpecialByMid get speical by mid
func (d *Dao) GetSpecialByMid(c context.Context, mid int64) (res []*model.UpSpecial, err error) {
var condition = dao.Condition{
Key: "ups.mid",
Operator: "=",
Value: mid,
}
return d.GetSpecial(c, condition)
}
// RawUpSpecial get up special propertys
func (d *Dao) RawUpSpecial(c context.Context, mid int64) (us *upgrpc.UpSpecial, err error) {
rows, err := d.managerDB.Query(c, _upSpecialSQL, mid)
if err != nil {
return
}
defer rows.Close()
us = new(upgrpc.UpSpecial)
for rows.Next() {
var groupID int64
if err = rows.Scan(&groupID); err != nil {
if err == xsql.ErrNoRows {
err = nil
}
return
}
us.GroupIDs = append(us.GroupIDs, groupID)
}
return
}
// RawUpsSpecial get mult up special propertys
func (d *Dao) RawUpsSpecial(c context.Context, mids []int64) (mu map[int64]*upgrpc.UpSpecial, err error) {
rows, err := d.managerDB.Query(c, fmt.Sprintf(_upsSpecialSQL, xstr.JoinInts(mids)))
if err != nil {
return
}
defer rows.Close()
mu = make(map[int64]*upgrpc.UpSpecial, len(mids))
for rows.Next() {
var mid, groupID int64
if err = rows.Scan(&mid, &groupID); err != nil {
if err == xsql.ErrNoRows {
err = nil
}
return
}
if mu[mid] == nil {
mu[mid] = new(upgrpc.UpSpecial)
}
mu[mid].GroupIDs = append(mu[mid].GroupIDs, groupID)
}
return
}
// UpGroupsMids get mids in one group.
func (d *Dao) UpGroupsMids(c context.Context, groupIDs []int64, lastID int64, ps int) (lid int64, gmids map[int64][]int64, err error) {
rows, err := d.managerDB.Query(c, fmt.Sprintf(_upGroupsMidsSQL, xstr.JoinInts(groupIDs)), lastID, ps)
if err != nil {
return
}
defer rows.Close()
gmids = make(map[int64][]int64)
for rows.Next() {
var id, gid, mid int64
if err = rows.Scan(&id, &mid, &gid); err != nil {
if err == xsql.ErrNoRows {
err = nil
}
return
}
if id > lid {
lid = id
}
gmids[gid] = append(gmids[gid], mid)
}
return
}

View File

@@ -0,0 +1,138 @@
package manager
import (
"context"
"database/sql"
"fmt"
"strings"
upgrpc "go-common/app/service/main/up/api/v1"
"go-common/app/service/main/up/dao"
"go-common/app/service/main/up/model"
xsql "go-common/library/database/sql"
"go-common/library/log"
)
const (
_insertGroup = "INSERT INTO up_group (name, tag, short_tag, colors, remark) VALUES (?,?,?,?,?)"
_checkGroupExist = "SELECT COUNT(0) FROM up_group WHERE (name=? OR tag=? OR short_tag=?) "
_updateGroupByID = "UPDATE up_group SET name=?, tag=?, short_tag=?, colors=?, remark=? WHERE id=?"
_removeGroupByID = "UPDATE up_group SET state=0 WHERE id=?"
_selectGroup = "SELECT id, name, tag, short_tag, remark, colors, state FROM up_group "
_upGroupsSQL = "SELECT id, name, tag, short_tag, remark, colors FROM up_group WHERE state = 1"
)
//AddGroup add group in db
func (d *Dao) AddGroup(c context.Context, groupAddInfo *model.AddGroupArg) (res sql.Result, err error) {
var color = fmt.Sprintf("%s|%s", groupAddInfo.FontColor, groupAddInfo.BgColor)
res, err = prepareAndExec(c, d.managerDB, _insertGroup, groupAddInfo.Name, groupAddInfo.Tag, groupAddInfo.ShortTag, color, groupAddInfo.Remark)
return
}
//CheckGroupExist check if group exist
func (d *Dao) CheckGroupExist(c context.Context, groupAddInfo *model.AddGroupArg, exceptid int64) (exist bool, err error) {
var sqlStr = _checkGroupExist
var args = []interface{}{groupAddInfo.Name, groupAddInfo.Tag, groupAddInfo.ShortTag}
if exceptid != 0 {
sqlStr += " AND id != ?"
args = append(args, exceptid)
}
rows, err := prepareAndQuery(c, d.managerDB, sqlStr, args...)
if err != nil {
return
}
defer rows.Close()
var count int
for rows.Next() {
err = rows.Scan(&count)
break
}
if err != nil {
return
}
exist = count > 0
return
}
//UpdateGroup update group
func (d *Dao) UpdateGroup(c context.Context, groupAddInfo *model.EditGroupArg) (res sql.Result, err error) {
if groupAddInfo.AddArg == nil {
return
}
var color = fmt.Sprintf("%s|%s", groupAddInfo.AddArg.FontColor, groupAddInfo.AddArg.BgColor)
res, err = prepareAndExec(c, d.managerDB, _updateGroupByID, groupAddInfo.AddArg.Name, groupAddInfo.AddArg.Tag, groupAddInfo.AddArg.ShortTag, color, groupAddInfo.AddArg.Remark, groupAddInfo.ID)
return
}
//RemoveGroup remove group
func (d *Dao) RemoveGroup(c context.Context, arg *model.RemoveGroupArg) (res sql.Result, err error) {
res, err = prepareAndExec(c, d.managerDB, _removeGroupByID, arg.ID)
return
}
//GetGroup get group
func (d *Dao) GetGroup(c context.Context, arg *model.GetGroupArg) (res []*model.UpGroup, err error) {
var con = dao.Condition{
Key: "state",
Operator: "=",
Value: arg.State,
}
var conditionStr, vals, _ = dao.ConcatCondition(con)
rows, err := prepareAndQuery(c, d.managerDB, _selectGroup+"WHERE "+conditionStr, vals...)
if err != nil {
return
}
defer rows.Close()
// id, name, tag, short_tag, remark, colors
var colorStr string
for rows.Next() {
var group = model.UpGroup{}
err = rows.Scan(&group.ID, &group.Name, &group.Tag, &group.ShortTag, &group.Remark, &colorStr, &group.State)
if err != nil {
log.Error("scan row failed, err=%v", err)
break
}
var colors = strings.Split(colorStr, "|")
if len(colors) >= 2 {
group.FontColor = colors[0]
group.BgColor = colors[1]
}
res = append(res, &group)
}
return
}
// UpGroups get up special group data.
func (d *Dao) UpGroups(c context.Context) (mug map[int64]*upgrpc.UpGroup, err error) {
rows, err := d.managerDB.Query(c, _upGroupsSQL)
if err != nil {
return
}
defer rows.Close()
mug = make(map[int64]*upgrpc.UpGroup)
for rows.Next() {
var (
colorStr string
colors []string
ug = new(upgrpc.UpGroup)
)
if err = rows.Scan(&ug.ID, &ug.Name, &ug.Tag, &ug.ShortTag, &ug.Note, &colorStr); err != nil {
if err == xsql.ErrNoRows {
err = nil
}
return
}
colors = strings.Split(colorStr, "|")
if len(colors) >= 2 {
ug.FontColor = colors[0]
ug.BgColor = colors[1]
}
mug[ug.ID] = ug
}
return
}

View File

@@ -0,0 +1,82 @@
package manager
import (
"context"
"go-common/app/service/main/up/model"
"testing"
"github.com/smartystreets/goconvey/convey"
"strings"
)
func TestManagerAddGroup(t *testing.T) {
var (
c = context.TODO()
groupAddInfo = &model.AddGroupArg{}
)
convey.Convey("AddGroup", t, func(ctx convey.C) {
_, err := d.AddGroup(c, groupAddInfo)
if strings.Contains(err.Error(), "Error 1062") {
err = nil
}
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestManagerCheckGroupExist(t *testing.T) {
var (
c = context.TODO()
groupAddInfo = &model.AddGroupArg{}
exceptid = int64(0)
)
convey.Convey("CheckGroupExist", t, func(ctx convey.C) {
exist, err := d.CheckGroupExist(c, groupAddInfo, exceptid)
ctx.Convey("Then err should be nil.exist should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(exist, convey.ShouldNotBeNil)
})
})
}
func TestManagerUpdateGroup(t *testing.T) {
var (
c = context.TODO()
groupAddInfo = &model.EditGroupArg{}
)
convey.Convey("UpdateGroup", t, func(ctx convey.C) {
res, err := d.UpdateGroup(c, groupAddInfo)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
}
func TestManagerRemoveGroup(t *testing.T) {
var (
c = context.TODO()
arg = &model.RemoveGroupArg{}
)
convey.Convey("RemoveGroup", t, func(ctx convey.C) {
res, err := d.RemoveGroup(c, arg)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestManagerGetGroup(t *testing.T) {
var (
c = context.TODO()
arg = &model.GetGroupArg{}
)
convey.Convey("GetGroup", t, func(ctx convey.C) {
_, err := d.GetGroup(c, arg)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,41 @@
package manager
import (
"context"
"fmt"
upgrpc "go-common/app/service/main/up/api/v1"
)
const (
_upSpecialKey = "up_special_%d"
)
// upSpecialCacheKey 缓存key
func upSpecialCacheKey(mid int64) string {
return fmt.Sprintf(_upSpecialKey, mid)
}
//go:generate $GOPATH/src/go-common/app/tool/cache/gen
type _cache interface {
// cache: -nullcache=&upgrpc.UpSpecial{GroupIDs:[]int64{-1}} -check_null_code=$!=nil&&len($.GroupIDs)>0&&$.GroupIDs[0]==-1
UpSpecial(c context.Context, mid int64) (us *upgrpc.UpSpecial, err error)
// cache: -batch=100 -max_group=1 -batch_err=break -nullcache=&upgrpc.UpSpecial{GroupIDs:[]int64{-1}} -check_null_code=$!=nil&&len($.GroupIDs)>0&&$.GroupIDs[0]==-1
UpsSpecial(c context.Context, mids []int64) (map[int64]*upgrpc.UpSpecial, error)
}
//go:generate $GOPATH/src/go-common/app/tool/cache/mc
type _mc interface {
// mc: -key=upSpecialCacheKey -expire=d.upSpecialExpire -encode=pb
AddCacheUpSpecial(c context.Context, mid int64, us *upgrpc.UpSpecial) (err error)
// mc: -key=upSpecialCacheKey
CacheUpSpecial(c context.Context, mid int64) (res *upgrpc.UpSpecial, err error)
// mc: -key=upSpecialCacheKey
DelCacheUpSpecial(c context.Context, mid int64) (err error)
// mc: -key=upSpecialCacheKey -expire=d.upSpecialExpire -encode=pb
AddCacheUpsSpecial(c context.Context, mu map[int64]*upgrpc.UpSpecial) (err error)
// mc: -key=upSpecialCacheKey
CacheUpsSpecial(c context.Context, mid []int64) (res map[int64]*upgrpc.UpSpecial, err error)
// mc: -key=upSpecialCacheKey
DelCacheUpsSpecial(c context.Context, mids []int64) (err error)
}

View File

@@ -0,0 +1,21 @@
package manager
import (
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestManagerupSpecialCacheKey(t *testing.T) {
convey.Convey("upSpecialCacheKey", t, func(convCtx convey.C) {
var (
mid = int64(0)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
p1 := upSpecialCacheKey(mid)
convCtx.Convey("Then p1 should not be nil.", func(convCtx convey.C) {
convCtx.So(p1, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,181 @@
package manager
import (
"context"
"go-common/app/service/main/up/dao"
"go-common/app/service/main/up/model"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestManagerUpSpecials(t *testing.T) {
var (
c = context.TODO()
)
convey.Convey("UpSpecials", t, func(ctx convey.C) {
ups, err := d.UpSpecials(c)
ctx.Convey("Then err should be nil.ups should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(ups, convey.ShouldNotBeNil)
})
})
}
func TestManagerRefreshUpSpecialIncremental(t *testing.T) {
var (
c = context.TODO()
lastMTime = time.Now()
)
convey.Convey("RefreshUpSpecialIncremental", t, func(ctx convey.C) {
ups, err := d.RefreshUpSpecialIncremental(c, lastMTime)
ctx.Convey("Then err should be nil.ups should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(len(ups), convey.ShouldBeGreaterThanOrEqualTo, 0)
})
})
}
func TestManagerDelSpecialByID(t *testing.T) {
var (
c = context.TODO()
id = int64(0)
)
convey.Convey("DelSpecialByID", t, func(ctx convey.C) {
res, err := d.DelSpecialByID(c, id)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestManagerInsertSpecial(t *testing.T) {
var (
c = context.TODO()
special = &model.UpSpecial{}
mids = int64(0)
)
convey.Convey("InsertSpecial", t, func(ctx convey.C) {
res, err := d.InsertSpecial(c, special, mids)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestManagerUpdateSpecialByID(t *testing.T) {
var (
c = context.TODO()
id = int64(0)
special = &model.UpSpecial{}
)
convey.Convey("UpdateSpecialByID", t, func(ctx convey.C) {
res, err := d.UpdateSpecialByID(c, id, special)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestManagerGetSpecialByMidGroup(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
groupID = int64(0)
)
convey.Convey("GetSpecialByMidGroup", t, func(ctx convey.C) {
res, err := d.GetSpecialByMidGroup(c, mid, groupID)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
}
func TestManagerGetSpecialByID(t *testing.T) {
var (
c = context.TODO()
id = int64(0)
)
convey.Convey("GetSpecialByID", t, func(ctx convey.C) {
res, err := d.GetSpecialByID(c, id)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
}
func TestManagerGetSepcialCount(t *testing.T) {
var (
c = context.TODO()
conditions dao.Condition
)
convey.Convey("GetSepcialCount", t, func(ctx convey.C) {
count, err := d.GetSepcialCount(c, conditions)
ctx.Convey("Then err should be nil.count should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(count, convey.ShouldNotBeNil)
})
})
}
func TestManagerGetSpecial(t *testing.T) {
var (
c = context.TODO()
conditions dao.Condition
)
convey.Convey("GetSpecial", t, func(ctx convey.C) {
res, err := d.GetSpecial(c, conditions)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestManagerGetSpecialByMid(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
)
convey.Convey("GetSpecialByMid", t, func(ctx convey.C) {
res, err := d.GetSpecialByMid(c, mid)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
}
func TestManagerRawUpSpecial(t *testing.T) {
var (
c = context.TODO()
mid = int64(27515314)
)
convey.Convey("RawUpSpecial", t, func(ctx convey.C) {
res, err := d.RawUpSpecial(c, mid)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestManagerRawUpsSpecial(t *testing.T) {
var (
c = context.TODO()
mids = []int64{27515314}
)
convey.Convey("RawUpsSpecial", t, func(ctx convey.C) {
res, err := d.RawUpsSpecial(c, mids)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,47 @@
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/service/main/up/conf:go_default_library",
"//app/service/main/up/dao:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["dao.go"],
importpath = "go-common/app/service/main/up/dao/monitor",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/up/conf:go_default_library",
"//app/service/main/up/model:go_default_library",
"//library/log: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,120 @@
package monitor
import (
"bytes"
"context"
"crypto/md5"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"strconv"
"time"
"go-common/app/service/main/up/conf"
"go-common/app/service/main/up/model"
"go-common/library/log"
)
const (
_uri = "/api/v1/message/add"
_method = "POST"
_fileType = "application/json"
)
// Dao is message dao.
type Dao struct {
c *conf.Config
client *http.Client
url string
}
// New new a message dao.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
client: &http.Client{
Timeout: time.Duration(time.Second * 1),
},
url: c.Monitor.Host + _uri,
}
return
}
// Send send exception message to owner.
func (d *Dao) Send(c context.Context, username, msg string) (err error) {
params := url.Values{}
now := time.Now().Unix()
params.Set("username", username)
params.Set("content", msg)
params.Set("title", "test")
params.Set("url", "")
params.Set("type", "wechat")
params.Set("token", d.c.Monitor.AppToken)
params.Set("timestamp", strconv.FormatInt(now, 10))
bap := &model.BAP{
UserName: params.Get("username"),
Content: params.Get("content"),
Title: params.Get("title"),
URL: params.Get("url"),
Ty: params.Get("type"),
Token: params.Get("token"),
TimeStamp: now,
Signature: d.getSign(params),
}
jsonStr, err := json.Marshal(bap)
if err != nil {
log.Error("monitor json.Marshal error (%v)", err)
return
}
req, err := http.NewRequest(_method, d.url, bytes.NewBuffer(jsonStr))
if err != nil {
log.Error("monitor http.NewRequest error (%v)", err)
return
}
req.Header.Add("Content-Type", _fileType)
// timeout
ctx, cancel := context.WithTimeout(c, 800*time.Millisecond)
req = req.WithContext(ctx)
defer cancel()
response, err := d.client.Do(req)
if err != nil {
log.Error("monitor d.client.Post error(%v)", err)
return
}
defer response.Body.Close()
if response.StatusCode != http.StatusOK {
log.Error("monitor http.StatusCode nq http.StatusOK (%d) | url(%s)", response.StatusCode, d.url)
return
}
body, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Error("monitor ioutil.ReadAll error(%v)", err)
return
}
var result struct {
Status int `json:"status"`
Msg string `json:"msg"`
}
if err = json.Unmarshal(body, &result); err != nil {
log.Error("monitor json.Unmarshal error(%v)", err)
}
if result.Status != 0 {
log.Error("monitor get status(%d) msg(%s)", result.Status, result.Msg)
}
return
}
func (d *Dao) getSign(params url.Values) (sign string) {
for k, v := range params {
if len(v) == 0 {
params.Del(k)
}
}
h := md5.New()
io.WriteString(h, params.Encode()+d.c.Monitor.AppSecret)
sign = fmt.Sprintf("%x", h.Sum(nil))
return
}

View File

@@ -0,0 +1,69 @@
package monitor
import (
"context"
"flag"
"go-common/app/service/main/up/conf"
"net/url"
"os"
"testing"
"github.com/smartystreets/goconvey/convey"
"go-common/app/service/main/up/dao"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", dao.AppID)
flag.Set("conf_token", dao.UatToken)
flag.Set("tree_id", dao.TreeID)
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/up-service.toml")
}
if os.Getenv("UT_LOCAL_TEST") != "" {
flag.Set("conf", "../../cmd/up-service.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
m.Run()
os.Exit(0)
}
func TestMonitorSend(t *testing.T) {
var (
c = context.TODO()
username = ""
msg = ""
)
convey.Convey("Send", t, func(ctx convey.C) {
err := d.Send(c, username, msg)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestMonitorgetSign(t *testing.T) {
var (
params url.Values
)
convey.Convey("getSign", t, func(ctx convey.C) {
sign := d.getSign(params)
ctx.Convey("Then sign should not be nil.", func(ctx convey.C) {
ctx.So(sign, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,86 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"api_test.go",
"dao.cache_test.go",
"dao_test.go",
"mc.cache_test.go",
"mc_all_identity_test.go",
"mc_up_test.go",
"sign_up_test.go",
"up_info_test.go",
"up_switch_test.go",
"up_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/up/conf:go_default_library",
"//app/service/main/up/dao:go_default_library",
"//app/service/main/up/dao/global:go_default_library",
"//app/service/main/up/model:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//vendor/github.com/bouk/monkey:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
"//vendor/gopkg.in/h2non/gock.v1:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"api.go",
"dao.cache.go",
"dao.go",
"mc.cache.go",
"mc_all_identity.go",
"mc_up.go",
"sign_up.go",
"up.go",
"up_info.go",
"up_switch.go",
],
importpath = "go-common/app/service/main/up/dao/up",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/openplatform/article/model:go_default_library",
"//app/interface/openplatform/article/rpc/client:go_default_library",
"//app/service/main/up/api/v1:go_default_library",
"//app/service/main/up/conf:go_default_library",
"//app/service/main/up/dao/global:go_default_library",
"//app/service/main/up/model:go_default_library",
"//library/cache/memcache: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/stat/prom:go_default_library",
"//library/sync/errgroup:go_default_library",
"//library/sync/pipeline/fanout:go_default_library",
"//library/xstr: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,95 @@
package up
import (
"context"
"net/url"
"strconv"
"go-common/app/interface/openplatform/article/model"
"go-common/library/ecode"
"go-common/library/log"
)
const (
_picUpInfoURI string = "/link_draw_ex/v0/doc/check"
_blinkUpInfoURI string = "/clip_ext/v0/video/have"
)
// Pic pic return value
type Pic struct {
Has int `json:"has_doc"`
}
// Blink blink return value
type Blink struct {
Has int `json:"has"`
}
// Pic get pic up info.
func (d *Dao) Pic(c context.Context, mid int64, ip string) (has int, err error) {
params := url.Values{}
params.Set("uid", strconv.FormatInt(mid, 10))
var res struct {
Code int `json:"code"`
Data Pic `json:"data"`
}
err = d.client.Get(c, d.picUpInfoURL, ip, params, &res)
if err != nil {
log.Error("d.client.Get(%s) error(%v)", d.picUpInfoURL+"?"+params.Encode(), err)
return
}
if res.Code != 0 {
log.Error("Pic url(%s) error(%v)", d.picUpInfoURL+"?"+params.Encode(), err)
err = ecode.Int(res.Code)
return
}
has = res.Data.Has
return
}
// Blink get BLink up info.
func (d *Dao) Blink(c context.Context, mid int64, ip string) (has int, err error) {
params := url.Values{}
params.Set("uid", strconv.FormatInt(mid, 10))
var res struct {
Code int `json:"code"`
Data Blink `json:"data"`
}
err = d.client.Get(c, d.blinkUpInfoURL, ip, params, &res)
if err != nil {
log.Error("d.client.Get(%s) error(%v)", d.blinkUpInfoURL+"?"+params.Encode(), err)
return
}
if res.Code != 0 {
log.Error("Blink url(%s) error(%v)", d.blinkUpInfoURL+"?"+params.Encode(), err)
err = ecode.Int(res.Code)
return
}
has = res.Data.Has
return
}
// IsAuthor checks that whether user has permission to write article.
func (d *Dao) IsAuthor(c context.Context, mid int64, ip string) (isArt int, err error) {
var (
arg = &model.ArgMid{
Mid: mid,
RealIP: ip,
}
res bool
)
if res, err = d.art.IsAuthor(c, arg); err != nil {
if _, er := strconv.ParseInt(err.Error(), 10, 64); er != nil {
log.Error("d.art.IsAuthor (%v) error(%v)", arg, err)
err = ecode.CreativeArticleRPCErr
}
if ecode.Cause(err) == ecode.ArtCreationNoPrivilege {
log.Error("d.art.IsAuthor(%d) error(%v)", mid, err)
}
return
}
if res {
isArt = 1
}
return
}

View File

@@ -0,0 +1,82 @@
package up
import (
"context"
"github.com/bouk/monkey"
"github.com/smartystreets/goconvey/convey"
httpx "go-common/library/net/http/blademaster"
"net/url"
"reflect"
"testing"
)
const (
uid = 12345
)
func TestUpPic(t *testing.T) {
var (
c = context.TODO()
mid = int64(uid)
ip = ""
)
convey.Convey("Pic", t, func(ctx convey.C) {
type result struct {
Code int `json:"code"`
Data Pic `json:"data"`
}
res := new(result)
guard := monkey.PatchInstanceMethod(reflect.TypeOf(d.client), "Get", func(_ *httpx.Client, _ context.Context, _, _ string, _ url.Values, _ interface{}) error {
res.Code = 0
res.Data = Pic{Has: 1}
return nil
})
defer guard.Unpatch()
has, err := d.Pic(c, mid, ip)
ctx.Convey("Then err should be nil.has should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(has, convey.ShouldNotBeNil)
})
})
}
func TestUpBlink(t *testing.T) {
var (
c = context.TODO()
mid = int64(uid)
ip = ""
)
convey.Convey("Blink", t, func(ctx convey.C) {
type result struct {
Code int `json:"code"`
Data Blink `json:"data"`
}
res := new(result)
guard := monkey.PatchInstanceMethod(reflect.TypeOf(d.client), "Get", func(_ *httpx.Client, _ context.Context, _, _ string, _ url.Values, _ interface{}) error {
res.Code = 0
res.Data = Blink{Has: 1}
return nil
})
defer guard.Unpatch()
has, err := d.Blink(c, mid, ip)
ctx.Convey("Then err should be nil.has should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(has, convey.ShouldNotBeNil)
})
})
}
func TestUpIsAuthor(t *testing.T) {
var (
c = context.TODO()
mid = int64(uid)
ip = ""
)
convey.Convey("IsAuthor", t, func(ctx convey.C) {
isArt, err := d.IsAuthor(c, mid, ip)
ctx.Convey("Then err should be nil.isArt should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(isArt, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,213 @@
// Code generated by $GOPATH/src/go-common/app/tool/cache/gen. DO NOT EDIT.
/*
Package up is a generated cache proxy package.
It is generated from:
type _cache interface {
//cache: -nullcache=&model.Up{ID:-1} -check_null_code=$!=nil&&$.ID==-1
Up(c context.Context, mid int64) (up *model.Up, err error)
//cache: -nullcache=&model.UpSwitch{ID:-1} -check_null_code=$!=nil&&$.ID==-1
UpSwitch(c context.Context, mid int64) (up *model.UpSwitch, err error)
//cache: -nullcache=&model.UpInfoActiveReply{ID:-1} -check_null_code=$!=nil&&$.ID==-1
UpInfoActive(c context.Context, mid int64) (up *model.UpInfoActiveReply, err error)
// cache: -batch=100 -max_group=1 -batch_err=break -nullcache=&model.UpInfoActiveReply{ID:-1} -check_null_code=$!=nil&&$.ID==-1
UpsInfoActive(c context.Context, mids []int64) (res map[int64]*model.UpInfoActiveReply, err error)
}
*/
package up
import (
"context"
"sync"
"go-common/app/service/main/up/model"
"go-common/library/stat/prom"
"go-common/library/sync/errgroup"
)
var _ _cache
// Up get data from cache if miss will call source method, then add to cache.
func (d *Dao) Up(c context.Context, id int64) (res *model.Up, err error) {
addCache := true
res, err = d.CacheUp(c, id)
if err != nil {
addCache = false
err = nil
}
defer func() {
if res != nil && res.ID == -1 {
res = nil
}
}()
if res != nil {
prom.CacheHit.Incr("Up")
return
}
prom.CacheMiss.Incr("Up")
res, err = d.RawUp(c, id)
if err != nil {
return
}
miss := res
if miss == nil {
miss = &model.Up{ID: -1}
}
if !addCache {
return
}
d.cache.Do(c, func(c context.Context) {
d.AddCacheUp(c, id, miss)
})
return
}
// UpSwitch get data from cache if miss will call source method, then add to cache.
func (d *Dao) UpSwitch(c context.Context, id int64) (res *model.UpSwitch, err error) {
addCache := true
res, err = d.CacheUpSwitch(c, id)
if err != nil {
addCache = false
err = nil
}
defer func() {
if res != nil && res.ID == -1 {
res = nil
}
}()
if res != nil {
prom.CacheHit.Incr("UpSwitch")
return
}
prom.CacheMiss.Incr("UpSwitch")
res, err = d.RawUpSwitch(c, id)
if err != nil {
return
}
miss := res
if miss == nil {
miss = &model.UpSwitch{ID: -1}
}
if !addCache {
return
}
d.cache.Do(c, func(c context.Context) {
d.AddCacheUpSwitch(c, id, miss)
})
return
}
// UpInfoActive get data from cache if miss will call source method, then add to cache.
func (d *Dao) UpInfoActive(c context.Context, id int64) (res *model.UpInfoActiveReply, err error) {
addCache := true
res, err = d.CacheUpInfoActive(c, id)
if err != nil {
addCache = false
err = nil
}
defer func() {
if res != nil && res.ID == -1 {
res = nil
}
}()
if res != nil {
prom.CacheHit.Incr("UpInfoActive")
return
}
prom.CacheMiss.Incr("UpInfoActive")
res, err = d.RawUpInfoActive(c, id)
if err != nil {
return
}
miss := res
if miss == nil {
miss = &model.UpInfoActiveReply{ID: -1}
}
if !addCache {
return
}
d.cache.Do(c, func(c context.Context) {
d.AddCacheUpInfoActive(c, id, miss)
})
return
}
// UpsInfoActive get data from cache if miss will call source method, then add to cache.
func (d *Dao) UpsInfoActive(c context.Context, keys []int64) (res map[int64]*model.UpInfoActiveReply, err error) {
if len(keys) == 0 {
return
}
addCache := true
if res, err = d.CacheUpsInfoActive(c, keys); err != nil {
addCache = false
res = nil
err = nil
}
var miss []int64
for _, key := range keys {
if (res == nil) || (res[key] == nil) {
miss = append(miss, key)
}
}
prom.CacheHit.Add("UpsInfoActive", int64(len(keys)-len(miss)))
for k, v := range res {
if v != nil && v.ID == -1 {
delete(res, k)
}
}
missLen := len(miss)
if missLen == 0 {
return
}
missData := make(map[int64]*model.UpInfoActiveReply, missLen)
prom.CacheMiss.Add("UpsInfoActive", int64(missLen))
var mutex sync.Mutex
group, ctx := errgroup.WithContext(c)
if missLen > 1 {
group.GOMAXPROCS(1)
}
var run = func(ms []int64) {
group.Go(func() (err error) {
data, err := d.RawUpsInfoActive(ctx, ms)
mutex.Lock()
for k, v := range data {
missData[k] = v
}
mutex.Unlock()
return
})
}
var (
i int
n = missLen / 100
)
for i = 0; i < n; i++ {
run(miss[i*n : (i+1)*n])
}
if len(miss[i*n:]) > 0 {
run(miss[i*n:])
}
err = group.Wait()
if res == nil {
res = make(map[int64]*model.UpInfoActiveReply, len(keys))
}
for k, v := range missData {
res[k] = v
}
if err != nil {
return
}
for _, key := range miss {
if res[key] == nil {
missData[key] = &model.UpInfoActiveReply{ID: -1}
}
}
if !addCache {
return
}
d.cache.Do(c, func(c context.Context) {
d.AddCacheUpsInfoActive(c, missData)
})
return
}

View File

@@ -0,0 +1,70 @@
package up
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestUpUp(t *testing.T) {
convey.Convey("Up", t, func(ctx convey.C) {
var (
c = context.Background()
id = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.Up(c, id)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestUpUpSwitch(t *testing.T) {
var (
c = context.TODO()
id = int64(0)
)
convey.Convey("UpSwitch", t, func(ctx convey.C) {
_, err := d.UpSwitch(c, id)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
//ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestUpUpInfoActive(t *testing.T) {
convey.Convey("UpInfoActive", t, func(ctx convey.C) {
var (
c = context.Background()
id = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.UpInfoActive(c, id)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestUpUpsInfoActive(t *testing.T) {
convey.Convey("UpsInfoActive", t, func(ctx convey.C) {
var (
c = context.Background()
keys = []int64{0}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.UpsInfoActive(c, keys)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,80 @@
package up
import (
"context"
"time"
"go-common/app/service/main/up/conf"
"go-common/app/service/main/up/dao/global"
"go-common/library/cache/memcache"
"go-common/library/database/sql"
httpx "go-common/library/net/http/blademaster"
"go-common/library/sync/pipeline/fanout"
article "go-common/app/interface/openplatform/article/rpc/client"
)
// DateLayout date layout
const DateLayout = "2006-01-02"
// Dao is creative dao.
type Dao struct {
// config
c *conf.Config
// db
db *sql.DB
//cache tool
cache *fanout.Fanout
//memcache pool
mcPool *memcache.Pool
mc *memcache.Pool
//up expiration
upExpire int32
// http client
client *httpx.Client
//api url
picUpInfoURL string
blinkUpInfoURL string
// rpc
art *article.Service
}
// New init db.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
db: sql.NewMySQL(c.DB.Creative),
cache: global.GetWorker(),
mcPool: memcache.NewPool(c.Memcache.Up),
upExpire: int32(time.Duration(c.Memcache.UpExpire) / time.Second),
// http client
client: httpx.NewClient(c.HTTPClient.Normal),
picUpInfoURL: c.Host.Live + _picUpInfoURI,
blinkUpInfoURL: c.Host.Live + _blinkUpInfoURI,
// rpc
art: article.New(c.ArticleRPC),
}
d.mc = d.mcPool
return
}
// Ping creativeDb
func (d *Dao) Ping(c context.Context) (err error) {
return d.db.Ping(c)
}
// Close db
func (d *Dao) Close() (err error) {
if d.db != nil {
d.db.Close()
}
if d.mcPool != nil {
d.mcPool.Close()
}
return
}
//GetHTTPClient get http client
func (d *Dao) GetHTTPClient() *httpx.Client {
return d.client
}

View File

@@ -0,0 +1,74 @@
package up
import (
"context"
"flag"
"os"
"testing"
"go-common/app/service/main/up/conf"
"go-common/app/service/main/up/dao"
"go-common/app/service/main/up/dao/global"
"github.com/smartystreets/goconvey/convey"
"gopkg.in/h2non/gock.v1"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", dao.AppID)
flag.Set("conf_token", dao.UatToken)
flag.Set("tree_id", dao.TreeID)
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/up-service.toml")
}
if os.Getenv("UT_LOCAL_TEST") != "" {
flag.Set("conf", "../../cmd/up-service.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
global.Init(conf.Conf)
d = New(conf.Conf)
d.client.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
// }
func TestUpPing(t *testing.T) {
var (
c = context.TODO()
)
convey.Convey("Ping", t, func(ctx convey.C) {
err := d.Ping(c)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestUpGetHTTPClient(t *testing.T) {
convey.Convey("GetHTTPClient", t, func(ctx convey.C) {
p1 := d.GetHTTPClient()
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,302 @@
// Code generated by $GOPATH/src/go-common/app/tool/cache/mc. DO NOT EDIT.
/*
Package up is a generated mc cache package.
It is generated from:
type _mc interface {
//mc: -key=upCacheKey -expire=d.upExpire -encode=json
AddCacheUp(c context.Context, mid int64, up *model.Up) (err error)
//mc: -key=upCacheKey
CacheUp(c context.Context, mid int64) (up *model.Up, err error)
//mc: -key=upCacheKey
DelCacheUp(c context.Context, mid int64) (err error)
//mc: -key=upSwitchKey -expire=d.upExpire -encode=json
AddCacheUpSwitch(c context.Context, mid int64, up *model.UpSwitch) (err error)
//mc: -key=upSwitchKey
CacheUpSwitch(c context.Context, mid int64) (res *model.UpSwitch, err error)
//mc: -key=upSwitchKey
DelCacheUpSwitch(c context.Context, mid int64) (err error)
//mc: -key=upInfoActiveKey -expire=d.upExpire -encode=json
AddCacheUpInfoActive(c context.Context, mid int64, up *model.UpInfoActiveReply) (err error)
//mc: -key=upInfoActiveKey
CacheUpInfoActive(c context.Context, mid int64) (res *model.UpInfoActiveReply, err error)
//mc: -key=upInfoActiveKey
DelCacheUpInfoActive(c context.Context, mid int64) (err error)
// mc: -key=upInfoActiveKey -expire=d.upExpire -encode=json
AddCacheUpsInfoActive(c context.Context, res map[int64]*model.UpInfoActiveReply) (err error)
// mc: -key=upInfoActiveKey
CacheUpsInfoActive(c context.Context, mids []int64) (res map[int64]*model.UpInfoActiveReply, err error)
// mc: -key=upInfoActiveKey
DelCacheUpsInfoActive(c context.Context, mids []int64) (err error)
}
*/
package up
import (
"context"
"fmt"
"go-common/app/service/main/up/model"
"go-common/library/cache/memcache"
"go-common/library/log"
"go-common/library/stat/prom"
)
var _ _mc
// AddCacheUp Set data to mc
func (d *Dao) AddCacheUp(c context.Context, id int64, val *model.Up) (err error) {
if val == nil {
return
}
conn := d.mc.Get(c)
defer conn.Close()
key := upCacheKey(id)
item := &memcache.Item{Key: key, Object: val, Expiration: d.upExpire, Flags: memcache.FlagJSON}
if err = conn.Set(item); err != nil {
prom.BusinessErrCount.Incr("mc:AddCacheUp")
log.Errorv(c, log.KV("AddCacheUp", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// CacheUp get data from mc
func (d *Dao) CacheUp(c context.Context, id int64) (res *model.Up, err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := upCacheKey(id)
reply, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:CacheUp")
log.Errorv(c, log.KV("CacheUp", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
res = &model.Up{}
err = conn.Scan(reply, res)
if err != nil {
prom.BusinessErrCount.Incr("mc:CacheUp")
log.Errorv(c, log.KV("CacheUp", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// DelCacheUp delete data from mc
func (d *Dao) DelCacheUp(c context.Context, id int64) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := upCacheKey(id)
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:DelCacheUp")
log.Errorv(c, log.KV("DelCacheUp", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// AddCacheUpSwitch Set data to mc
func (d *Dao) AddCacheUpSwitch(c context.Context, id int64, val *model.UpSwitch) (err error) {
if val == nil {
return
}
conn := d.mc.Get(c)
defer conn.Close()
key := upSwitchKey(id)
item := &memcache.Item{Key: key, Object: val, Expiration: d.upExpire, Flags: memcache.FlagJSON}
if err = conn.Set(item); err != nil {
prom.BusinessErrCount.Incr("mc:AddCacheUpSwitch")
log.Errorv(c, log.KV("AddCacheUpSwitch", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// CacheUpSwitch get data from mc
func (d *Dao) CacheUpSwitch(c context.Context, id int64) (res *model.UpSwitch, err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := upSwitchKey(id)
reply, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:CacheUpSwitch")
log.Errorv(c, log.KV("CacheUpSwitch", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
res = &model.UpSwitch{}
err = conn.Scan(reply, res)
if err != nil {
prom.BusinessErrCount.Incr("mc:CacheUpSwitch")
log.Errorv(c, log.KV("CacheUpSwitch", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// DelCacheUpSwitch delete data from mc
func (d *Dao) DelCacheUpSwitch(c context.Context, id int64) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := upSwitchKey(id)
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:DelCacheUpSwitch")
log.Errorv(c, log.KV("DelCacheUpSwitch", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// AddCacheUpInfoActive Set data to mc
func (d *Dao) AddCacheUpInfoActive(c context.Context, id int64, val *model.UpInfoActiveReply) (err error) {
if val == nil {
return
}
conn := d.mc.Get(c)
defer conn.Close()
key := upInfoActiveKey(id)
item := &memcache.Item{Key: key, Object: val, Expiration: d.upExpire, Flags: memcache.FlagJSON}
if err = conn.Set(item); err != nil {
prom.BusinessErrCount.Incr("mc:AddCacheUpInfoActive")
log.Errorv(c, log.KV("AddCacheUpInfoActive", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// CacheUpInfoActive get data from mc
func (d *Dao) CacheUpInfoActive(c context.Context, id int64) (res *model.UpInfoActiveReply, err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := upInfoActiveKey(id)
reply, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:CacheUpInfoActive")
log.Errorv(c, log.KV("CacheUpInfoActive", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
res = &model.UpInfoActiveReply{}
err = conn.Scan(reply, res)
if err != nil {
prom.BusinessErrCount.Incr("mc:CacheUpInfoActive")
log.Errorv(c, log.KV("CacheUpInfoActive", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// DelCacheUpInfoActive delete data from mc
func (d *Dao) DelCacheUpInfoActive(c context.Context, id int64) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := upInfoActiveKey(id)
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:DelCacheUpInfoActive")
log.Errorv(c, log.KV("DelCacheUpInfoActive", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// AddCacheUpsInfoActive Set data to mc
func (d *Dao) AddCacheUpsInfoActive(c context.Context, values map[int64]*model.UpInfoActiveReply) (err error) {
if len(values) == 0 {
return
}
conn := d.mc.Get(c)
defer conn.Close()
for id, val := range values {
key := upInfoActiveKey(id)
item := &memcache.Item{Key: key, Object: val, Expiration: d.upExpire, Flags: memcache.FlagJSON}
if err = conn.Set(item); err != nil {
prom.BusinessErrCount.Incr("mc:AddCacheUpsInfoActive")
log.Errorv(c, log.KV("AddCacheUpsInfoActive", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
}
return
}
// CacheUpsInfoActive get data from mc
func (d *Dao) CacheUpsInfoActive(c context.Context, ids []int64) (res map[int64]*model.UpInfoActiveReply, err error) {
l := len(ids)
if l == 0 {
return
}
keysMap := make(map[string]int64, l)
keys := make([]string, 0, l)
for _, id := range ids {
key := upInfoActiveKey(id)
keysMap[key] = id
keys = append(keys, key)
}
conn := d.mc.Get(c)
defer conn.Close()
replies, err := conn.GetMulti(keys)
if err != nil {
prom.BusinessErrCount.Incr("mc:CacheUpsInfoActive")
log.Errorv(c, log.KV("CacheUpsInfoActive", fmt.Sprintf("%+v", err)), log.KV("keys", keys))
return
}
for key, reply := range replies {
var v *model.UpInfoActiveReply
v = &model.UpInfoActiveReply{}
err = conn.Scan(reply, v)
if err != nil {
prom.BusinessErrCount.Incr("mc:CacheUpsInfoActive")
log.Errorv(c, log.KV("CacheUpsInfoActive", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
if res == nil {
res = make(map[int64]*model.UpInfoActiveReply, len(keys))
}
res[keysMap[key]] = v
}
return
}
// DelCacheUpsInfoActive delete data from mc
func (d *Dao) DelCacheUpsInfoActive(c context.Context, ids []int64) (err error) {
if len(ids) == 0 {
return
}
conn := d.mc.Get(c)
defer conn.Close()
for _, id := range ids {
key := upInfoActiveKey(id)
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
continue
}
prom.BusinessErrCount.Incr("mc:DelCacheUpsInfoActive")
log.Errorv(c, log.KV("DelCacheUpsInfoActive", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
}
return
}

View File

@@ -0,0 +1,132 @@
package up
import (
"context"
"go-common/app/service/main/up/model"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestUpAddCacheUp(t *testing.T) {
var (
c = context.TODO()
id = int64(0)
val = &model.Up{}
)
convey.Convey("AddCacheUp", t, func(ctx convey.C) {
err := d.AddCacheUp(c, id, val)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestUpCacheUp(t *testing.T) {
var (
c = context.TODO()
id = int64(0)
)
convey.Convey("CacheUp", t, func(ctx convey.C) {
res, err := d.CacheUp(c, id)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestUpDelCacheUp(t *testing.T) {
var (
c = context.TODO()
id = int64(0)
)
convey.Convey("DelCacheUp", t, func(ctx convey.C) {
err := d.DelCacheUp(c, id)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestUpAddCacheUpSwitch(t *testing.T) {
var (
c = context.TODO()
id = int64(0)
val = &model.UpSwitch{}
)
convey.Convey("AddCacheUpSwitch", t, func(ctx convey.C) {
err := d.AddCacheUpSwitch(c, id, val)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestUpCacheUpSwitch(t *testing.T) {
var (
c = context.TODO()
id = int64(0)
)
convey.Convey("CacheUpSwitch", t, func(ctx convey.C) {
res, err := d.CacheUpSwitch(c, id)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestUpDelCacheUpSwitch(t *testing.T) {
var (
c = context.TODO()
id = int64(0)
)
convey.Convey("DelCacheUpSwitch", t, func(ctx convey.C) {
err := d.DelCacheUpSwitch(c, id)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestUpAddCacheUpInfoActive(t *testing.T) {
var (
c = context.TODO()
id = int64(0)
val = &model.UpInfoActiveReply{}
)
convey.Convey("AddCacheUpInfoActive", t, func(ctx convey.C) {
err := d.AddCacheUpInfoActive(c, id, val)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestUpCacheUpInfoActive(t *testing.T) {
var (
c = context.TODO()
id = int64(0)
)
convey.Convey("CacheUpInfoActive", t, func(ctx convey.C) {
res, err := d.CacheUpInfoActive(c, id)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestUpDelCacheUpInfoActive(t *testing.T) {
var (
c = context.TODO()
id = int64(0)
)
convey.Convey("DelCacheUpInfoActive", t, func(ctx convey.C) {
err := d.DelCacheUpInfoActive(c, id)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,54 @@
package up
import (
"context"
"strconv"
"go-common/app/service/main/up/model"
"go-common/library/cache/memcache"
"go-common/library/log"
)
const (
_prefix = "allID_"
)
func keyIdentityAll(mid int64) string {
return _prefix + strconv.FormatInt(mid, 10)
}
// IdentityAllCache get all up all of identify type cache.
func (d *Dao) IdentityAllCache(c context.Context, mid int64) (st *model.IdentifyAll, err error) {
var (
conn = d.mcPool.Get(c)
r *memcache.Item
)
defer conn.Close()
r, err = conn.Get(keyIdentityAll(mid))
if err != nil {
if err == memcache.ErrNotFound {
err = nil
} else {
log.Error("conn.Get2(%d) error(%v)", mid, err)
}
return
}
if err = conn.Scan(r, &st); err != nil {
log.Error("json.Unmarshal(%s) error(%v)", r.Value, err)
st = nil
}
return
}
// AddIdentityAllCache add all of up identity type cache.
func (d *Dao) AddIdentityAllCache(c context.Context, mid int64, st *model.IdentifyAll) (err error) {
var (
key = keyIdentityAll(mid)
)
conn := d.mcPool.Get(c)
defer conn.Close()
if err = conn.Set(&memcache.Item{Key: key, Object: st, Flags: memcache.FlagJSON, Expiration: d.upExpire}); err != nil {
log.Error("memcache.Set(%v) error(%v)", key, err)
}
return
}

View File

@@ -0,0 +1,54 @@
package up
import (
"context"
"go-common/app/service/main/up/model"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestUpkeyIdentityAll(t *testing.T) {
var (
mid = int64(0)
)
convey.Convey("keyIdentityAll", t, func(ctx convey.C) {
p1 := keyIdentityAll(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestUpIdentityAllCache(t *testing.T) {
var (
c = context.TODO()
mid = int64(1)
st = &model.IdentifyAll{}
)
convey.Convey("IdentityAllCache", t, func(ctx convey.C) {
err := d.AddIdentityAllCache(c, mid, st)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
st, err := d.IdentityAllCache(c, mid)
ctx.Convey("Then err should be nil.st should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(st, convey.ShouldNotBeNil)
})
})
}
func TestUpAddIdentityAllCache(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
st = &model.IdentifyAll{}
)
convey.Convey("AddIdentityAllCache", t, func(ctx convey.C) {
err := d.AddIdentityAllCache(c, mid, st)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,76 @@
package up
import (
"context"
"fmt"
"go-common/app/service/main/up/model"
)
const (
_upKey = "up_srv_%d"
_upSwitchKey = "up_sw_%d"
_upInfoActive = "up_info_active_%d"
)
//go:generate $GOPATH/src/go-common/app/tool/cache/gen
type _cache interface {
//cache: -nullcache=&model.Up{ID:-1} -check_null_code=$!=nil&&$.ID==-1
Up(c context.Context, mid int64) (up *model.Up, err error)
//cache: -nullcache=&model.UpSwitch{ID:-1} -check_null_code=$!=nil&&$.ID==-1
UpSwitch(c context.Context, mid int64) (up *model.UpSwitch, err error)
//cache: -nullcache=&model.UpInfoActiveReply{ID:-1} -check_null_code=$!=nil&&$.ID==-1
UpInfoActive(c context.Context, mid int64) (up *model.UpInfoActiveReply, err error)
// cache: -batch=100 -max_group=1 -batch_err=break -nullcache=&model.UpInfoActiveReply{ID:-1} -check_null_code=$!=nil&&$.ID==-1
UpsInfoActive(c context.Context, mids []int64) (res map[int64]*model.UpInfoActiveReply, err error)
}
//go:generate $GOPATH/src/go-common/app/tool/cache/mc
type _mc interface {
//mc: -key=upCacheKey -expire=d.upExpire -encode=json
AddCacheUp(c context.Context, mid int64, up *model.Up) (err error)
//mc: -key=upCacheKey
CacheUp(c context.Context, mid int64) (up *model.Up, err error)
//mc: -key=upCacheKey
DelCacheUp(c context.Context, mid int64) (err error)
//mc: -key=upSwitchKey -expire=d.upExpire -encode=json
AddCacheUpSwitch(c context.Context, mid int64, up *model.UpSwitch) (err error)
//mc: -key=upSwitchKey
CacheUpSwitch(c context.Context, mid int64) (res *model.UpSwitch, err error)
//mc: -key=upSwitchKey
DelCacheUpSwitch(c context.Context, mid int64) (err error)
//mc: -key=upInfoActiveKey -expire=d.upExpire -encode=json
AddCacheUpInfoActive(c context.Context, mid int64, up *model.UpInfoActiveReply) (err error)
//mc: -key=upInfoActiveKey
CacheUpInfoActive(c context.Context, mid int64) (res *model.UpInfoActiveReply, err error)
//mc: -key=upInfoActiveKey
DelCacheUpInfoActive(c context.Context, mid int64) (err error)
// mc: -key=upInfoActiveKey -expire=d.upExpire -encode=json
AddCacheUpsInfoActive(c context.Context, res map[int64]*model.UpInfoActiveReply) (err error)
// mc: -key=upInfoActiveKey
CacheUpsInfoActive(c context.Context, mids []int64) (res map[int64]*model.UpInfoActiveReply, err error)
// mc: -key=upInfoActiveKey
DelCacheUpsInfoActive(c context.Context, mids []int64) (err error)
}
//upCacheKey 缓存key
func upCacheKey(mid int64) string {
return fmt.Sprintf(_upKey, mid)
}
//upSwitchCacheKey 缓存key
func upSwitchKey(mid int64) string {
return fmt.Sprintf(_upSwitchKey, mid)
}
//upInfoActiveCacheKey 缓存key
func upInfoActiveKey(mid int64) string {
return fmt.Sprintf(_upInfoActive, mid)
}
//DelCpUp 异步删除缓存
func (d *Dao) DelCpUp(c context.Context, mid int64) {
d.cache.Do(c, func(c context.Context) {
d.DelCacheUp(c, mid)
})
}

View File

@@ -0,0 +1,44 @@
package up
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestUpupCacheKey(t *testing.T) {
var (
mid = int64(0)
)
convey.Convey("upCacheKey", t, func(ctx convey.C) {
p1 := upCacheKey(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestUpupSwitchKey(t *testing.T) {
var (
mid = int64(0)
)
convey.Convey("upSwitchKey", t, func(ctx convey.C) {
p1 := upSwitchKey(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
}
func TestUpDelCpUp(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
)
convey.Convey("DelCpUp", t, func(ctx convey.C) {
d.DelCpUp(c, mid)
ctx.Convey("No return values", func(ctx convey.C) {
})
})
}

View File

@@ -0,0 +1,37 @@
package up
import (
"context"
"go-common/app/service/main/up/dao/global"
"go-common/app/service/main/up/model"
"go-common/library/log"
"go-common/library/xstr"
"time"
)
const (
// _getHighAllyUpsSql .
_getHighAllyUpsSql = "SELECT id, mid, state, begin_date, end_date FROM sign_up WHERE mid IN (?) AND end_date >= ? AND state <> 100"
)
// GetHighAllyUps dao get high ally ups
func (d *Dao) GetHighAllyUps(c context.Context, mids []int64) (res []*model.SignUp, err error) {
midStr := xstr.JoinInts(mids)
now := time.Now().Format(DateLayout)
rows, err := global.GetUpCrmDB().Query(c, _getHighAllyUpsSql, midStr, now)
if err != nil {
log.Error("d.GetHighAllyUps error (%v)", err)
return
}
for rows.Next() {
r := &model.SignUp{}
err = rows.Scan(&r.ID, &r.Mid, &r.State, &r.BeginDate, &r.EndDate)
if err != nil {
log.Error("d.GetHighAllyUps scan error (%v)", err)
return
}
res = append(res, r)
}
return
}

View File

@@ -0,0 +1,24 @@
package up
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestUpGetHighAllyUps(t *testing.T) {
convey.Convey("GetHighAllyUps", t, func(ctx convey.C) {
var (
c = context.Background()
mids = []int64{0}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.GetHighAllyUps(c, mids)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldBeEmpty)
})
})
})
}

View File

@@ -0,0 +1,66 @@
package up
import (
"context"
upgrpc "go-common/app/service/main/up/api/v1"
"go-common/app/service/main/up/dao/global"
"go-common/app/service/main/up/model"
"go-common/library/database/sql"
)
const (
// insert
_inUpInfoSQL = "INSERT INTO up (mid,attribute) VALUES (?,?) ON DUPLICATE KEY UPDATE attribute=?"
// select
_upInfoSQL = "SELECT id, mid, attribute FROM up WHERE mid = ?"
_upInfoActivitysSQL = "SELECT id, mid, activity FROM up_base_info WHERE id > ? AND business_type = 1 LIMIT ?"
)
// AddUp add up.
func (d *Dao) AddUp(c context.Context, u *model.Up) (id int64, err error) {
res, err := d.db.Exec(c, _inUpInfoSQL, u.MID, u.Attribute, u.Attribute)
if err != nil {
return
}
id, err = res.RowsAffected()
return
}
// RawUp get attribute.
func (d *Dao) RawUp(c context.Context, mid int64) (u *model.Up, err error) {
row := d.db.QueryRow(c, _upInfoSQL, mid)
u = &model.Up{}
if err = row.Scan(&u.ID, &u.MID, &u.Attribute); err != nil {
if err == sql.ErrNoRows {
u = nil
err = nil
return
}
}
return
}
// UpInfoActivitys list <id, UpActivity> k-v pairs
func (d *Dao) UpInfoActivitys(c context.Context, lastID int64, ps int) (mup map[int64]*upgrpc.UpActivity, err error) {
rows, err := global.GetUpCrmDB().Query(c, _upInfoActivitysSQL, lastID, ps)
if err != nil {
return
}
defer rows.Close()
mup = make(map[int64]*upgrpc.UpActivity, ps)
for rows.Next() {
var (
id int64
up = new(upgrpc.UpActivity)
)
if err = rows.Scan(&id, &up.Mid, &up.Activity); err != nil {
if err == sql.ErrNoRows {
err = nil
}
return
}
mup[id] = up
}
return
}

View File

@@ -0,0 +1,58 @@
package up
import (
"context"
"database/sql"
"errors"
"fmt"
"go-common/library/xstr"
"go-common/app/service/main/up/dao/global"
"go-common/app/service/main/up/model"
"go-common/library/log"
)
const (
// _getUpInfoActiveSQL .
_getUpInfoActiveSQL = "SELECT id, mid, active_tid FROM up_base_info WHERE mid = ?"
// _getUpsInfoActiveSQL .
_getUpsInfoActiveSQL = "SELECT id, mid, active_tid FROM up_base_info WHERE mid IN (%s)"
)
// RawUpInfoActive get up info active
func (d *Dao) RawUpInfoActive(ctx context.Context, mid int64) (upInfoActive *model.UpInfoActiveReply, err error) {
row := global.GetUpCrmDB().QueryRow(ctx, _getUpInfoActiveSQL, mid)
upInfoActive = &model.UpInfoActiveReply{}
if err = row.Scan(&upInfoActive.ID, &upInfoActive.MID, &upInfoActive.ActiveTid); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("RawUpInfoActive row.Scan error(%v)", err)
err = errors.New("RawUpInfoActive get data failed")
}
}
return
}
// RawUpsInfoActive get ups info active
func (d *Dao) RawUpsInfoActive(ctx context.Context, mids []int64) (res map[int64]*model.UpInfoActiveReply, err error) {
res = make(map[int64]*model.UpInfoActiveReply)
sql := fmt.Sprintf(_getUpsInfoActiveSQL, xstr.JoinInts(mids))
log.Info("SQL: %s", sql)
rows, err := global.GetUpCrmDB().Query(ctx, sql)
if err != nil {
log.Error("RawUpsInfoActive UpCrmDB.Query error(%v)", err)
return
}
for rows.Next() {
upInfoActive := model.UpInfoActiveReply{}
if err = rows.Scan(&upInfoActive.ID, &upInfoActive.MID, &upInfoActive.ActiveTid); err != nil {
log.Error("RawUpsInfoActive rows.Scan error(%v)", err)
return
}
res[upInfoActive.MID] = &upInfoActive
}
return
}

View File

@@ -0,0 +1,40 @@
package up
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestUpRawUpInfoActive(t *testing.T) {
convey.Convey("RawUpInfoActive", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
upInfoActive, err := d.RawUpInfoActive(c, mid)
ctx.Convey("Then err should be nil.upInfoActive should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(upInfoActive, convey.ShouldNotBeNil)
})
})
})
}
func TestUpRawUpsInfoActive(t *testing.T) {
convey.Convey("RawUpsInfoActive", t, func(ctx convey.C) {
var (
c = context.Background()
mids = []int64{0}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.RawUpsInfoActive(c, mids)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,38 @@
package up
import (
"context"
"database/sql"
"go-common/app/service/main/up/model"
)
const (
// insert
_inUPSwitchSQL = "INSERT INTO up_switch (mid, attribute) VALUES (?,?) ON DUPLICATE KEY UPDATE attribute=?"
// select
_getUPSwitchSQL = "SELECT id, mid, attribute FROM up_switch WHERE mid=?"
)
// SetSwitch add or update up switch.
func (d *Dao) SetSwitch(c context.Context, u *model.UpSwitch) (id int64, err error) {
res, err := d.db.Exec(c, _inUPSwitchSQL, u.MID, u.Attribute, u.Attribute)
if err != nil {
return
}
return res.RowsAffected()
}
// RawUpSwitch get up switch attribute.
func (d *Dao) RawUpSwitch(c context.Context, mid int64) (u *model.UpSwitch, err error) {
row := d.db.QueryRow(c, _getUPSwitchSQL, mid)
u = &model.UpSwitch{}
if err = row.Scan(&u.ID, &u.MID, &u.Attribute); err != nil {
if err == sql.ErrNoRows {
u = nil
err = nil
return
}
}
return
}

View File

@@ -0,0 +1,41 @@
package up
import (
"context"
"go-common/app/service/main/up/model"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestUpSetSwitch(t *testing.T) {
var (
c = context.Background()
u = &model.UpSwitch{
MID: int64(1),
Attribute: 0,
}
)
convey.Convey("SetSwitch", t, func(ctx convey.C) {
id, err := d.SetSwitch(c, u)
println(111, id)
ctx.Convey("Then err should be nil.id should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(id, convey.ShouldNotBeNil)
})
})
}
func TestUpRawUpSwitch(t *testing.T) {
var (
c = context.TODO()
mid = int64(0)
)
convey.Convey("RawUpSwitch", t, func(ctx convey.C) {
_, err := d.RawUpSwitch(c, mid)
ctx.Convey("Then err should be nil.u should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
//ctx.So(u, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,56 @@
package up
import (
"context"
"testing"
"go-common/app/service/main/up/model"
"github.com/smartystreets/goconvey/convey"
)
func TestUpAddUp(t *testing.T) {
var (
c = context.Background()
u = &model.Up{
MID: int64(2089809),
Attribute: 0,
}
)
convey.Convey("AddUp", t, func(ctx convey.C) {
id, err := d.AddUp(c, u)
ctx.Convey("Then err should be nil.id should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(id, convey.ShouldNotBeNil)
})
})
}
func TestUpRawUp(t *testing.T) {
var (
c = context.Background()
mid = int64(0)
)
convey.Convey("RawUp", t, func(ctx convey.C) {
u, err := d.RawUp(c, mid)
ctx.Convey("Then err should be nil.u should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(u, convey.ShouldNotBeNil)
})
})
}
func TestUpInfoActivitys(t *testing.T) {
var (
c = context.Background()
lastID = int64(0)
ps = 100
)
convey.Convey("UpInfoActivitys", t, func(ctx convey.C) {
u, err := d.UpInfoActivitys(c, lastID, ps)
ctx.Convey("Then err should be nil.u should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(u, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,93 @@
package dao
import "fmt"
const (
//logicNoOp = 0
logicOpAnd = 1
logicOpOr = 2
)
const (
//AppID appid
AppID = "main.archive.up-service"
//UatToken uat token
UatToken = "5f1660060bb011e8865c66d44b23cda7"
//TreeID uat treeid
TreeID = "15572"
)
// Condition 生成的condition为
// [before] [key] [operator] ? [after]
// 如
// [(] [id] [=] ? [and]
// [ctime] [>] ? [)]
// [order by] [time] nil [] //如果value是nil不会设置placeholder ?
type Condition struct {
logicOp int
Before string
Key string
Operator string
Value interface{}
After string
}
//ConcatCondition concat conditions
func ConcatCondition(conditions ...Condition) (conditionStr string, args []interface{}, hasOperator bool) {
hasOperator = false
for _, c := range conditions {
var questionMark = "?"
if c.Value == nil {
questionMark = ""
}
if c.Operator != "" {
hasOperator = true
}
var logicOp = ""
switch c.logicOp {
case logicOpAnd:
logicOp = " and "
case logicOpOr:
logicOp = " or "
}
conditionStr += fmt.Sprintf(" %s %s %s %s %s %s", logicOp, c.Before, c.Key, c.Operator, questionMark, c.After)
if c.Value != nil {
args = append(args, c.Value)
}
}
return
}
//AndCondition and condition
func AndCondition(conditions ...Condition) (result []Condition) {
return addLogicOperator(logicOpAnd, conditions...)
}
//OrCondition or condition
func OrCondition(conditions ...Condition) (result []Condition) {
return addLogicOperator(logicOpOr, conditions...)
}
func addLogicOperator(operator int, conditions ...Condition) (result []Condition) {
var isFirst = true
for _, v := range conditions {
if isFirst {
isFirst = false
} else {
v.logicOp = operator
}
result = append(result, v)
}
return
}
// Split split num by size; size should be positive
func Split(start int, end int, size int, f func(start int, end int)) {
for s := start; s < end; s += size {
e := s + size
if e > end {
e = end
}
f(s, e)
}
}

View File

@@ -0,0 +1,69 @@
package dao
import (
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoConcatCondition(t *testing.T) {
var (
conditions Condition
)
convey.Convey("ConcatCondition", t, func(ctx convey.C) {
conditionStr, args, hasOperator := ConcatCondition(conditions)
ctx.Convey("Then conditionStr,args,hasOperator should not be nil.", func(ctx convey.C) {
ctx.So(hasOperator, convey.ShouldNotBeNil)
ctx.So(args, convey.ShouldBeNil)
ctx.So(conditionStr, convey.ShouldNotBeNil)
})
})
}
func TestDaoAndCondition(t *testing.T) {
var (
conditions Condition
)
convey.Convey("AndCondition", t, func(ctx convey.C) {
result := AndCondition(conditions)
ctx.Convey("Then result should not be nil.", func(ctx convey.C) {
ctx.So(result, convey.ShouldNotBeNil)
})
})
}
func TestDaoOrCondition(t *testing.T) {
var (
conditions Condition
)
convey.Convey("OrCondition", t, func(ctx convey.C) {
result := OrCondition(conditions)
ctx.Convey("Then result should not be nil.", func(ctx convey.C) {
ctx.So(result, convey.ShouldNotBeNil)
})
})
}
func TestDaoaddLogicOperator(t *testing.T) {
var (
operator = int(0)
conditions Condition
)
convey.Convey("addLogicOperator", t, func(ctx convey.C) {
result := addLogicOperator(operator, conditions)
ctx.Convey("Then result should not be nil.", func(ctx convey.C) {
ctx.So(result, convey.ShouldNotBeNil)
})
})
}
func TestSplit(t *testing.T) {
var (
start = 0
end = 100
size = 10
f = func(start int, end int) {}
)
convey.Convey("split", t, func(ctx convey.C) {
Split(start, end, size, f)
})
}