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,28 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/interface/main/mcn/dao/bfs:all-srcs",
"//app/interface/main/mcn/dao/cache:all-srcs",
"//app/interface/main/mcn/dao/datadao:all-srcs",
"//app/interface/main/mcn/dao/global:all-srcs",
"//app/interface/main/mcn/dao/mcndao:all-srcs",
"//app/interface/main/mcn/dao/msg:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,52 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"upload.go",
],
importpath = "go-common/app/interface/main/mcn/dao/bfs",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/mcn/conf: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"],
)
go_test(
name = "go_default_test",
srcs = [
"dao_test.go",
"upload_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/mcn/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
"//vendor/gopkg.in/h2non/gock.v1:go_default_library",
],
)

View File

@@ -0,0 +1,26 @@
package bfs
import (
"go-common/app/interface/main/mcn/conf"
)
// Dao dao
type Dao struct {
c *conf.Config
bucket string
key string
secret string
bfs string
}
// New init mysql db
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
bucket: c.BFS.Bucket,
key: c.BFS.Key,
secret: c.BFS.Secret,
bfs: c.Host.Bfs,
}
return
}

View File

@@ -0,0 +1,47 @@
package bfs
import (
"flag"
"os"
"strings"
"testing"
"go-common/app/interface/main/mcn/conf"
"gopkg.in/h2non/gock.v1"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.mcn-interface")
flag.Set("conf_token", "49e4671bafbf93059aeb602685052ca0")
flag.Set("tree_id", "58909")
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/mcn-interface.toml")
}
if os.Getenv("UT_LOCAL_TEST") != "" {
flag.Set("conf", "../../cmd/mcn-interface.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
os.Exit(m.Run())
}
func httpMock(method, url string) *gock.Request {
r := gock.New(url)
r.Method = strings.ToUpper(method)
return r
}

View File

@@ -0,0 +1,74 @@
package bfs
import (
"context"
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"fmt"
"hash"
"io"
"net/http"
"strconv"
"go-common/library/log"
)
const (
uploadurl = "/bfs/%s/%s"
template = "%s\n%s\n%s\n%d\n"
method = "PUT"
)
// Upload upload picture or log file to bfs
func (d *Dao) Upload(c context.Context, fileName, fileType string, expire int64, body io.Reader) (location string, err error) {
var (
url string
req *http.Request
resp *http.Response
code int
)
client := &http.Client{}
url = fmt.Sprintf(d.bfs+uploadurl, d.bucket, fileName)
if req, err = http.NewRequest(method, url, body); err != nil {
log.Error("http.NewRequest() Upload(%v) error(%v)", url, err)
return
}
authorization := authorize(d.key, d.secret, method, d.bucket, fileName, expire)
req.Header.Set("Host", d.bfs)
req.Header.Add("Date", fmt.Sprint(expire))
req.Header.Add("Authorization", authorization)
req.Header.Add("Content-Type", fileType)
resp, err = client.Do(req)
if err != nil {
log.Error("resp.Do(%s) error(%v)", url, err)
return
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
err = fmt.Errorf("status code error:%v", resp.StatusCode)
return
}
code, err = strconv.Atoi(resp.Header.Get("code"))
if err != nil || code != http.StatusOK {
err = fmt.Errorf("response code error:%v", code)
return
}
location = resp.Header.Get("Location")
return
}
// authorize returns authorization for upload file to bfs
func authorize(key, secret, method, bucket, file string, expire int64) (authorization string) {
var (
content string
mac hash.Hash
signature string
)
content = fmt.Sprintf(template, method, bucket, file, expire)
mac = hmac.New(sha1.New, []byte(secret))
mac.Write([]byte(content))
signature = base64.StdEncoding.EncodeToString(mac.Sum(nil))
authorization = fmt.Sprintf("%s:%s:%d", key, signature, expire)
return
}

View File

@@ -0,0 +1,51 @@
package bfs
import (
"bytes"
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
"gopkg.in/h2non/gock.v1"
)
func TestBfsUpload(t *testing.T) {
convey.Convey("Upload", t, func(ctx convey.C) {
var (
c = context.Background()
fileName = ""
fileType = "plain/text"
expire = int64(0)
body = bytes.NewBuffer([]byte("just test"))
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
defer gock.OffAll()
httpMock("PUT", d.bfs).Reply(200).SetHeader("code", "200").SetHeader("Location", "baidu")
location, err := d.Upload(c, fileName, fileType, expire, body)
ctx.Convey("Then err should be nil.location should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(location, convey.ShouldNotBeNil)
})
})
})
}
func TestBfsauthorize(t *testing.T) {
convey.Convey("authorize", t, func(ctx convey.C) {
var (
key = "1234"
secret = "wer1234"
method = "poost"
bucket = "dte"
file = "www"
expire = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
authorization := authorize(key, secret, method, bucket, file, expire)
ctx.Convey("Then authorization should not be nil.", func(ctx convey.C) {
ctx.So(authorization, convey.ShouldNotBeNil)
})
})
})
}

57
app/interface/main/mcn/dao/cache/BUILD vendored Normal file
View File

@@ -0,0 +1,57 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"cache.go",
"tag.go",
"video_types.go",
],
importpath = "go-common/app/interface/main/mcn/dao/cache",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/creative/model/tag:go_default_library",
"//app/interface/main/mcn/conf:go_default_library",
"//app/service/main/videoup/model/archive:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster: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 = [
"cache_test.go",
"tag_test.go",
"video_types_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/creative/model/tag:go_default_library",
"//app/interface/main/mcn/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,9 @@
package cache
import "time"
//LoadCache load cache
func LoadCache() {
var now = time.Now()
RefreshUpType(now)
}

View File

@@ -0,0 +1,46 @@
package cache
import (
"flag"
"os"
"testing"
"go-common/app/interface/main/mcn/conf"
"github.com/smartystreets/goconvey/convey"
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.mcn-interface")
flag.Set("conf_token", "49e4671bafbf93059aeb602685052ca0")
flag.Set("tree_id", "58909")
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/mcn-interface.toml")
}
if os.Getenv("UT_LOCAL_TEST") != "" {
flag.Set("conf", "../../cmd/mcn-interface.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
os.Exit(m.Run())
}
func TestCacheLoadCache(t *testing.T) {
convey.Convey("LoadCache", t, func(ctx convey.C) {
ctx.Convey("When everything goes positive", func(ctx convey.C) {
LoadCache()
ctx.Convey("No return values", func(ctx convey.C) {
})
})
})
}

46
app/interface/main/mcn/dao/cache/tag.go vendored Normal file
View File

@@ -0,0 +1,46 @@
package cache
import (
"sync"
"time"
"go-common/app/interface/main/creative/model/tag"
)
var (
//TagCache tag's cache key=>tag_id, value=>*tag.Meta
TagCache = make(map[int64]*tag.Meta)
tagMutex sync.Mutex
)
//ClearTagCache clear all tag cache
func ClearTagCache(tm time.Time) {
TagCache = make(map[int64]*tag.Meta)
}
//AddTagCache add tag cache
func AddTagCache(meta *tag.Meta) {
if meta == nil {
return
}
tagMutex.Lock()
TagCache[meta.TagID] = meta
tagMutex.Unlock()
}
//GetTagCache get tag cache
func GetTagCache(ids ...int64) (result map[int64]*tag.Meta, leftIDs []int64) {
result = make(map[int64]*tag.Meta)
tagMutex.Lock()
for _, v := range ids {
var d, ok = TagCache[v]
if !ok {
leftIDs = append(leftIDs, v)
continue
}
result[v] = d
}
tagMutex.Unlock()
return
}

View File

@@ -0,0 +1,52 @@
package cache
import (
"testing"
"time"
"go-common/app/interface/main/creative/model/tag"
"github.com/smartystreets/goconvey/convey"
)
func TestCacheClearTagCache(t *testing.T) {
convey.Convey("ClearTagCache", t, func(ctx convey.C) {
var (
tm = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
ClearTagCache(tm)
ctx.Convey("No return values", func(ctx convey.C) {
})
})
})
}
func TestCacheAddTagCache(t *testing.T) {
convey.Convey("AddTagCache", t, func(ctx convey.C) {
var (
meta = &tag.Meta{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
AddTagCache(meta)
ctx.Convey("No return values", func(ctx convey.C) {
})
})
})
}
func TestCacheGetTagCache(t *testing.T) {
convey.Convey("GetTagCache", t, func(ctx convey.C) {
var (
ids = int64(3)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
LoadCache()
result, leftIDs := GetTagCache(ids)
ctx.Convey("Then result,leftIDs should not be nil.", func(ctx convey.C) {
ctx.So(leftIDs, convey.ShouldNotBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,60 @@
package cache
import (
"context"
"time"
"go-common/app/interface/main/mcn/conf"
"go-common/app/service/main/videoup/model/archive"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
)
var (
//VideoUpTypeCache cache for video types, map key is tid
VideoUpTypeCache = make(map[int]archive.Type)
)
//RefreshUpTypeAsync refresh in a goroutine
func RefreshUpTypeAsync(tm time.Time) {
go RefreshUpType(tm)
}
//RefreshUpType refresh
func RefreshUpType(tm time.Time) {
var url = conf.Conf.Host.Videoup + "/videoup/types"
var client = bm.NewClient(conf.Conf.HTTPClient)
var result struct {
Code int `json:"code"`
Data map[int]archive.Type `json:"data"`
}
var err = client.Get(context.Background(), url, "", nil, &result)
if err != nil {
log.Error("refresh videoup types fail, err=%v", err)
return
}
log.Info("refresh videoup types ok")
VideoUpTypeCache = result.Data
}
//GetTidName get tid name
func GetTidName(tid int64) string {
info, ok := VideoUpTypeCache[int(tid)]
if !ok {
return ""
}
return info.Name
}
// GetTidNames get tid name
func GetTidNames(tids []int64) (tpNames map[int64]string) {
tpNames = make(map[int64]string, len(tids))
for _, tid := range tids {
info, ok := VideoUpTypeCache[int(tid)]
if !ok {
continue
}
tpNames[tid] = info.Name
}
return
}

View File

@@ -0,0 +1,48 @@
package cache
import (
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestCacheRefreshUpTypeAsync(t *testing.T) {
convey.Convey("RefreshUpTypeAsync", t, func(ctx convey.C) {
var (
tm = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
RefreshUpTypeAsync(tm)
ctx.Convey("No return values", func(ctx convey.C) {
})
})
})
}
func TestCacheRefreshUpType(t *testing.T) {
convey.Convey("RefreshUpType", t, func(ctx convey.C) {
var (
tm = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
RefreshUpType(tm)
ctx.Convey("No return values", func(ctx convey.C) {
})
})
})
}
func TestCacheGetTidName(t *testing.T) {
convey.Convey("GetTidName", t, func(ctx convey.C) {
var (
tid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := GetTidName(tid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,72 @@
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",
"cache_test.go",
"creative_test.go",
"dao_test.go",
],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//app/interface/main/mcn/conf:go_default_library",
"//app/interface/main/mcn/dao/global:go_default_library",
"//app/interface/main/mcn/model/datamodel:go_default_library",
"//app/interface/main/mcn/tool/datacenter: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",
"cache.go",
"creative.go",
"dao.go",
],
importpath = "go-common/app/interface/main/mcn/dao/datadao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/mcn/conf:go_default_library",
"//app/interface/main/mcn/dao/cache:go_default_library",
"//app/interface/main/mcn/dao/global:go_default_library",
"//app/interface/main/mcn/model/datamodel:go_default_library",
"//app/interface/main/mcn/model/mcnmodel:go_default_library",
"//app/interface/main/mcn/tool/cache:go_default_library",
"//app/interface/main/mcn/tool/datacenter:go_default_library",
"//app/interface/main/tag/api:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/metadata:go_default_library",
"//library/sync/errgroup: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,577 @@
package datadao
import (
"context"
"fmt"
"net/http"
"net/url"
"time"
"go-common/app/interface/main/mcn/dao/cache"
"go-common/app/interface/main/mcn/dao/global"
"go-common/app/interface/main/mcn/model/datamodel"
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/app/interface/main/mcn/tool/datacenter"
tagmdl "go-common/app/interface/main/tag/api"
"go-common/library/log"
"go-common/library/sync/errgroup"
)
// const url for api
const (
APIMcnSummary = "http://berserker.bilibili.co/avenger/api/155/query" // 7 see doc http://info.bilibili.co/pages/viewpage.action?pageId=11545690
APIIndexInc = "http://berserker.bilibili.co/avenger/api/156/query" // 3.1
APIIndexSource = "http://berserker.bilibili.co/avenger/api/159/query" // 3.2
APIPlaySource = "http://berserker.bilibili.co/avenger/api/161/query" // 3.3
APIMcnFans = "http://berserker.bilibili.co/avenger/api/168/query" // 3.4
APIMcnFansInc = "http://berserker.bilibili.co/avenger/api/171/query" // 3.5
APIMcnFansDec = "http://berserker.bilibili.co/avenger/api/169/query" // 3.6
APIMcnFansAttentionWay = "http://berserker.bilibili.co/avenger/api/170/query" // 3.7
APIMcnFansSex = "http://berserker.bilibili.co/avenger/api/162/query" // 3.8
APIMcnFansAge = "http://berserker.bilibili.co/avenger/api/163/query" // 3.8
APIMcnFansPlayWay = "http://berserker.bilibili.co/avenger/api/164/query" // 3.8
APIMcnFansArea = "http://berserker.bilibili.co/avenger/api/165/query" // 3.9
APIMcnFansType = "http://berserker.bilibili.co/avenger/api/166/query" // 3.10
APIMcnFansTag = "http://berserker.bilibili.co/avenger/api/167/query" // 3.11
)
func (d *Dao) callDataAPI(c context.Context, api string, query *datacenter.Query, res interface{}) (err error) {
var response = &datacenter.Response{
Result: res,
}
if query.Error() != nil {
err = query.Error()
log.Error("query error, err=%s", err)
return
}
var params = url.Values{}
params.Add("query", query.String())
if err = d.Client.Get(c, api, params, response); err != nil {
log.Error("fail to get response, err=%+v", err)
return
}
if response.Code != http.StatusOK {
err = fmt.Errorf("code:%d, msg:%s", response.Code, response.Msg)
return
}
return
}
// GetMcnSummary 7
// see doc http://info.bilibili.co/pages/viewpage.action?pageId=11545690#id-对外接口文档-7.mcn获取概要数据
func (d *Dao) GetMcnSummary(c context.Context, signID int64, date time.Time) (res *mcnmodel.McnGetDataSummaryReply, err error) {
res = new(mcnmodel.McnGetDataSummaryReply)
var tmp []*datamodel.DmConMcnArchiveD
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionLte(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
).Limit(1, 0).Order("log_date desc")
var api = APIMcnSummary
if err = d.callDataAPI(c, api, q, &tmp); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
if len(tmp) > 0 {
res.CopyFromDmConMcnArchiveD(tmp[0])
}
//log.Info("%s query arg(%d,%+v) res(%+v)", api, signID, date, tmp[0])
return
}
//GetMcnSummaryCache GetMcnSummary with cache
func (d *Dao) GetMcnSummaryCache(c context.Context, signID int64, date time.Time) (res *mcnmodel.McnGetDataSummaryReply, err error) {
res = new(mcnmodel.McnGetDataSummaryReply)
var cache = NewCacheMcnDataSignID(signID, date, res, "McnGetDataSummaryReply", func(c context.Context, signID int64, date time.Time) (res interface{}, err error) {
return d.GetMcnSummary(c, signID, date)
})
if err = d.McWrapper.GetOrLoad(c, cache); err != nil {
log.Error("cache get err, err=%v", err)
return
}
return
}
// GetIndexInc 3.1
// see doc http://info.bilibili.co/pages/viewpage.action?pageId=11545690#id-对外接口文档-3.1.查询MCN增量趋势
func (d *Dao) GetIndexInc(c context.Context, signID int64, date time.Time, tp string) (res *mcnmodel.McnGetIndexIncReply, err error) {
res = new(mcnmodel.McnGetIndexIncReply)
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionLte(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
datacenter.ConditionMapType{"type": datacenter.ConditionIn(tp)},
).Limit(30, 0).Order("log_date desc")
var api = APIIndexInc
if err = d.callDataAPI(c, api, q, &res.Result); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
//log.Info("%s query arg(%d,%+v,%s) res(%+v)", api, signID, date, tp, res.Result[0])
return
}
//GetIndexIncCache GetIndexInc with cache
func (d *Dao) GetIndexIncCache(c context.Context, signID int64, date time.Time, tp string) (res *mcnmodel.McnGetIndexIncReply, err error) {
res = new(mcnmodel.McnGetIndexIncReply)
var cache = NewCacheMcnDataWithTp(signID, date, tp, res, "McnGetIndexIncReply", func(c context.Context, signID int64, date time.Time, tp string) (res interface{}, err error) {
return d.GetIndexInc(c, signID, date, tp)
})
if err = d.McWrapper.GetOrLoad(c, cache); err != nil {
log.Error("cache get err, err=%v", err)
return
}
return
}
// GetIndexSource 3.2
// see doc http://info.bilibili.co/pages/viewpage.action?pageId=11545690#id-对外接口文档-3.2.查询MCN下播放稿件来源所在分区
func (d *Dao) GetIndexSource(c context.Context, signID int64, date time.Time, tp string) (res *mcnmodel.McnGetIndexSourceReply, err error) {
res = new(mcnmodel.McnGetIndexSourceReply)
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionIn(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
datacenter.ConditionMapType{"type": datacenter.ConditionIn(tp)},
)
var api = APIIndexSource
if err = d.callDataAPI(c, api, q, &res.Result); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
var tids []int64
for _, v := range res.Result {
tids = append(tids, v.TypeID)
}
tpNames := cache.GetTidNames(tids)
for _, v := range res.Result {
if tpName, ok := tpNames[v.TypeID]; ok {
v.TypeName = tpName
}
}
//log.Info("%s query arg(%d,%+v,%s) res(%+v)", api, signID, date, tp, res.Result[0])
return
}
//GetIndexSourceCache GetIndexSource with cache
func (d *Dao) GetIndexSourceCache(c context.Context, signID int64, date time.Time, tp string) (res *mcnmodel.McnGetIndexSourceReply, err error) {
res = new(mcnmodel.McnGetIndexSourceReply)
var cache = NewCacheMcnDataWithTp(signID, date, tp, res, "McnGetIndexSourceReply", func(c context.Context, signID int64, date time.Time, tp string) (res interface{}, err error) {
return d.GetIndexSource(c, signID, date, tp)
})
if err = d.McWrapper.GetOrLoad(c, cache); err != nil {
log.Error("cache get err, err=%v", err)
return
}
return
}
// GetPlaySource 3.3
// see doc http://info.bilibili.co/pages/viewpage.action?pageId=11545690#id-对外接口文档-3.3.查询MCN播放设备占比
func (d *Dao) GetPlaySource(c context.Context, signID int64, date time.Time) (res *mcnmodel.McnGetPlaySourceReply, err error) {
res = new(mcnmodel.McnGetPlaySourceReply)
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionLte(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
).Limit(1, 0).Order("log_date desc")
var api = APIPlaySource
var tmp []*mcnmodel.McnGetPlaySourceReply
if err = d.callDataAPI(c, api, q, &tmp); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
if len(tmp) > 0 {
res = tmp[0]
}
//log.Info("%s query arg(%d,%+v) res(%+v)", api, signID, date, tmp)
return
}
//GetPlaySourceCache GetPlaySource with cache
func (d *Dao) GetPlaySourceCache(c context.Context, signID int64, date time.Time) (res *mcnmodel.McnGetPlaySourceReply, err error) {
res = new(mcnmodel.McnGetPlaySourceReply)
var cache = NewCacheMcnDataSignID(signID, date, res, "McnGetPlaySourceReply", func(c context.Context, signID int64, date time.Time) (res interface{}, err error) {
return d.GetPlaySource(c, signID, date)
})
if err = d.McWrapper.GetOrLoad(c, cache); err != nil {
log.Error("cache get err, err=%v", err)
return
}
return
}
// GetMcnFans 3.4
// see doc http://info.bilibili.co/pages/viewpage.action?pageId=11545690#id-对外接口文档-3.4.查询MCN粉丝数与活跃度
func (d *Dao) GetMcnFans(c context.Context, signID int64, date time.Time) (res *mcnmodel.McnGetMcnFansReply, err error) {
res = new(mcnmodel.McnGetMcnFansReply)
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionLte(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
).Limit(1, 0).Order("log_date desc")
var tmp []*mcnmodel.McnGetMcnFansReply
var api = APIMcnFans
if err = d.callDataAPI(c, api, q, &tmp); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
if len(tmp) > 0 {
res = tmp[0]
}
//log.Info("%s query arg(%d,%+v) res(%+v)", api, signID, date, tmp[0])
return
}
//GetMcnFansCache GetMcnFans with cache
func (d *Dao) GetMcnFansCache(c context.Context, signID int64, date time.Time) (res *mcnmodel.McnGetMcnFansReply, err error) {
res = new(mcnmodel.McnGetMcnFansReply)
var cache = NewCacheMcnDataSignID(signID, date, res, "McnGetMcnFansReply", func(c context.Context, signID int64, date time.Time) (res interface{}, err error) {
return d.GetMcnFans(c, signID, date)
})
if err = d.McWrapper.GetOrLoad(c, cache); err != nil {
log.Error("cache get err, err=%v", err)
return
}
return
}
// GetMcnFansInc 3.5
// see doc http://info.bilibili.co/pages/viewpage.action?pageId=11545690#id-对外接口文档-3.5.查询MCN粉丝按天增量
func (d *Dao) GetMcnFansInc(c context.Context, signID int64, date time.Time) (res *mcnmodel.McnGetMcnFansIncReply, err error) {
res = new(mcnmodel.McnGetMcnFansIncReply)
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionLte(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
).Limit(30, 0).Order("log_date desc")
var api = APIMcnFansInc
if err = d.callDataAPI(c, api, q, &res.Result); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
//log.Info("%s query arg(%d,%+v) res(%+v)", api, signID, date, res.Result[0])
return
}
//GetMcnFansIncCache GetMcnFansInc with cache
func (d *Dao) GetMcnFansIncCache(c context.Context, signID int64, date time.Time) (res *mcnmodel.McnGetMcnFansIncReply, err error) {
res = new(mcnmodel.McnGetMcnFansIncReply)
var cache = NewCacheMcnDataSignID(signID, date, res, "McnGetMcnFansIncReply", func(c context.Context, signID int64, date time.Time) (res interface{}, err error) {
return d.GetMcnFansInc(c, signID, date)
})
if err = d.McWrapper.GetOrLoad(c, cache); err != nil {
log.Error("cache get err, err=%v", err)
return
}
return
}
// GetMcnFansDec 3.6
// see doc http://info.bilibili.co/pages/viewpage.action?pageId=11545690#id-对外接口文档-3.6.查询MCN粉丝取关数按天
func (d *Dao) GetMcnFansDec(c context.Context, signID int64, date time.Time) (res *mcnmodel.McnGetMcnFansDecReply, err error) {
res = new(mcnmodel.McnGetMcnFansDecReply)
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionLte(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
).Limit(30, 0).Order("log_date desc")
var api = APIMcnFansDec
if err = d.callDataAPI(c, api, q, &res.Result); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
//log.Info("%s query arg(%d,%+v) res(%+v)", api, signID, date, res.Result[0])
return
}
//GetMcnFansDecCache GetMcnFansDec with cache
func (d *Dao) GetMcnFansDecCache(c context.Context, signID int64, date time.Time) (res *mcnmodel.McnGetMcnFansDecReply, err error) {
res = new(mcnmodel.McnGetMcnFansDecReply)
var cache = NewCacheMcnDataSignID(signID, date, res, "McnGetMcnFansDecReply", func(c context.Context, signID int64, date time.Time) (res interface{}, err error) {
return d.GetMcnFansDec(c, signID, date)
})
if err = d.McWrapper.GetOrLoad(c, cache); err != nil {
log.Error("cache get err, err=%v", err)
return
}
return
}
// GetMcnFansAttentionWay 3.7
// see doc http://info.bilibili.co/pages/viewpage.action?pageId=11545690#id-对外接口文档-3.7.查询MCN粉丝关注渠道
func (d *Dao) GetMcnFansAttentionWay(c context.Context, signID int64, date time.Time) (res *mcnmodel.McnGetMcnFansAttentionWayReply, err error) {
res = new(mcnmodel.McnGetMcnFansAttentionWayReply)
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionLte(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
).Limit(1, 0).Order("log_date desc")
var tmp []*mcnmodel.McnGetMcnFansAttentionWayReply
var api = APIMcnFansAttentionWay
if err = d.callDataAPI(c, api, q, &tmp); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
if len(tmp) > 0 {
res = tmp[0]
}
//log.Info("%s query arg(%d,%+v) res(%+v)", api, signID, date, tmp[0])
return
}
//GetMcnFansAttentionWayCache GetMcnFansAttentionWay with cache
func (d *Dao) GetMcnFansAttentionWayCache(c context.Context, signID int64, date time.Time) (res *mcnmodel.McnGetMcnFansAttentionWayReply, err error) {
res = new(mcnmodel.McnGetMcnFansAttentionWayReply)
var cache = NewCacheMcnDataSignID(signID, date, res, "McnGetMcnFansAttentionWayReply", func(c context.Context, signID int64, date time.Time) (res interface{}, err error) {
return d.GetMcnFansAttentionWay(c, signID, date)
})
if err = d.McWrapper.GetOrLoad(c, cache); err != nil {
log.Error("cache get err, err=%v", err)
return
}
return
}
// GetFansBaseFansAttr 3.8
// see doc http://info.bilibili.co/pages/viewpage.action?pageId=11545690#id-对外接口文档-3.8.查询MCN粉丝/游客基本属性分析(性别占比 观众年龄 观看途径)
func (d *Dao) GetFansBaseFansAttr(c context.Context, signID int64, date time.Time, tp string) (res *mcnmodel.McnGetBaseFansAttrReply, err error) {
res = new(mcnmodel.McnGetBaseFansAttrReply)
var group, _ = errgroup.WithContext(c)
group.Go(func() (err error) {
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionLte(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
datacenter.ConditionMapType{"type": datacenter.ConditionIn(tp)},
).Limit(1, 0).Order("log_date desc")
var api = APIMcnFansSex
var tmp []*datamodel.DmConMcnFansSexW
if err = d.callDataAPI(context.Background(), api, q, &tmp); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
if len(tmp) > 0 {
res.FansSex = tmp[0]
}
//log.Info("%s query arg(%d,%+v,%s) res(%+v)", api, signID, date, tp, tmp[0])
return
})
group.Go(func() (err error) {
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionLte(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
datacenter.ConditionMapType{"type": datacenter.ConditionIn(tp)},
).Limit(1, 0).Order("log_date desc")
var tmp []*datamodel.DmConMcnFansAgeW
var api = APIMcnFansAge
if err = d.callDataAPI(context.Background(), api, q, &tmp); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
if len(tmp) > 0 {
res.FansAge = tmp[0]
}
//log.Info("%s query arg(%d,%+v,%s) res(%+v)", api, signID, date, tp, tmp[0])
return
})
group.Go(func() (err error) {
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionLte(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
datacenter.ConditionMapType{"type": datacenter.ConditionIn(tp)},
).Limit(1, 0).Order("log_date desc")
var tmp []*datamodel.DmConMcnFansPlayWayW
var api = APIMcnFansPlayWay
if err = d.callDataAPI(context.Background(), api, q, &tmp); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
if len(tmp) > 0 {
res.FansPlayWay = tmp[0]
}
//log.Info("%s query arg(%d,%+v,%s) res(%+v)", api, signID, date, tp, tmp[0])
return
})
err = group.Wait()
if err != nil {
log.Error("fail to get data, err=%v", err)
return
}
return
}
//GetFansBaseFansAttrCache GetFansBaseFansAttr with cache
func (d *Dao) GetFansBaseFansAttrCache(c context.Context, signID int64, date time.Time, tp string) (res *mcnmodel.McnGetBaseFansAttrReply, err error) {
res = new(mcnmodel.McnGetBaseFansAttrReply)
var cache = NewCacheMcnDataWithTp(signID, date, tp, res, "McnGetBaseFansAttrReply", func(c context.Context, signID int64, date time.Time, tp string) (res interface{}, err error) {
return d.GetFansBaseFansAttr(c, signID, date, tp)
})
if err = d.McWrapper.GetOrLoad(c, cache); err != nil {
log.Error("cache get err, err=%v", err)
return
}
return
}
// GetFansArea 3.9
// see doc http://info.bilibili.co/pages/viewpage.action?pageId=11545690#id-对外接口文档-3.9.查询MCN粉丝/游客地区分布分析
func (d *Dao) GetFansArea(c context.Context, signID int64, date time.Time, tp string) (res *mcnmodel.McnGetFansAreaReply, err error) {
res = new(mcnmodel.McnGetFansAreaReply)
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionIn(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
datacenter.ConditionMapType{"type": datacenter.ConditionIn(tp)},
)
var api = APIMcnFansArea
if err = d.callDataAPI(c, api, q, &res.Result); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
//log.Info("%s query arg(%d,%+v,%s) res(%+v)", api, signID, date, tp, res.Result[0])
return
}
//GetFansAreaCache GetFansArea with cache
func (d *Dao) GetFansAreaCache(c context.Context, signID int64, date time.Time, tp string) (res *mcnmodel.McnGetFansAreaReply, err error) {
res = new(mcnmodel.McnGetFansAreaReply)
var cache = NewCacheMcnDataWithTp(signID, date, tp, res, "McnGetFansAreaReply", func(c context.Context, signID int64, date time.Time, tp string) (res interface{}, err error) {
return d.GetFansArea(c, signID, date, tp)
})
if err = d.McWrapper.GetOrLoad(c, cache); err != nil {
log.Error("cache get err, err=%v", err)
return
}
return
}
// GetFansType 3.10
// see doc http://info.bilibili.co/pages/viewpage.action?pageId=11545690#id-对外接口文档-3.10.查询MCN粉丝/游客内容倾向分析
func (d *Dao) GetFansType(c context.Context, signID int64, date time.Time, tp string) (res *mcnmodel.McnGetFansTypeReply, err error) {
res = new(mcnmodel.McnGetFansTypeReply)
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionIn(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
datacenter.ConditionMapType{"type": datacenter.ConditionIn(tp)},
)
var api = APIMcnFansType
if err = d.callDataAPI(c, api, q, &res.Result); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
var tids []int64
for _, v := range res.Result {
tids = append(tids, v.TypeID)
}
tpNames := cache.GetTidNames(tids)
for _, v := range res.Result {
if tpName, ok := tpNames[v.TypeID]; ok {
v.TypeName = tpName
}
}
//log.Info("%s query arg(%d,%+v,%s) res(%+v)", api, signID, date, tp, res.Result[0])
return
}
//GetFansTypeCache GetFansType with cache
func (d *Dao) GetFansTypeCache(c context.Context, signID int64, date time.Time, tp string) (res *mcnmodel.McnGetFansTypeReply, err error) {
res = new(mcnmodel.McnGetFansTypeReply)
var cache = NewCacheMcnDataWithTp(signID, date, tp, res, "McnGetFansTypeReply", func(c context.Context, signID int64, date time.Time, tp string) (res interface{}, err error) {
return d.GetFansType(c, signID, date, tp)
})
if err = d.McWrapper.GetOrLoad(c, cache); err != nil {
log.Error("cache get err, err=%v", err)
return
}
return
}
// GetFansTag 3.11
// see doc http://info.bilibili.co/pages/viewpage.action?pageId=11545690#id-对外接口文档-3.11.查询MCN粉丝/游客标签地图分析
func (d *Dao) GetFansTag(c context.Context, signID int64, date time.Time, tp string) (res *mcnmodel.McnGetFansTagReply, err error) {
res = new(mcnmodel.McnGetFansTagReply)
var q = &datacenter.Query{}
q.Select("*").Where(
datacenter.ConditionMapType{"log_date": datacenter.ConditionIn(date)},
datacenter.ConditionMapType{"sign_id": datacenter.ConditionIn(signID)},
datacenter.ConditionMapType{"type": datacenter.ConditionIn(tp)},
)
var api = APIMcnFansTag
if err = d.callDataAPI(c, api, q, &res.Result); err != nil {
log.Error("call data api fail, api=%s, err=%s", api, err)
return
}
var tagIDs []int64
for _, v := range res.Result {
tagIDs = append(tagIDs, v.TagID)
}
var tagsReply *tagmdl.TagsReply
if tagsReply, err = global.GetTagGRPC().Tags(c, &tagmdl.TagsReq{Tids: tagIDs}); err != nil {
log.Error("tag(%+v) grpc client fail, err=%s", tagIDs, err)
err = nil
}
for _, v := range res.Result {
if tagsReply == nil {
continue
}
if tag, ok := tagsReply.Tags[v.TagID]; ok {
v.TagName = tag.Name
}
}
//log.Info("%s query arg(%d,%+v,%s) res(%+v)", api, signID, date, tp, res.Result[0])
return
}
//GetFansTagCache GetFansTag with cache
func (d *Dao) GetFansTagCache(c context.Context, signID int64, date time.Time, tp string) (res *mcnmodel.McnGetFansTagReply, err error) {
res = new(mcnmodel.McnGetFansTagReply)
var cache = NewCacheMcnDataWithTp(signID, date, tp, res, "McnGetFansTagReply", func(c context.Context, signID int64, date time.Time, tp string) (res interface{}, err error) {
return d.GetFansTag(c, signID, date, tp)
})
if err = d.McWrapper.GetOrLoad(c, cache); err != nil {
log.Error("cache get err, err=%v", err)
return
}
return
}

View File

@@ -0,0 +1,448 @@
package datadao
import (
"context"
"go-common/app/interface/main/mcn/tool/datacenter"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
"go-common/app/interface/main/mcn/model/datamodel"
)
func TestDatadaocallDataAPI(t *testing.T) {
convey.Convey("callDataAPI", t, func(ctx convey.C) {
var (
c = context.Background()
api = APIMcnSummary
query = &datacenter.Query{}
res []*datamodel.DmConMcnArchiveD
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
err := d.callDataAPI(c, api, query, res)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDatadaoGetMcnSummary(t *testing.T) {
convey.Convey("GetMcnSummary", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetMcnSummary(c, signID, date)
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 TestDatadaoGetMcnSummaryCache(t *testing.T) {
convey.Convey("GetMcnSummaryCache", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetMcnSummaryCache(c, signID, date)
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 TestDatadaoGetIndexInc(t *testing.T) {
convey.Convey("GetIndexInc", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
tp = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetIndexInc(c, signID, date, tp)
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 TestDatadaoGetIndexIncCache(t *testing.T) {
convey.Convey("GetIndexIncCache", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
tp = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetIndexIncCache(c, signID, date, tp)
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 TestDatadaoGetIndexSource(t *testing.T) {
convey.Convey("GetIndexSource", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
tp = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetIndexSource(c, signID, date, tp)
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 TestDatadaoGetIndexSourceCache(t *testing.T) {
convey.Convey("GetIndexSourceCache", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
tp = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetIndexSourceCache(c, signID, date, tp)
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 TestDatadaoGetPlaySource(t *testing.T) {
convey.Convey("GetPlaySource", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetPlaySource(c, signID, date)
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 TestDatadaoGetPlaySourceCache(t *testing.T) {
convey.Convey("GetPlaySourceCache", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetPlaySourceCache(c, signID, date)
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 TestDatadaoGetMcnFans(t *testing.T) {
convey.Convey("GetMcnFans", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetMcnFans(c, signID, date)
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 TestDatadaoGetMcnFansCache(t *testing.T) {
convey.Convey("GetMcnFansCache", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetMcnFansCache(c, signID, date)
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 TestDatadaoGetMcnFansInc(t *testing.T) {
convey.Convey("GetMcnFansInc", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetMcnFansInc(c, signID, date)
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 TestDatadaoGetMcnFansIncCache(t *testing.T) {
convey.Convey("GetMcnFansIncCache", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetMcnFansIncCache(c, signID, date)
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 TestDatadaoGetMcnFansDec(t *testing.T) {
convey.Convey("GetMcnFansDec", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetMcnFansDec(c, signID, date)
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 TestDatadaoGetMcnFansDecCache(t *testing.T) {
convey.Convey("GetMcnFansDecCache", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetMcnFansDecCache(c, signID, date)
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 TestDatadaoGetMcnFansAttentionWay(t *testing.T) {
convey.Convey("GetMcnFansAttentionWay", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetMcnFansAttentionWay(c, signID, date)
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 TestDatadaoGetMcnFansAttentionWayCache(t *testing.T) {
convey.Convey("GetMcnFansAttentionWayCache", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetMcnFansAttentionWayCache(c, signID, date)
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 TestDatadaoGetFansBaseFansAttr(t *testing.T) {
convey.Convey("GetFansBaseFansAttr", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
tp = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetFansBaseFansAttr(c, signID, date, tp)
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 TestDatadaoGetFansBaseFansAttrCache(t *testing.T) {
convey.Convey("GetFansBaseFansAttrCache", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
tp = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetFansBaseFansAttrCache(c, signID, date, tp)
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 TestDatadaoGetFansArea(t *testing.T) {
convey.Convey("GetFansArea", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
tp = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetFansArea(c, signID, date, tp)
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 TestDatadaoGetFansAreaCache(t *testing.T) {
convey.Convey("GetFansAreaCache", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
tp = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetFansAreaCache(c, signID, date, tp)
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 TestDatadaoGetFansType(t *testing.T) {
convey.Convey("GetFansType", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
tp = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetFansType(c, signID, date, tp)
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 TestDatadaoGetFansTypeCache(t *testing.T) {
convey.Convey("GetFansTypeCache", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
tp = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetFansTypeCache(c, signID, date, tp)
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 TestDatadaoGetFansTag(t *testing.T) {
convey.Convey("GetFansTag", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
tp = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetFansTag(c, signID, date, tp)
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 TestDatadaoGetFansTagCache(t *testing.T) {
convey.Convey("GetFansTagCache", t, func(ctx convey.C) {
var (
c = context.Background()
signID = int64(0)
date = time.Now()
tp = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetFansTagCache(c, signID, date, tp)
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,143 @@
package datadao
import (
"context"
"encoding/json"
"fmt"
"go-common/app/interface/main/mcn/conf"
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/app/interface/main/mcn/tool/cache"
"time"
)
var (
dateFmt = "20060102"
)
//CacheBaseLoader base loader
type CacheBaseLoader struct {
SignID int64
Date time.Time
Val interface{}
desc string
}
func descHelper(d cache.DataLoader) (key string) {
return d.Desc()
}
func newCacheBaseLoader(signID int64, date time.Time, val interface{}, desc string) CacheBaseLoader {
return CacheBaseLoader{SignID: signID, Date: date, Val: val, desc: desc}
}
//Key cache's key
func (s *CacheBaseLoader) Key() (key string) {
return fmt.Sprintf("%s_%d_%s", descHelper(s), s.SignID, s.Date.Format(dateFmt))
}
//Value cache's value
func (s *CacheBaseLoader) Value() (value interface{}) {
return s.Val
}
//LoadValue need load value
func (s *CacheBaseLoader) LoadValue(c context.Context) (value interface{}, err error) {
panic("implement me")
}
//Expire expiration
func (s *CacheBaseLoader) Expire() time.Duration {
return time.Duration(conf.Conf.Memcache.McnDataCacheExpire)
}
//Desc key desc
func (s *CacheBaseLoader) Desc() string {
return s.desc
}
// -----------------------------------------
//LoadFuncWithTp sign with type
type LoadFuncWithTp func(c context.Context, signID int64, date time.Time, tp string) (res interface{}, err error)
//LoadFuncOnlySign only sign
type LoadFuncOnlySign func(c context.Context, signID int64, date time.Time) (res interface{}, err error)
//NewCacheMcnDataWithTp reply
func NewCacheMcnDataWithTp(signID int64, date time.Time, tp string, val interface{}, desc string, loadFunc LoadFuncWithTp) *cacheMcnDataWithTp {
return &cacheMcnDataWithTp{
CacheBaseLoader: newCacheBaseLoader(signID, date, val, desc),
Tp: tp,
LoadFunc: loadFunc,
}
}
//cacheMcnDataWithTp cache
type cacheMcnDataWithTp struct {
CacheBaseLoader
Tp string
LoadFunc LoadFuncWithTp
}
//Key key
func (s *cacheMcnDataWithTp) Key() (key string) {
return fmt.Sprintf("%s_%d_%s_%s", s.Desc(), s.SignID, s.Date.Format(dateFmt), s.Tp)
}
//LoadValue load
func (s *cacheMcnDataWithTp) LoadValue(c context.Context) (value interface{}, err error) {
value, err = s.LoadFunc(c, s.SignID, s.Date, s.Tp)
if err != nil {
s.Val = nil
return
}
if sorter, ok := value.(mcnmodel.Sorter); ok {
sorter.Sort()
}
// 如果s.Val存在则将结果populate到s.Val上因为外部会直接使用原始传入的s.Val值
if s.Val != nil {
var b, _ = json.Marshal(value)
json.Unmarshal(b, s.Val)
}
return
}
// NewCacheMcnDataSignID 请求只有sign id的情况
func NewCacheMcnDataSignID(signID int64, date time.Time, val interface{}, desc string, loadFunc LoadFuncOnlySign) *cacheMcnDataSignID {
return &cacheMcnDataSignID{
CacheBaseLoader: newCacheBaseLoader(signID, date, val, desc),
LoadFunc: loadFunc,
}
}
type cacheMcnDataSignID struct {
CacheBaseLoader
LoadFunc LoadFuncOnlySign
}
//Key key
func (s *cacheMcnDataSignID) Key() (key string) {
return fmt.Sprintf("%s_%d_%s", s.Desc(), s.SignID, s.Date.Format(dateFmt))
}
//LoadValue load
func (s *cacheMcnDataSignID) LoadValue(c context.Context) (value interface{}, err error) {
value, err = s.LoadFunc(c, s.SignID, s.Date)
if err != nil {
s.Val = nil
return
}
if sorter, ok := value.(mcnmodel.Sorter); ok {
sorter.Sort()
}
// 如果s.Val存在则将结果populate到s.Val上因为外部会直接使用原始传入的s.Val值
if s.Val != nil {
var b, _ = json.Marshal(value)
json.Unmarshal(b, s.Val)
}
return
}

View File

@@ -0,0 +1,203 @@
package datadao
import (
"context"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestDatadaodescHelper(t *testing.T) {
convey.Convey("descHelper", t, func(ctx convey.C) {
var (
d = &CacheBaseLoader{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
key := descHelper(d)
ctx.Convey("Then key should not be nil.", func(ctx convey.C) {
ctx.So(key, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaonewCacheBaseLoader(t *testing.T) {
convey.Convey("newCacheBaseLoader", t, func(ctx convey.C) {
var (
signID = int64(0)
date = time.Now()
val = interface{}(0)
desc = ""
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := newCacheBaseLoader(signID, date, val, desc)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoKeyCacheBaseLoader(t *testing.T) {
var (
c = CacheBaseLoader{}
)
convey.Convey("Key", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
key := c.Key()
ctx.Convey("Then key should not be nil.", func(ctx convey.C) {
ctx.So(key, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoValueCacheBaseLoader(t *testing.T) {
var (
c = CacheBaseLoader{Val: 1}
)
convey.Convey("Value", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
value := c.Value()
ctx.Convey("Then value should not be nil.", func(ctx convey.C) {
ctx.So(value, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoExpireCacheBaseLoader(t *testing.T) {
var (
c = CacheBaseLoader{Val: 1}
)
convey.Convey("Expire", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := c.Expire()
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoDesc(t *testing.T) {
var (
c = CacheBaseLoader{Val: 1}
)
convey.Convey("Desc", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := c.Desc()
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoNewCacheMcnDataWithTp(t *testing.T) {
convey.Convey("NewCacheMcnDataWithTp", t, func(ctx convey.C) {
var (
signID = int64(0)
date = time.Now()
tp = ""
val = interface{}(0)
desc = ""
loadFunc LoadFuncWithTp
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := NewCacheMcnDataWithTp(signID, date, tp, val, desc, loadFunc)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoKeyCacheMcnDataWithTp(t *testing.T) {
var (
s = cacheMcnDataWithTp{CacheBaseLoader: CacheBaseLoader{Val: 1}}
)
convey.Convey("Key", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
key := s.Key()
ctx.Convey("Then key should not be nil.", func(ctx convey.C) {
ctx.So(key, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoLoadValuecacheMcnDataWithTp(t *testing.T) {
convey.Convey("LoadValue", t, func(ctx convey.C) {
var (
c = context.Background()
s = cacheMcnDataWithTp{
CacheBaseLoader: CacheBaseLoader{Val: 1},
LoadFunc: func(c context.Context, signID int64, date time.Time, tp string) (res interface{}, err error) {
return d.GetIndexSource(c, signID, date, tp)
},
}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
value, err := s.LoadValue(c)
ctx.Convey("Then err should be nil.value should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(value, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoNewCacheMcnDataSignID(t *testing.T) {
convey.Convey("NewCacheMcnDataSignID", t, func(ctx convey.C) {
var (
signID = int64(0)
date = time.Now()
val = interface{}(0)
desc = ""
loadFunc LoadFuncOnlySign
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := NewCacheMcnDataSignID(signID, date, val, desc, loadFunc)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoKeycacheMcnDataSignID(t *testing.T) {
var (
s = cacheMcnDataSignID{CacheBaseLoader: CacheBaseLoader{Val: 1}}
)
convey.Convey("Key", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
key := s.Key()
ctx.Convey("Then key should not be nil.", func(ctx convey.C) {
ctx.So(key, convey.ShouldNotBeNil)
})
})
})
}
func TestDatadaoLoadValuecacheMcnDataSignID(t *testing.T) {
convey.Convey("LoadValue", t, func(ctx convey.C) {
var (
c = context.Background()
s = cacheMcnDataSignID{
CacheBaseLoader: CacheBaseLoader{Val: 1},
LoadFunc: func(c context.Context, signID int64, date time.Time) (res interface{}, err error) {
return d.GetMcnFans(c, signID, date)
},
}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
value, err := s.LoadValue(c)
ctx.Convey("Then err should be nil.value should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(value, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,118 @@
package datadao
import (
"context"
"encoding/json"
"fmt"
"net/url"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/metadata"
)
// HTTPDataHandle .
func (d *Dao) HTTPDataHandle(c context.Context, params url.Values, key string) (data interface{}, err error) {
var (
uri string
res struct {
Code int `json:"code"`
Data json.RawMessage `json:"data"`
Message string `json:"message"`
}
)
if uri, err = d.getURI(key); err != nil {
return
}
if err = d.bmClient.Get(c, uri, metadata.String(c, metadata.RemoteIP), params, &res); err != nil {
return
}
if res.Code != 0 {
log.Error("d.bmClient.Get(%s,%d)", uri+"?"+params.Encode(), res.Code)
err = ecode.Error(ecode.Int(res.Code), res.Message)
return
}
data = res.Data
return
}
// getURI .
func (d *Dao) getURI(key string) (uri string, err error) {
var (
ok bool
url struct {
host string
uri string
}
_url = map[string]struct {
host string
uri string
}{
"archives": {
uri: "/x/internal/creative/archives",
host: d.Conf.Host.API,
},
"archiveHistoryList": {
uri: "/x/internal/creative/archive/history/list",
host: d.Conf.Host.API,
},
"archiveVideos": {
uri: "/x/internal/creative/archive/videos",
host: d.Conf.Host.API,
},
"dataArchive": {
uri: "/x/internal/creative/data/archive",
host: d.Conf.Host.API,
},
"dataVideoQuit": {
uri: "/x/internal/creative/data/videoquit",
host: d.Conf.Host.API,
},
"danmuDistri": {
uri: "/x/internal/creative/danmu/distri",
host: d.Conf.Host.API,
},
"dataBase": {
uri: "/x/internal/creative/data/base",
host: d.Conf.Host.API,
},
"dataTrend": {
uri: "/x/internal/creative/data/trend",
host: d.Conf.Host.API,
},
"dataAction": {
uri: "/x/internal/creative/data/action",
host: d.Conf.Host.API,
},
"dataFan": {
uri: "/x/internal/creative/data/fan",
host: d.Conf.Host.API,
},
"dataPandect": {
uri: "/x/internal/creative/data/pandect",
host: d.Conf.Host.API,
},
"dataSurvey": {
uri: "/x/internal/creative/data/survey",
host: d.Conf.Host.API,
},
"dataPlaySource": {
uri: "/x/internal/creative/data/playsource",
host: d.Conf.Host.API,
},
"dataPlayAnalysis": {
uri: "/x/internal/creative/data/playanalysis",
host: d.Conf.Host.API,
},
"dataArticleRank": {
uri: "/x/internal/creative/data/article/rank",
host: d.Conf.Host.API,
},
}
)
if url, ok = _url[key]; !ok {
return uri, fmt.Errorf("url(%s) not exist", key)
}
uri = url.host + url.uri
return uri, err
}

View File

@@ -0,0 +1,56 @@
package datadao
import (
"context"
"encoding/json"
"github.com/bouk/monkey"
"go-common/library/net/http/blademaster"
"net/url"
"reflect"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDatadaoHTTPDataHandle(t *testing.T) {
var (
c = context.Background()
params url.Values
key = "archives"
)
convey.Convey("HTTPDataHandle", t, func(ctx convey.C) {
type result struct {
Code int `json:"code"`
Data json.RawMessage `json:"data"`
Message string `json:"message"`
}
res := new(result)
guard := monkey.PatchInstanceMethod(reflect.TypeOf(d.bmClient), "Get", func(_ *blademaster.Client, _ context.Context, _, _ string, _ url.Values, _ interface{}) error {
res.Code = 0
res.Data = json.RawMessage("play")
res.Message = "success"
return nil
})
defer guard.Unpatch()
_, err := d.HTTPDataHandle(c, params, key)
ctx.Convey("Then err should be nil.data should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
}
func TestDatadaogetURI(t *testing.T) {
convey.Convey("getURI", t, func(ctx convey.C) {
var (
key = "archives"
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
uri, err := d.getURI(key)
ctx.Convey("Then err should be nil.uri should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(uri, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,30 @@
package datadao
import (
"go-common/app/interface/main/mcn/conf"
"go-common/app/interface/main/mcn/dao/global"
"go-common/app/interface/main/mcn/tool/cache"
"go-common/app/interface/main/mcn/tool/datacenter"
"go-common/library/cache/memcache"
bm "go-common/library/net/http/blademaster"
)
//Dao data dao
type Dao struct {
Client *datacenter.HttpClient
Conf *conf.Config
mc *memcache.Pool
McWrapper *cache.MCWrapper
bmClient *bm.Client
}
//New .
func New(c *conf.Config) *Dao {
return &Dao{
Client: datacenter.New(c.DataClientConf),
Conf: c,
mc: global.GetMc(),
McWrapper: cache.New(global.GetMc()),
bmClient: global.GetBMClient(),
}
}

View File

@@ -0,0 +1,60 @@
package datadao
import (
"flag"
"net/http"
"os"
"testing"
"go-common/app/interface/main/mcn/conf"
"go-common/app/interface/main/mcn/dao/global"
"gopkg.in/h2non/gock.v1"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.mcn-interface")
flag.Set("conf_token", "49e4671bafbf93059aeb602685052ca0")
flag.Set("tree_id", "58909")
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/mcn-interface.toml")
}
if os.Getenv("UT_LOCAL_TEST") != "" {
flag.Set("conf", "../../cmd/mcn-interface.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
global.Init(conf.Conf)
d = New(conf.Conf)
d.Client.SetTransport(gock.DefaultTransport)
var result = `{
"code": 200,
"msg": "success",
"result": [ ]
}`
gock.New("http://berserker.bilibili.co/avenger/api").Get("/").AddMatcher(
func(request *http.Request, request2 *gock.Request) (bool, error) {
return true, nil
}).Persist().Reply(200).JSON(result)
defer gock.OffAll()
os.Exit(m.Run())
}
// func httpMock(method, url string) *gock.Request {
// r := gock.New(url)
// r.Method = strings.ToUpper(method)
// return r
// }

View File

@@ -0,0 +1,58 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"account.go",
"resource.go",
],
importpath = "go-common/app/interface/main/mcn/dao/global",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/mcn/conf:go_default_library",
"//app/interface/main/tag/api:go_default_library",
"//app/service/main/account/api:go_default_library",
"//app/service/main/account/model:go_default_library",
"//app/service/main/archive/api:go_default_library",
"//app/service/main/member/api:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = [
"account_test.go",
"resource_test.go",
],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//app/interface/main/mcn/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,49 @@
package global
import (
"context"
accgrpc "go-common/app/service/main/account/api"
accmdl "go-common/app/service/main/account/model"
"go-common/library/log"
)
//GetInfo get info
func GetInfo(c context.Context, mid int64) (res *accmdl.Info, err error) {
if mid == 0 {
return
}
var infoReply *accgrpc.InfoReply
if infoReply, err = accGRPC.Info3(c, &accgrpc.MidReq{Mid: mid}); err != nil {
return
}
res = infoReply.Info
return
}
//GetInfos get many infos
func GetInfos(c context.Context, mids []int64) (res map[int64]*accmdl.Info, err error) {
if len(mids) == 0 {
return
}
var infosReply *accgrpc.InfosReply
if infosReply, err = accGRPC.Infos3(c, &accgrpc.MidsReq{Mids: mids}); err != nil {
return
}
res = infosReply.Infos
return
}
//GetName get user name
func GetName(c context.Context, mid int64) (nickname string) {
accInfos, e := GetInfos(c, []int64{mid})
if e == nil && accInfos != nil {
var info, ok = accInfos[mid]
if ok {
nickname = info.Name
}
} else {
log.Warn("get up info fail, err=%s", e)
}
return
}

View File

@@ -0,0 +1,55 @@
package global
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestGlobalGetInfo(t *testing.T) {
convey.Convey("GetInfo", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(417851)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := GetInfo(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 TestGlobalGetInfos(t *testing.T) {
convey.Convey("GetInfos", t, func(ctx convey.C) {
var (
c = context.Background()
mid = []int64{417851}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := GetInfos(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 TestGlobalGetName(t *testing.T) {
convey.Convey("GetName", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
nickname := GetName(c, mid)
ctx.Convey("Then nickname should not be nil.", func(ctx convey.C) {
ctx.So(nickname, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,74 @@
package global
import (
"go-common/app/interface/main/mcn/conf"
taggrpc "go-common/app/interface/main/tag/api"
accgrpc "go-common/app/service/main/account/api"
arcgrpc "go-common/app/service/main/archive/api"
memgrpc "go-common/app/service/main/member/api"
"go-common/library/cache/memcache"
bm "go-common/library/net/http/blademaster"
"github.com/pkg/errors"
)
var (
accGRPC accgrpc.AccountClient
memGRPC memgrpc.MemberClient
arcGRPC arcgrpc.ArchiveClient
tagGRPC taggrpc.TagRPCClient
mc *memcache.Pool
bmClient *bm.Client
)
// GetAccGRPC .
func GetAccGRPC() accgrpc.AccountClient {
return accGRPC
}
// GetMemGRPC .
func GetMemGRPC() memgrpc.MemberClient {
return memGRPC
}
// GetArcGRPC .
func GetArcGRPC() arcgrpc.ArchiveClient {
return arcGRPC
}
// GetTagGRPC .
func GetTagGRPC() taggrpc.TagRPCClient {
return tagGRPC
}
// GetMc get mc
func GetMc() *memcache.Pool {
return mc
}
// GetBMClient get http client
func GetBMClient() *bm.Client {
return bmClient
}
//Init init global
func Init(c *conf.Config) {
var err error
if accGRPC, err = accgrpc.NewClient(c.GRPCClient.Account); err != nil {
panic(errors.WithMessage(err, "Failed to dial account service"))
}
if memGRPC, err = memgrpc.NewClient(c.GRPCClient.Member); err != nil {
panic(errors.WithMessage(err, "Failed to dial member service"))
}
if arcGRPC, err = arcgrpc.NewClient(c.GRPCClient.Archive); err != nil {
panic(errors.WithMessage(err, "Failed to dial archive service"))
}
if tagGRPC, err = taggrpc.NewClient(c.GRPCClient.Tag); err != nil {
panic(errors.WithMessage(err, "Failed to dial tag service"))
}
mc = memcache.NewPool(&c.Memcache.Config)
bmClient = bm.NewClient(c.HTTPClient)
}

View File

@@ -0,0 +1,69 @@
package global
import (
"flag"
"os"
"testing"
"go-common/app/interface/main/mcn/conf"
"github.com/smartystreets/goconvey/convey"
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.mcn-interface")
flag.Set("conf_token", "49e4671bafbf93059aeb602685052ca0")
flag.Set("tree_id", "58909")
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/mcn-interface.toml")
}
if os.Getenv("UT_LOCAL_TEST") != "" {
flag.Set("conf", "../../cmd/mcn-interface.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
Init(conf.Conf)
os.Exit(m.Run())
}
func TestGlobalGetAccGRPC(t *testing.T) {
convey.Convey("GetAccGRPC", t, func(ctx convey.C) {
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := GetAccGRPC()
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestGlobalGetMemGRPC(t *testing.T) {
convey.Convey("GetMemGRPC", t, func(ctx convey.C) {
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := GetMemGRPC()
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestGlobalGetArcGRPC(t *testing.T) {
convey.Convey("GetArcGRPC", t, func(ctx convey.C) {
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := GetArcGRPC()
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,354 @@
-- mcn签约表
drop table if exists mcn_sign;
create table mcn_sign (
id int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
mcn_mid int(11) unsigned NOT NULL DEFAULT 0 COMMENT 'mcn的mid',
company_name varchar(32) NOT NULL DEFAULT '' COMMENT '企业名称',
company_license_id varchar(32) NOT NULL DEFAULT '' COMMENT '营业执照注册号',
company_license_link varchar(255) NOT NULL DEFAULT '' COMMENT '营业执照链接',
contract_link varchar(255) NOT NULL DEFAULT '' COMMENT '合同链接',
contact_name varchar(16) NOT NULL DEFAULT '' COMMENT '对接人姓名',
contact_title varchar(16) NOT NULL DEFAULT '' COMMENT '对接人职务',
contact_idcard varchar(32) NOT NULL DEFAULT '' COMMENT '对接人身份证号',
contact_phone varchar(16) NOT NULL DEFAULT '' COMMENT '对接人手机号',
begin_date date NOT NULL DEFAULT '0000-00-00' COMMENT '合同开始时间',
end_date date NOT NULL DEFAULT '0000-00-00' COMMENT '合同结束时间',
reject_reason varchar(255) NOT NULL DEFAULT '' COMMENT '驳回理由',
`reject_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '驳回时间',
`pay_expire_state` tinyint(4) NOT NULL DEFAULT '1' COMMENT '付款到期状态:1:未到期 2:即将到期',
state tinyint(4) NOT NULL DEFAULT 0 COMMENT '状态,0未申请1待审核2已驳回10已签约11冷却中12已到期13封禁14清退, 15待开启100移除',
ctime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '添加时间',
mtime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
KEY `ix_mcn_mid` (`mcn_mid`),
KEY `ix_mtime` (`mtime`),
KEY `ix_state` (`state`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='mcn签约表';
-- mcn付款表
drop table if exists mcn_sign_pay;
CREATE TABLE mcn_sign_pay (
id int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
mcn_mid int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn mid',
sign_id int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn签约ID',
due_date date NOT NULL DEFAULT '0000-00-00' COMMENT '付款时间',
pay_value BIGINT(20) NOT NULL DEFAULT '0' COMMENT '金额',
state tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态0未支付1已支付100删除',
note varchar(255) NOT NULL DEFAULT '' COMMENT '备注',
ctime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
mtime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (id),
KEY ix_signid (sign_id),
KEY ix_mcn_mid (mcn_mid),
KEY ix_generate_date (due_date),
KEY ix_mtime (mtime)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='付款表';
-- mcn up绑定表
drop table if exists mcn_up;
CREATE TABLE mcn_up (
id int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
sign_id int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn签约ID',
mcn_mid int(11) unsigned NOT NULL DEFAULT 0 COMMENT 'mcn的mid',
up_mid int(11) unsigned NOT NULL DEFAULT 0 COMMENT '绑定up的mid',
begin_date date NOT NULL DEFAULT '0000-00-00' COMMENT '合同开始时间',
end_date date NOT NULL DEFAULT '0000-00-00' COMMENT '合同结束时间',
contract_link varchar(255) NOT NULL DEFAULT '' COMMENT '与up合同链接',
up_auth_link varchar(255) NOT NULL DEFAULT '' COMMENT 'up授权协议链接',
reject_reason varchar(255) NOT NULL DEFAULT '' COMMENT '驳回理由',
reject_time timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '驳回时间',
state tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态0未授权1已拒绝2审核中3已驳回10已签约11已冻结12已到期13封禁14已解约100删除',
state_change_time timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '状态变化时间',
ctime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
mtime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (id),
UNIQUE KEY uk_sign_id_mcn_mid_up_mid (sign_id, mcn_mid, up_mid),
KEY ix_up_mid(up_mid),
KEY ix_mtime (mtime)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='mcn绑定up表';
-- 数据相关表
-- 1。mcn整体数据表
-- 2。mcn下各up主数据表
-- 3。Top稿件表
-- 1。mcn整体数据表
drop table if exists mcn_data_summary;
create table mcn_data_summary (
id int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
mcn_mid int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn mid',
sign_id int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn签约ID',
up_count int(11) unsigned NOT NULL DEFAULT '0' COMMENT '签约UP主数',
fans_count_accumulate int(11) unsigned NOT NULL DEFAULT '0' COMMENT '累计粉丝量',
fans_count_online int(11) unsigned NOT NULL DEFAULT '0' COMMENT '线上涨粉量',
fans_count_real int(11) unsigned NOT NULL DEFAULT '0' COMMENT '实际涨粉量',
fans_count_cheat_accumulate int(11) unsigned NOT NULL DEFAULT '0' COMMENT '累计作弊粉丝',
fans_count_increase_day int(11) unsigned NOT NULL DEFAULT '0' COMMENT '当日新增粉丝数',
play_count_accumulate int(11) unsigned NOT NULL DEFAULT '0' COMMENT '累计播放数',
play_count_increase_day int(11) unsigned NOT NULL DEFAULT '0' COMMENT '当日新增播放数',
archive_count_accumulate int(11) unsigned NOT NULL DEFAULT '0' COMMENT '累计投稿量',
active_tid smallint(6) unsigned NOT NULL DEFAULT '0' COMMENT '分区,表示某个分区',
generate_date date NOT NULL DEFAULT '0000-00-00' COMMENT '计算日',
data_type tinyint(4) NOT NULL DEFAULT '0' COMMENT '数据类型1按天2按月',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_sign_id_generate_date_active_tid_data_type` (sign_id, generate_date, active_tid, data_type),
KEY ix_mcn_mid (mcn_mid),
KEY `ix_mtime` (`mtime`),
KEY `ix_generate_date` (`generate_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='mcn整体数据';
drop table if exists mcn_data_up_detail;
create table mcn_data_up_detail (
id int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
mcn_mid int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn mid',
sign_id int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn签约ID',
up_mid int(11) unsigned NOT NULL DEFAULT '0' COMMENT '签约UP主ID',
fans_count_accumulate int(11) unsigned NOT NULL DEFAULT '0' COMMENT '累计粉丝量',
fans_count_online int(11) unsigned NOT NULL DEFAULT '0' COMMENT '线上涨粉量',
fans_count_real int(11) unsigned NOT NULL DEFAULT '0' COMMENT '实际涨粉量',
fans_count_cheat_accumulate int(11) unsigned NOT NULL DEFAULT '0' COMMENT '累计作弊粉丝',
fans_count_increase_day int(11) unsigned NOT NULL DEFAULT '0' COMMENT '当日新增粉丝数',
play_count_accumulate int(11) unsigned NOT NULL DEFAULT '0' COMMENT '累计播放数',
play_count_increase_day int(11) unsigned NOT NULL DEFAULT '0' COMMENT '当日新增播放数',
archive_count_accumulate int(11) unsigned NOT NULL DEFAULT '0' COMMENT '累计投稿量',
active_tid smallint(6) unsigned NOT NULL DEFAULT '0' COMMENT 'Up所属分区',
generate_date date NOT NULL DEFAULT '0000-00-00' COMMENT '计算日',
data_type tinyint(4) NOT NULL DEFAULT '0' COMMENT '数据类型1按天2按月',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_sign_id_generate_date_data_type_up_mid` (sign_id, generate_date, data_type, up_mid),
KEY ix_mcn_mid (mcn_mid),
KEY `ix_mtime` (`mtime`),
KEY `ix_generate_date` (`generate_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='mcn up整体数据';
-- 2。mcn下各up主数据表
drop table if exists mcn_data_up;
create table mcn_data_up (
id int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
mcn_mid int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn mid',
sign_id int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn签约ID',
up_mid int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'up的mid',
data_type tinyint(4) NOT NULL DEFAULT '0' COMMENT '数据类型1累计2昨日3上周4上月',
fans_increase_accumulate int(11) unsigned NOT NULL default '0' COMMENT '粉丝数增涨量',
archive_count int(11) unsigned NOT NULL default '0' COMMENT '投搞量',
play_count int(11) unsigned NOT NULL default '0' COMMENT '播放量',
fans_increase_month int(11) unsigned NOT NULL default '0' COMMENT '近一个月涨粉量',
fans_count int(11) unsigned NOT NULL DEFAULT '0' COMMENT '粉丝总量',
fans_count_active int(11) unsigned NOT NULL DEFAULT '0' COMMENT '活跃粉丝总量',
generate_date date NOT NULL DEFAULT '0000-00-00' COMMENT '计算日',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_sign_id_generate_date_data_type` (sign_id, generate_date, data_type),
KEY ix_mcn_mid (mcn_mid),
KEY ix_up_mid (up_mid),
KEY `ix_mtime` (`mtime`),
KEY `ix_generate_date` (`generate_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='mcn下up数据';
-- alter table mcn_up_test add column state_change_time timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '状态变化时间';
-- 增加字段, fat 1, uat 1, prod 1
alter table mcn_data_summary add column fans_count_real_accumulate bigint(20) NOT NULL DEFAULT '0' COMMENT '累计实际涨粉量';
alter table mcn_data_summary add column fans_count_online_accumulate bigint(20) NOT NULL DEFAULT '0' COMMENT '累计线上涨粉量';
alter table mcn_data_summary add column archive_count_day int(11) NOT NULL DEFAULT '0' COMMENT '当日新增投稿量';
alter table mcn_data_up_detail add column fans_count_real_accumulate bigint(20) NOT NULL DEFAULT '0' COMMENT '累计实际涨粉量';
alter table mcn_data_up_detail add column fans_count_online_accumulate bigint(20) NOT NULL DEFAULT '0' COMMENT '累计线上涨粉量';
alter table mcn_data_up_detail add column archive_count_day int(11) NOT NULL DEFAULT '0' COMMENT '当日新增投稿量';
-- 修改数据字段类型去掉unsigned 修改播放相关的为bigint, fat 1, uat 1, prod 1
alter table mcn_data_summary modify column fans_count_accumulate int(11) NOT NULL DEFAULT '0' COMMENT '累计粉丝量';
alter table mcn_data_summary modify column fans_count_online int(11) NOT NULL DEFAULT '0' COMMENT '线上涨粉量';
alter table mcn_data_summary modify column fans_count_real int(11) NOT NULL DEFAULT '0' COMMENT '实际涨粉量';
alter table mcn_data_summary modify column fans_count_cheat_accumulate int(11) NOT NULL DEFAULT '0' COMMENT '累计作弊粉丝';
alter table mcn_data_summary modify column fans_count_increase_day int(11) NOT NULL DEFAULT '0' COMMENT '当日新增粉丝数';
alter table mcn_data_summary modify column play_count_accumulate int(11) NOT NULL DEFAULT '0' COMMENT '累计播放数';
alter table mcn_data_summary modify column play_count_increase_day int(11) NOT NULL DEFAULT '0' COMMENT '当日新增播放数';
alter table mcn_data_summary modify column archive_count_accumulate int(11) NOT NULL DEFAULT '0' COMMENT '累计投稿量';
alter table mcn_data_up_detail modify column fans_count_accumulate int(11) NOT NULL DEFAULT '0' COMMENT '累计粉丝量';
alter table mcn_data_up_detail modify column fans_count_online int(11) NOT NULL DEFAULT '0' COMMENT '线上涨粉量';
alter table mcn_data_up_detail modify column fans_count_real int(11) NOT NULL DEFAULT '0' COMMENT '实际涨粉量';
alter table mcn_data_up_detail modify column fans_count_cheat_accumulate int(11) NOT NULL DEFAULT '0' COMMENT '累计作弊粉丝';
alter table mcn_data_up_detail modify column fans_count_increase_day int(11) NOT NULL DEFAULT '0' COMMENT '当日新增粉丝数';
alter table mcn_data_up_detail modify column play_count_accumulate int(11) NOT NULL DEFAULT '0' COMMENT '累计播放数';
alter table mcn_data_up_detail modify column play_count_increase_day int(11) NOT NULL DEFAULT '0' COMMENT '当日新增播放数';
alter table mcn_data_up_detail modify column archive_count_accumulate int(11) NOT NULL DEFAULT '0' COMMENT '累计投稿量';
alter table mcn_data_up modify column fans_increase_accumulate int(11) NOT NULL default '0' COMMENT '粉丝数增涨量';
alter table mcn_data_up modify column archive_count int(11) NOT NULL default '0' COMMENT '投搞量';
alter table mcn_data_up modify column play_count bigint(20) NOT NULL default '0' COMMENT '播放量';
alter table mcn_data_up modify column fans_increase_month int(11) NOT NULL default '0' COMMENT '近一个月涨粉量';
alter table mcn_data_up modify column fans_count int(11) NOT NULL DEFAULT '0' COMMENT '粉丝总量';
alter table mcn_data_up modify column fans_count_active int(11) NOT NULL DEFAULT '0' COMMENT '活跃粉丝总量';
-- fat 1, uat 1, prod 1
alter table mcn_data_summary modify column play_count_accumulate bigint(20) NOT NULL DEFAULT '0' COMMENT '累计播放数';
alter table mcn_data_summary modify column play_count_increase_day bigint(20) NOT NULL DEFAULT '0' COMMENT '当日/月新增播放数';
alter table mcn_data_up_detail modify column play_count_accumulate bigint(20) NOT NULL DEFAULT '0' COMMENT '累计播放数';
alter table mcn_data_up_detail modify column play_count_increase_day bigint(20) NOT NULL DEFAULT '0' COMMENT '当日/月新增播放数';
alter table mcn_sign modify column reject_time datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '驳回时间';
-- fat 1, uat 1, prod 1, 增加时间上的索引
create index ix_end_date on mcn_sign (end_date);
create index ix_begin_date on mcn_sign (begin_date);
create index ix_end_date on mcn_up (end_date);
create index ix_begin_date on mcn_up (begin_date);
--------- 2期
-- fat 1, uat 1, prod 1, 增加表
alter table mcn_up add column up_type tinyint(4) not null default '0' comment '用户类型0为站内1为站外';
alter table mcn_up add column site_link varchar(255) not null default '' comment 'up主站外账号链接';
-- mcn_data_import_up: table
CREATE TABLE `mcn_data_import_up` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
`mcn_mid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn mid',
`sign_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn签约ID',
`up_mid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'UP主 mid',
`standard_fans_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '达标粉丝数类型, 1: 1w粉丝',
`standard_fans_date` int(11) NOT NULL DEFAULT '0' COMMENT '达到粉丝数门槛花费的时间,秒',
`standard_archive_count` int(11) NOT NULL DEFAULT '0' COMMENT '达标时投稿量',
`standard_fans_count` int(11) NOT NULL DEFAULT '0' COMMENT '达标时粉丝数',
`is_reward` int(11) NOT NULL DEFAULT '0' COMMENT '奖励情况 0:未奖励 1:已奖励',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_sign_id_mid_type` (`sign_id`,`up_mid`,`standard_fans_type`),
KEY `ix_mtime` (`mtime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='引入账号数据表';
-- mcn_up_recommend_pool: table
CREATE TABLE `mcn_up_recommend_pool` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
`up_mid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'up mid',
`fans_count` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '粉丝量',
`fans_count_increase_month` int(11) NOT NULL DEFAULT '0' COMMENT '本月粉丝增长量',
`archive_count` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '总稿件数',
`play_count_accumulate` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '累积播放量',
`play_count_average` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '稿均播放量',
`active_tid` smallint(6) unsigned NOT NULL DEFAULT '0' COMMENT '分区,表示某个分区',
`last_archive_time` datetime NOT NULL DEFAULT '1970-01-01 08:00:00' COMMENT '最近投稿时间',
`state` tinyint(4) unsigned NOT NULL DEFAULT '1' COMMENT '推荐池状态: 1:未推荐 2:推荐 3:禁止推荐 100:移除',
`source` tinyint(4) unsigned NOT NULL DEFAULT '1' COMMENT '推荐池来源: 1:自动添加(大数据) 2:手动添加',
`generate_time` datetime NOT NULL DEFAULT '1970-01-01 08:00:00' COMMENT '大数据更新时间',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_up_mid` (`up_mid`),
KEY `ix_state` (`state`),
KEY `ix_active_tid` (`active_tid`),
KEY `ix_fans_count` (`fans_count`),
KEY `ix_play_count_accumulate` (`play_count_accumulate`),
KEY `ix_play_count_average` (`play_count_average`),
KEY `ix_fans_count_increase_month` (`fans_count_increase_month`),
KEY `ix_source` (`source`),
KEY `ix_generate_time` (`generate_time`),
KEY `ix_mtime` (`mtime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='mcn-up主推荐池';
-- mcn_up_recommend_source: table
CREATE TABLE `mcn_up_recommend_source` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
`up_mid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'up mid',
`fans_count` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '粉丝量',
`fans_count_increase_month` int(11) NOT NULL DEFAULT '0' COMMENT '本月粉丝增长量',
`archive_count` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '总稿件数',
`play_count_accumulate` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '累积播放量',
`play_count_average` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '稿均播放量',
`active_tid` smallint(6) unsigned NOT NULL DEFAULT '0' COMMENT '分区,表示某个分区',
`last_archive_time` datetime NOT NULL DEFAULT '1970-01-01 08:00:00' COMMENT '最近投稿时间',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`id`),
KEY `ix_up_mid` (`up_mid`),
KEY `ix_mtime` (`mtime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='mcn-up主推荐池的来源(大数据提供)';
-- fat 1, uat 1, prod 0
-- 1。涨粉量排名
create table mcn_rank_up_fans (
id int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
mcn_mid int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn mid',
sign_id int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn签约ID',
up_mid int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'up的mid',
value1 int(11) NOT NULL default '0' COMMENT '数据1',
value2 int(11) NOT NULL default '0' COMMENT '数据2',
active_tid smallint(6) unsigned NOT NULL DEFAULT '0' COMMENT '分区,表示某个分区',
data_type tinyint(4) NOT NULL DEFAULT '0' COMMENT '数据类型1累计总榜2昨日3上周4上月5活跃粉丝(累计)',
generate_date date NOT NULL DEFAULT '0000-00-00' COMMENT '计算日',
ctime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
mtime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_sign_id_generate_date_data_type_up_mid` (sign_id, generate_date, data_type, up_mid),
KEY ix_mcn_mid (mcn_mid),
KEY ix_up_mid (up_mid),
KEY `ix_mtime` (`mtime`),
KEY `ix_generate_date` (`generate_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='mcn下up涨粉量排名';
-- 2。Top稿件表
create table mcn_rank_archive_likes (
id int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
mcn_mid int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn mid',
sign_id int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn签约ID',
up_mid int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'up的mid',
archive_id bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '稿件id',
like_count bigint(20) NOT NULL DEFAULT '0' COMMENT '日/周/月新增点赞数根据data_type统计',
data_type tinyint(4) NOT NULL DEFAULT '0' COMMENT '数据类型1累计2昨日3上周4上月',
tid smallint(6) unsigned NOT NULL DEFAULT '0' COMMENT '分区ID',
generate_date date NOT NULL DEFAULT '0000-00-00' COMMENT '计算日',
ctime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
mtime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`id`),
KEY ix_mcn_mid (mcn_mid),
KEY `ix_mtime` (`mtime`),
KEY `ix_generate_date` (`generate_date`),
UNIQUE KEY `uk_sign_id_generate_date_data_type_archive_id` (sign_id, generate_date, data_type, archive_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='mcn下top稿件表';
-- mcn_data_up_cheat: table
CREATE TABLE `mcn_data_up_cheat` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`mcn_mid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn mid',
`sign_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'mcn签约ID',
`up_mid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'up主 mid',
`generate_date` date NOT NULL DEFAULT '0000-00-00' COMMENT '计算日',
`fans_count_cheat_increase_day` int(11) NOT NULL DEFAULT '0' COMMENT '新增作弊粉丝量',
`fans_count_cheat_cleaned_accumulate` int(11) NOT NULL DEFAULT '0' COMMENT '已清除粉丝量',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_up_mid_sign_id_generate_date` (`up_mid`,`sign_id`,`generate_date`),
KEY `ix_mcn_mid` (`mcn_mid`),
KEY `ix_mtime` (`mtime`),
KEY `ix_generate_date` (`generate_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='作弊筛选详情表'
;
-- fat 1, uat 1, prod 0
ALTER TABLE mcn_rank_archive_likes CHANGE archive_id avid bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '稿件id';
ALTER TABLE `bilibili_upcrm`.`mcn_data_up_cheat`
ADD COLUMN `fans_count_cheat_accumulate` int(11) NOT NULL DEFAULT '0' COMMENT '累计作弊粉丝',
ADD COLUMN `fans_count_accumulate` int(11) NOT NULL DEFAULT '0' COMMENT '实际粉丝量';
-- fat 1, uat 1, prod 0
ALTER TABLE mcn_up ADD COLUMN confirm_time timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'up确认时间';
---------------
alter table mcn_sign add permission int(11) unsigned default '1' not null comment '权限列表-属性位';
alter table mcn_up
add permission int(11) unsigned default '1' not null comment '权限列表-属性位',
add publication_price bigint default '0' not null comment '刊例价(千分位*1000)';

View File

@@ -0,0 +1,254 @@
#投稿数及昨日增量
CREATE TABLE `dm_con_mcn_archive_d` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`up_all` int(11) NOT NULL DEFAULT '0' COMMENT '绑定up主数',
`archive_all` bigint(20) NOT NULL DEFAULT '0' COMMENT '总投稿数',
`archive_inc` bigint(20) NOT NULL DEFAULT '0' COMMENT '投稿数昨日增量',
`play_all` bigint(20) NOT NULL DEFAULT '0' COMMENT '总播放数',
`play_inc` bigint(20) NOT NULL DEFAULT '0' COMMENT '播放数昨日增量',
`danmu_all` bigint(20) NOT NULL DEFAULT '0' COMMENT '总弹幕数',
`danmu_inc` bigint(20) NOT NULL DEFAULT '0' COMMENT '弹幕数昨日增量',
`reply_all` bigint(20) NOT NULL DEFAULT '0' COMMENT '总评论数',
`reply_inc` bigint(20) NOT NULL DEFAULT '0' COMMENT '评论数昨日增量',
`share_all` bigint(20) NOT NULL DEFAULT '0' COMMENT '总分享数',
`share_inc` bigint(20) NOT NULL DEFAULT '0' COMMENT '分享数昨日增量',
`coin_all` bigint(20) NOT NULL DEFAULT '0' COMMENT '总硬币数',
`coin_inc` bigint(20) NOT NULL DEFAULT '0' COMMENT '硬币数昨日增量',
`fav_all` bigint(20) NOT NULL DEFAULT '0' COMMENT '总收藏数',
`fav_inc` bigint(20) NOT NULL DEFAULT '0' COMMENT '收藏数昨日增量',
`like_all` bigint(20) NOT NULL DEFAULT '0' COMMENT '总点赞数',
`like_inc` bigint(20) NOT NULL DEFAULT '0' COMMENT '点赞数昨日增量',
`fans_all` bigint(20) NOT NULL DEFAULT '0' COMMENT '总粉丝数',
`fans_inc` bigint(20) NOT NULL DEFAULT '0' COMMENT '昨日粉丝增量',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='mcn稿件汇总指标';
#播放/弹幕/评论/分享/硬币/收藏/点赞数每日增量
CREATE TABLE `dm_con_mcn_index_inc_d` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`value` bigint(20) NOT NULL DEFAULT '0' COMMENT '当日播放/弹幕/评论/分享/硬币/收藏/点赞数',
`type` varchar(20) NOT NULL COMMENT '分区类型play、danmu、reply、share、coin、fav、like',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`,`type`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='播放/弹幕/评论/分享/硬币/收藏/点赞数每日增量';
#mcn播放/弹幕/评论/分享/硬币/收藏/点赞来源分区
CREATE TABLE `dm_con_mcn_index_source_d` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`type_id` int(11) NOT NULL COMMENT '一级分区ID',
`rank` int(11) NOT NULL COMMENT '排名',
`value` bigint(20) NOT NULL DEFAULT '0' COMMENT '一级分区',
`type` varchar(20) NOT NULL COMMENT '分区类型play、danmu、reply、share、coin、fav、like',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`,`type_id`,`type`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='mcn播放/弹幕/评论/分享/硬币/收藏/点赞来源分区';
#mcn稿件播放来源占比
CREATE TABLE `dm_con_mcn_play_source_d` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`iphone` bigint(20) NOT NULL COMMENT 'iphone播放量',
`andriod` bigint(20) NOT NULL COMMENT 'andriod播放量',
`pc` bigint(20) NOT NULL COMMENT 'pc播放量',
`h5` bigint(20) NOT NULL COMMENT 'h5播放量',
`other` bigint(20) NOT NULL COMMENT 'other播放量',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='mcn稿件播放来源占比';
#游客/粉丝性别占比
CREATE TABLE `dm_con_mcn_fans_sex_w` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`male` bigint(20) NOT NULL COMMENT '男性人数',
`female` bigint(20) NOT NULL COMMENT '女性人数',
`type` varchar(20) NOT NULL COMMENT '粉丝类型guest、fans',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`,`type`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='游客/粉丝性别占比';
#游客/粉丝年龄分布
CREATE TABLE `dm_con_mcn_fans_age_w` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`a` bigint(20) NOT NULL COMMENT '0-16岁人数',
`b` bigint(20) NOT NULL COMMENT '16-25岁人数',
`c` bigint(20) NOT NULL COMMENT '25-40岁人数',
`d` bigint(20) NOT NULL COMMENT '40岁以上人数',
`type` varchar(20) NOT NULL COMMENT '粉丝类型guest、fans',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`,`type`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='游客/粉丝年龄分布';
#游客/粉丝观看途径
CREATE TABLE `dm_con_mcn_fans_play_way_w` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`app` bigint(20) NOT NULL COMMENT 'app观看人数',
`pc` bigint(20) NOT NULL COMMENT 'pc观看人数',
`outside` bigint(20) NOT NULL COMMENT '站外观看人数',
`other` bigint(20) NOT NULL COMMENT '其他观看人数',
`type` varchar(20) NOT NULL COMMENT '粉丝类型guest、fans',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`,`type`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='游客/粉丝观看途径';
#游客/粉丝地区分布
CREATE TABLE `dm_con_mcn_fans_area_w` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`province` varchar(200) NOT NULL COMMENT '省份',
`user` bigint(20) NOT NULL COMMENT '人数',
`type` varchar(20) NOT NULL COMMENT '粉丝类型guest、fans',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`,`province`,`type`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='游客/粉丝地区分布';
#游客/粉丝倾向分布
CREATE TABLE `dm_con_mcn_fans_type_w` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`type_id` int(11) NOT NULL COMMENT '二级分区ID',
`user` bigint(20) NOT NULL COMMENT '人数',
`type` varchar(20) NOT NULL COMMENT '粉丝类型guest、fans',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`,`type_id`,`type`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='游客/粉丝倾向分布';
#游客/粉丝标签地图分布
CREATE TABLE `dm_con_mcn_fans_tag_w` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`tag_id` int(11) NOT NULL COMMENT '标签ID',
`user` bigint(20) NOT NULL COMMENT '人数',
`type` varchar(20) NOT NULL COMMENT '粉丝类型guest、fans',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`,`tag_id`,`type`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='游客/粉丝标签地图分布';
#mcn粉丝数相关
CREATE TABLE `dm_con_mcn_fans_d` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`fans_all` bigint(20) NOT NULL COMMENT 'mcn总粉丝数',
`fans_inc` bigint(20) NOT NULL COMMENT 'mcn粉丝数昨日增量',
`act_fans` bigint(20) NOT NULL COMMENT 'mcn活跃粉丝数',
`fans_dec_all` bigint(20) NOT NULL COMMENT 'mcn取关粉丝总数',
`fans_dec` bigint(20) NOT NULL COMMENT 'mcn昨日取关粉丝数',
`view_fans_rate` float(3,2) NOT NULL COMMENT '观看活跃度',
`act_fans_rate` float(3,2) NOT NULL COMMENT '互动活跃度',
`reply_fans_rate` float(3,2) NOT NULL COMMENT '评论活跃度',
`danmu_fans_rate` float(3,2) NOT NULL COMMENT '弹幕活跃度',
`coin_fans_rate` float(3,2) NOT NULL COMMENT '投币活跃度',
`like_fans_rate` float(3,2) NOT NULL COMMENT '点赞活跃度',
`fav_fans_rate` float(3,2) NOT NULL COMMENT '收藏活跃度',
`share_fans_rate` float(3,2) NOT NULL COMMENT '分享活跃度',
`live_gift_fans_rate` float(3,2) NOT NULL COMMENT '直播礼物活跃度',
`live_danmu_fans_rate` float(3,2) NOT NULL COMMENT '直播弹幕活跃度',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='mcn粉丝数相关';
#mcn粉丝按天增量
CREATE TABLE `dm_con_mcn_fans_inc_d` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`fans_inc` bigint(20) NOT NULL COMMENT '当日新增粉丝数',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='mcn粉丝按天增量';
#mcn粉丝按天取关数
CREATE TABLE `dm_con_mcn_fans_dec_d` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`fans_dec` bigint(20) NOT NULL COMMENT '当日取关粉丝数',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='mcn粉丝按天取关数';
#mcn粉丝关注渠道
CREATE TABLE `dm_con_mcn_fans_attention_way_d` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`sign_id` bigint(20) NOT NULL COMMENT 'mcn签约ID',
`mcn_mid` bigint(20) NOT NULL COMMENT 'mcn的mid',
`log_date` date NOT NULL COMMENT '日期',
`homepage` bigint(20) NOT NULL COMMENT '主站个人空间关注用户数',
`video` bigint(20) NOT NULL COMMENT '主站视频页关注用户数',
`article` bigint(20) NOT NULL COMMENT '专栏关注用户数',
`music` bigint(20) NOT NULL COMMENT '音频关注用户数',
`other` bigint(20) NOT NULL COMMENT '其他关注用户数',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uni_idx` (`sign_id`,`log_date`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='mcn粉丝关注渠道';

View File

@@ -0,0 +1,87 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"crm.go",
"dao.cache.go",
"dao.go",
"data.go",
"mc.cache.go",
"memcahe.go",
"rank.go",
"recommend_pool.go",
"sign.go",
],
importpath = "go-common/app/interface/main/mcn/dao/mcndao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/mcn/model:go_default_library",
"//app/admin/main/up/util:go_default_library",
"//app/admin/main/up/util/mathutil:go_default_library",
"//app/interface/main/mcn/conf:go_default_library",
"//app/interface/main/mcn/dao/cache:go_default_library",
"//app/interface/main/mcn/dao/global:go_default_library",
"//app/interface/main/mcn/model:go_default_library",
"//app/interface/main/mcn/model/mcnmodel:go_default_library",
"//app/interface/main/mcn/tool/validate:go_default_library",
"//app/service/main/archive/api:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/stat/prom:go_default_library",
"//library/sync/pipeline/fanout:go_default_library",
"//vendor/github.com/bluele/gcache:go_default_library",
"//vendor/github.com/jinzhu/gorm:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = [
"crm_test.go",
"dao.cache_test.go",
"dao_test.go",
"data_test.go",
"mc.cache_test.go",
"memcahe_test.go",
"rank_test.go",
"recommend_pool_test.go",
"sign_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/mcn/conf:go_default_library",
"//app/interface/main/mcn/dao/global:go_default_library",
"//app/interface/main/mcn/model:go_default_library",
"//app/interface/main/mcn/model/mcnmodel:go_default_library",
"//library/ecode:go_default_library",
"//vendor/github.com/bluele/gcache:go_default_library",
"//vendor/github.com/jinzhu/gorm:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,38 @@
package mcndao
import (
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/library/log"
)
//GetActiveTid get tid from crm database
func (d *Dao) GetActiveTid(mids []int64) (res map[int64]int64, err error) {
var infoList []*mcnmodel.UpBaseInfo
err = d.mcndb.Select("mid, active_tid").Where("mid in (?) and business_type=1", mids).Find(&infoList).Error
if err != nil {
log.Error("fail to get active_tid from crm, err=%s", err)
return
}
res = make(map[int64]int64, len(infoList))
for _, v := range infoList {
res[v.Mid] = v.ActiveTid
}
return
}
//GetUpBaseInfo get up base info from crm database
func (d *Dao) GetUpBaseInfo(fields string, mids []int64) (res map[int64]*mcnmodel.UpBaseInfo, err error) {
var infoList []*mcnmodel.UpBaseInfo
err = d.mcndb.Select(fields).Where("mid in (?) and business_type=1", mids).Find(&infoList).Error
if err != nil {
log.Error("fail to get active_tid from crm, err=%s", err)
return
}
res = make(map[int64]*mcnmodel.UpBaseInfo, len(infoList))
for _, v := range infoList {
res[v.Mid] = v
}
return
}

View File

@@ -0,0 +1,22 @@
package mcndao
import (
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestMcndaoGetActiveTid(t *testing.T) {
convey.Convey("GetActiveTid", t, func(ctx convey.C) {
var (
mids = []int64{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.GetActiveTid(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,133 @@
// Code generated by $GOPATH/src/go-common/app/tool/cache/gen. DO NOT EDIT.
/*
Package mcndao is a generated cache proxy package.
It is generated from:
type _cache interface {
//cache: -nullcache=&mcnmodel.McnSign{ID:-1} -check_null_code=$!=nil&&$.ID==-1
McnSign(c context.Context, mcnmid int64) (up *mcnmodel.McnSign, err error)
//cache: -nullcache=&mcnmodel.McnGetDataSummaryReply{IsNull:true} -check_null_code=$!=nil&&$.IsNull
McnDataSummary(c context.Context, mcnmid int64, generateDate time.Time) (res *mcnmodel.McnGetDataSummaryReply, err error)
//cache: -nullcache=&mcnmodel.UpPermissionCache{IsNull:true} -check_null_code=$!=nil&&$.IsNull
UpPermission(c context.Context, signID int64, mid int64) (data *mcnmodel.UpPermissionCache, err error)
}
*/
package mcndao
import (
"context"
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/library/stat/prom"
"time"
)
var _ _cache
// McnSign get data from cache if miss will call source method, then add to cache.
func (d *Dao) McnSign(c context.Context, id int64) (res *mcnmodel.McnSign, err error) {
addCache := true
res, err = d.CacheMcnSign(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("McnSign")
return
}
prom.CacheMiss.Incr("McnSign")
res, err = d.RawMcnSign(c, id)
if err != nil {
return
}
miss := res
if miss == nil {
miss = &mcnmodel.McnSign{ID: -1}
}
if !addCache {
return
}
d.cache.Do(c, func(c context.Context) {
d.AddCacheMcnSign(c, id, miss)
})
return
}
// McnDataSummary get data from cache if miss will call source method, then add to cache.
func (d *Dao) McnDataSummary(c context.Context, id int64, generateDate time.Time) (res *mcnmodel.McnGetDataSummaryReply, err error) {
addCache := true
res, err = d.CacheMcnDataSummary(c, id, generateDate)
if err != nil {
addCache = false
err = nil
}
defer func() {
if res != nil && res.IsNull {
res = nil
}
}()
if res != nil {
prom.CacheHit.Incr("McnDataSummary")
return
}
prom.CacheMiss.Incr("McnDataSummary")
res, err = d.RawMcnDataSummary(c, id, generateDate)
if err != nil {
return
}
miss := res
if miss == nil {
miss = &mcnmodel.McnGetDataSummaryReply{IsNull: true}
}
if !addCache {
return
}
d.cache.Do(c, func(c context.Context) {
d.AddCacheMcnDataSummary(c, id, miss, generateDate)
})
return
}
// UpPermission get data from cache if miss will call source method, then add to cache.
func (d *Dao) UpPermission(c context.Context, id int64, mid int64) (res *mcnmodel.UpPermissionCache, err error) {
addCache := true
res, err = d.CacheUpPermission(c, id, mid)
if err != nil {
addCache = false
err = nil
}
defer func() {
if res != nil && res.IsNull {
res = nil
}
}()
if res != nil {
prom.CacheHit.Incr("UpPermission")
return
}
prom.CacheMiss.Incr("UpPermission")
res, err = d.RawUpPermission(c, id, mid)
if err != nil {
return
}
miss := res
if miss == nil {
miss = &mcnmodel.UpPermissionCache{IsNull: true}
}
if !addCache {
return
}
d.cache.Do(c, func(c context.Context) {
d.AddCacheUpPermission(c, id, miss, mid)
})
return
}

View File

@@ -0,0 +1,42 @@
package mcndao
import (
"context"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestMcndaoMcnSign(t *testing.T) {
convey.Convey("McnSign", 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.McnSign(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 TestMcndaoMcnDataSummary(t *testing.T) {
convey.Convey("McnDataSummary", t, func(ctx convey.C) {
var (
c = context.Background()
id = int64(0)
generateDate = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.McnDataSummary(c, id, generateDate)
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)
})
})
})
}

View File

@@ -0,0 +1,74 @@
package mcndao
import (
"context"
"fmt"
"runtime"
"time"
"go-common/app/interface/main/mcn/conf"
"go-common/app/interface/main/mcn/dao/global"
"go-common/library/cache/memcache"
"go-common/library/sync/pipeline/fanout"
"github.com/bluele/gcache"
"github.com/jinzhu/gorm"
)
// Dao dao
type Dao struct {
c *conf.Config
mc *memcache.Pool
mcndb *gorm.DB
//cache tool
cache *fanout.Fanout
mcnSignExpire int32
mcnDataExpire int32
localcache gcache.Cache
}
// New init mysql db
func New(c *conf.Config, localcache gcache.Cache) (dao *Dao) {
dao = &Dao{
c: c,
mc: global.GetMc(),
// cache worker
cache: fanout.New("cache", fanout.Worker(runtime.NumCPU()), fanout.Buffer(1024)),
mcnSignExpire: int32(time.Duration(c.Memcache.McnSignCacheExpire) / time.Second),
mcnDataExpire: int32(time.Duration(c.Memcache.McnDataCacheExpire) / time.Second),
localcache: localcache,
}
if localcache == nil {
dao.localcache = gcache.New(c.RankCache.Size).Simple().Build()
}
if dao.mcnDataExpire == 0 {
dao.mcnDataExpire = 3600
}
if dao.mcnSignExpire == 0 {
dao.mcnSignExpire = 3600
}
var err error
dao.mcndb, err = gorm.Open("mysql", c.MCNorm.DSN)
if err != nil {
panic(fmt.Errorf("db connect fail, err=%s", err))
}
dao.mcndb.LogMode(c.Other.Debug)
return
}
// Close close the resource.
func (d *Dao) Close() {
d.cache.Close()
d.mc.Close()
d.mcndb.Close()
}
// Ping dao ping
func (d *Dao) Ping(c context.Context) error {
return nil
}
//GetMcnDB get mcn db
func (d *Dao) GetMcnDB() *gorm.DB {
return d.mcndb
}

View File

@@ -0,0 +1,43 @@
package mcndao
import (
"flag"
"os"
"testing"
"go-common/app/interface/main/mcn/conf"
"github.com/bluele/gcache"
"go-common/app/interface/main/mcn/dao/global"
)
var (
d *Dao
localcache = gcache.New(1024).Simple().Build()
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.mcn-interface")
flag.Set("conf_token", "49e4671bafbf93059aeb602685052ca0")
flag.Set("tree_id", "58909")
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/mcn-interface.toml")
}
if os.Getenv("UT_LOCAL_TEST") != "" {
flag.Set("conf", "../../cmd/mcn-interface.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
global.Init(conf.Conf)
d = New(conf.Conf, localcache)
os.Exit(m.Run())
}

View File

@@ -0,0 +1,145 @@
package mcndao
import (
"time"
"go-common/app/interface/main/mcn/model"
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/library/log"
"github.com/jinzhu/gorm"
)
const (
dateFmt = "2006-01-02"
tidSummary = 65535 // 特殊的tid表示所有分区数据之和
)
//GetMcnDataSummary .
func (d *Dao) GetMcnDataSummary(selec string, query interface{}, args ...interface{}) (res *mcnmodel.McnDataSummary, err error) {
res = new(mcnmodel.McnDataSummary)
err = d.mcndb.Select(selec).Where(query, args...).Limit(1).Find(res).Error
if err != nil {
log.Error("query db fail, err=%s", err)
return
}
return
}
//GetMcnDataSummaryWithDiff get data with datacenter diff
func (d *Dao) GetMcnDataSummaryWithDiff(signID int64, dataTYpe mcnmodel.McnDataType, generateDate time.Time) (res *mcnmodel.McnGetDataSummaryReply, err error) {
dataDay0, err := d.GetMcnDataSummary("up_count, fans_count_accumulate, archive_count_accumulate, play_count_accumulate, generate_date", "sign_id=? and data_type=? and generate_date=? and active_tid=?", signID, dataTYpe, generateDate.Format(dateFmt), tidSummary)
if int64(dataDay0.GenerateDate) == 0 {
err = gorm.ErrRecordNotFound
}
if err != nil {
if err == gorm.ErrRecordNotFound {
err = nil
log.Warn("not found generate date=%s, sign id=%d", generateDate.Format(dateFmt), signID)
return
}
log.Error("fail to get data db, err=%s, sign id=%d", err, signID)
return
}
dataDay1, err := d.GetMcnDataSummary("up_count, fans_count_accumulate, archive_count_accumulate, play_count_accumulate, generate_date", "sign_id=? and data_type=? and generate_date=? and active_tid=?", signID, dataTYpe, generateDate.AddDate(0, 0, -1).Format(dateFmt), tidSummary)
if int64(dataDay1.GenerateDate) == 0 {
err = gorm.ErrRecordNotFound
}
if err != nil {
if err == gorm.ErrRecordNotFound {
err = nil
log.Warn("not found generate date=%s, sign id=%d", generateDate.Format(dateFmt), signID)
dataDay1 = new(mcnmodel.McnDataSummary)
} else {
log.Error("fail to get data db, err=%s, sign id=%d", err, signID)
return
}
}
res = new(mcnmodel.McnGetDataSummaryReply)
res.CopyFrom(dataDay0)
res.CalcDiff(dataDay1)
return
}
//GetDataUpLatestDate .
func (d *Dao) GetDataUpLatestDate(dataType mcnmodel.DataType, signID int64) (generateDate time.Time, err error) {
var model = mcnmodel.McnDataUp{}
err = d.mcndb.Select("generate_date").Where("data_type=? and sign_id=?", dataType, signID).Order("generate_date desc").Limit(1).Find(&model).Error
if err != nil {
log.Error("get latest date from mcn_data_up fail, err=%s", err)
return
}
generateDate = model.GenerateDate.Time()
return
}
//GetAllUpData .
func (d *Dao) GetAllUpData(signID int64, upmid int64, generateDate time.Time) (res []*mcnmodel.McnUpDataInfo, err error) {
var sqlstr = `select
u.begin_date,
u.end_date,
u.state,
u.up_mid,
u.publication_price,
u.permission,
d.fans_increase_accumulate,
d.archive_count,
d.play_count,
d.fans_increase_month,
d.fans_count,
d.fans_count_active,
generate_date
from
mcn_up as u left join mcn_data_up as d
on (d.sign_id = u.sign_id and d.up_mid = u.up_mid and d.data_type=1 and generate_date=? )
where u.sign_id=? and u.state not in (?)`
var values = []interface{}{generateDate, signID, []model.MCNUPState{model.MCNUPStateOnDelete}}
if upmid != 0 {
sqlstr += " and u.up_mid=?"
values = append(values, upmid)
}
err = d.mcndb.Raw(sqlstr, values...).Find(&res).Error
if err != nil {
log.Error("query db fail, err=%s", err)
return
}
return
}
//GetAllUpDataTemp .
func (d *Dao) GetAllUpDataTemp(signID int64, upmid int64, generateDate time.Time) (res []*mcnmodel.McnUpDataInfo, err error) {
/*
前台这边一期的数据
1.首页 - 绑定up主总数
2.up主列表 - 总粉数
3.up主列表 - 投稿数
4.up主列表 - up分区
5.up主列表 - 签约及到期时间
*/
var sqlstr = `select
u.begin_date,
u.end_date,
u.state,
u.up_mid,
d.article_count_accumulate as archive_count,
d.fans_count,
d.active_fans as fans_count_active
from
mcn_up as u left join up_base_info as d
on (d.mid = u.up_mid and d.business_type = 1)
where u.sign_id=? and u.state not in (?)`
var values = []interface{}{signID, []model.MCNUPState{model.MCNUPStateOnDelete, model.MCNUPStateOnExpire, model.MCNUPStateOnClear}}
if upmid != 0 {
sqlstr += " and u.up_mid=?"
values = append(values, upmid)
}
err = d.mcndb.Raw(sqlstr, values...).Find(&res).Error
if err != nil {
log.Error("query db fail, err=%s", err)
return
}
return
}

View File

@@ -0,0 +1,94 @@
package mcndao
import (
"testing"
"time"
"go-common/app/interface/main/mcn/model/mcnmodel"
"github.com/jinzhu/gorm"
"github.com/smartystreets/goconvey/convey"
)
func TestMcndaoGetMcnDataSummary(t *testing.T) {
convey.Convey("GetMcnDataSummary", t, func(ctx convey.C) {
var (
selec = "*"
query = "1=?"
args = "1"
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.GetMcnDataSummary(selec, query, 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 TestMcndaoGetMcnDataSummaryWithDiff(t *testing.T) {
convey.Convey("GetMcnDataSummaryWithDiff", t, func(ctx convey.C) {
var (
signID = int64(0)
dataTYpe mcnmodel.McnDataType
generateDate = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.GetMcnDataSummaryWithDiff(signID, dataTYpe, generateDate)
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 TestMcndaoGetDataUpLatestDate(t *testing.T) {
convey.Convey("GetDataUpLatestDate", t, func(ctx convey.C) {
var (
dataType = mcnmodel.DataType(1)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
generateDate, err := d.GetDataUpLatestDate(dataType, 0)
ctx.Convey("Then err should be nil.generateDate should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldEqual, gorm.ErrRecordNotFound)
ctx.So(generateDate, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoGetAllUpData(t *testing.T) {
convey.Convey("GetAllUpData", t, func(ctx convey.C) {
var (
signID = int64(0)
upmid = int64(0)
generateDate = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.GetAllUpData(signID, upmid, generateDate)
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 TestMcndaoGetAllUpDataTemp(t *testing.T) {
convey.Convey("GetAllUpDataTemp", t, func(ctx convey.C) {
var (
signID = int64(0)
upmid = int64(0)
generateDate = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.GetAllUpDataTemp(signID, upmid, generateDate)
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,287 @@
// Code generated by $GOPATH/src/go-common/app/tool/cache/mc. DO NOT EDIT.
/*
Package mcndao is a generated mc cache package.
It is generated from:
type _mc interface {
//mc: -key=mcnSignCacheKey -expire=d.mcnSignExpire -encode=json
AddCacheMcnSign(c context.Context, mcnmid int64, up *mcnmodel.McnSign) (err error)
//mc: -key=mcnSignCacheKey
CacheMcnSign(c context.Context, mcnmid int64) (up *mcnmodel.McnSign, err error)
//mc: -key=mcnSignCacheKey
DelCacheMcnSign(c context.Context, mcnmid int64) (err error)
//mc: -key=mcnDataCacheKey -expire=d.mcnDataExpire -encode=json
AddCacheMcnDataSummary(c context.Context, mcnmid int64, data *mcnmodel.McnGetDataSummaryReply, generateDate time.Time) (err error)
//mc: -key=mcnDataCacheKey
CacheMcnDataSummary(c context.Context, mcnmid int64, generateDate time.Time) (data *mcnmodel.McnGetDataSummaryReply, err error)
//mc: -key=mcnDataCacheKey
DelMcnDataSummary(c context.Context, mcnmid int64, generateDate time.Time) (err error)
//mc: -key=mcnPublicationPriceKey -expire=0 -encode=json
AddCachePublicationPrice(c context.Context, signID int64, data *mcnmodel.PublicationPriceCache, mid int64) (err error)
//mc: -key=mcnPublicationPriceKey
CachePublicationPrice(c context.Context, signID int64, mid int64) (data *mcnmodel.PublicationPriceCache, err error)
//mc: -key=mcnPublicationPriceKey
DelPublicationPrice(c context.Context, signID int64, mid int64) (err error)
//mc: -key=mcnUpPermissionKey -expire=d.mcnSignExpire -encode=json
AddCacheUpPermission(c context.Context, signID int64, data *mcnmodel.UpPermissionCache, mid int64) (err error)
//mc: -key=mcnUpPermissionKey
CacheUpPermission(c context.Context, signID int64, mid int64) (data *mcnmodel.UpPermissionCache, err error)
//mc: -key=mcnUpPermissionKey
DelUpPermission(c context.Context, signID int64, mid int64) (err error)
}
*/
package mcndao
import (
"context"
"fmt"
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/library/cache/memcache"
"go-common/library/log"
"go-common/library/stat/prom"
"time"
)
var _ _mc
// AddCacheMcnSign Set data to mc
func (d *Dao) AddCacheMcnSign(c context.Context, id int64, val *mcnmodel.McnSign) (err error) {
if val == nil {
return
}
conn := d.mc.Get(c)
defer conn.Close()
key := mcnSignCacheKey(id)
item := &memcache.Item{Key: key, Object: val, Expiration: d.mcnSignExpire, Flags: memcache.FlagJSON}
if err = conn.Set(item); err != nil {
prom.BusinessErrCount.Incr("mc:AddCacheMcnSign")
log.Errorv(c, log.KV("AddCacheMcnSign", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// CacheMcnSign get data from mc
func (d *Dao) CacheMcnSign(c context.Context, id int64) (res *mcnmodel.McnSign, err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := mcnSignCacheKey(id)
reply, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:CacheMcnSign")
log.Errorv(c, log.KV("CacheMcnSign", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
res = &mcnmodel.McnSign{}
err = conn.Scan(reply, res)
if err != nil {
prom.BusinessErrCount.Incr("mc:CacheMcnSign")
log.Errorv(c, log.KV("CacheMcnSign", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// DelCacheMcnSign delete data from mc
func (d *Dao) DelCacheMcnSign(c context.Context, id int64) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := mcnSignCacheKey(id)
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:DelCacheMcnSign")
log.Errorv(c, log.KV("DelCacheMcnSign", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// AddCacheMcnDataSummary Set data to mc
func (d *Dao) AddCacheMcnDataSummary(c context.Context, id int64, val *mcnmodel.McnGetDataSummaryReply, generateDate time.Time) (err error) {
if val == nil {
return
}
conn := d.mc.Get(c)
defer conn.Close()
key := mcnDataCacheKey(id, generateDate)
item := &memcache.Item{Key: key, Object: val, Expiration: d.mcnDataExpire, Flags: memcache.FlagJSON}
if err = conn.Set(item); err != nil {
prom.BusinessErrCount.Incr("mc:AddCacheMcnDataSummary")
log.Errorv(c, log.KV("AddCacheMcnDataSummary", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// CacheMcnDataSummary get data from mc
func (d *Dao) CacheMcnDataSummary(c context.Context, id int64, generateDate time.Time) (res *mcnmodel.McnGetDataSummaryReply, err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := mcnDataCacheKey(id, generateDate)
reply, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:CacheMcnDataSummary")
log.Errorv(c, log.KV("CacheMcnDataSummary", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
res = &mcnmodel.McnGetDataSummaryReply{}
err = conn.Scan(reply, res)
if err != nil {
prom.BusinessErrCount.Incr("mc:CacheMcnDataSummary")
log.Errorv(c, log.KV("CacheMcnDataSummary", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// DelMcnDataSummary delete data from mc
func (d *Dao) DelMcnDataSummary(c context.Context, id int64, generateDate time.Time) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := mcnDataCacheKey(id, generateDate)
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:DelMcnDataSummary")
log.Errorv(c, log.KV("DelMcnDataSummary", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// AddCachePublicationPrice Set data to mc
func (d *Dao) AddCachePublicationPrice(c context.Context, id int64, val *mcnmodel.PublicationPriceCache, mid int64) (err error) {
if val == nil {
return
}
conn := d.mc.Get(c)
defer conn.Close()
key := mcnPublicationPriceKey(id, mid)
item := &memcache.Item{Key: key, Object: val, Expiration: 0, Flags: memcache.FlagJSON}
if err = conn.Set(item); err != nil {
prom.BusinessErrCount.Incr("mc:AddCachePublicationPrice")
log.Errorv(c, log.KV("AddCachePublicationPrice", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// CachePublicationPrice get data from mc
func (d *Dao) CachePublicationPrice(c context.Context, id int64, mid int64) (res *mcnmodel.PublicationPriceCache, err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := mcnPublicationPriceKey(id, mid)
reply, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:CachePublicationPrice")
log.Errorv(c, log.KV("CachePublicationPrice", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
res = &mcnmodel.PublicationPriceCache{}
err = conn.Scan(reply, res)
if err != nil {
prom.BusinessErrCount.Incr("mc:CachePublicationPrice")
log.Errorv(c, log.KV("CachePublicationPrice", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// DelPublicationPrice delete data from mc
func (d *Dao) DelPublicationPrice(c context.Context, id int64, mid int64) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := mcnPublicationPriceKey(id, mid)
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:DelPublicationPrice")
log.Errorv(c, log.KV("DelPublicationPrice", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// AddCacheUpPermission Set data to mc
func (d *Dao) AddCacheUpPermission(c context.Context, id int64, val *mcnmodel.UpPermissionCache, mid int64) (err error) {
if val == nil {
return
}
conn := d.mc.Get(c)
defer conn.Close()
key := mcnUpPermissionKey(id, mid)
item := &memcache.Item{Key: key, Object: val, Expiration: d.mcnSignExpire, Flags: memcache.FlagJSON}
if err = conn.Set(item); err != nil {
prom.BusinessErrCount.Incr("mc:AddCacheUpPermission")
log.Errorv(c, log.KV("AddCacheUpPermission", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// CacheUpPermission get data from mc
func (d *Dao) CacheUpPermission(c context.Context, id int64, mid int64) (res *mcnmodel.UpPermissionCache, err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := mcnUpPermissionKey(id, mid)
reply, err := conn.Get(key)
if err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:CacheUpPermission")
log.Errorv(c, log.KV("CacheUpPermission", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
res = &mcnmodel.UpPermissionCache{}
err = conn.Scan(reply, res)
if err != nil {
prom.BusinessErrCount.Incr("mc:CacheUpPermission")
log.Errorv(c, log.KV("CacheUpPermission", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}
// DelUpPermission delete data from mc
func (d *Dao) DelUpPermission(c context.Context, id int64, mid int64) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
key := mcnUpPermissionKey(id, mid)
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
prom.BusinessErrCount.Incr("mc:DelUpPermission")
log.Errorv(c, log.KV("DelUpPermission", fmt.Sprintf("%+v", err)), log.KV("key", key))
return
}
return
}

View File

@@ -0,0 +1,108 @@
package mcndao
import (
"context"
"testing"
"time"
"go-common/app/interface/main/mcn/model/mcnmodel"
"github.com/smartystreets/goconvey/convey"
)
func TestMcndaoAddCacheMcnSign(t *testing.T) {
convey.Convey("AddCacheMcnSign", t, func(ctx convey.C) {
var (
c = context.Background()
id = int64(0)
val = &mcnmodel.McnSign{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.AddCacheMcnSign(c, id, val)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMcndaoCacheMcnSign(t *testing.T) {
convey.Convey("CacheMcnSign", 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.CacheMcnSign(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 TestMcndaoDelCacheMcnSign(t *testing.T) {
convey.Convey("DelCacheMcnSign", t, func(ctx convey.C) {
var (
c = context.Background()
id = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.DelCacheMcnSign(c, id)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMcndaoAddCacheMcnDataSummary(t *testing.T) {
convey.Convey("AddCacheMcnDataSummary", t, func(ctx convey.C) {
var (
c = context.Background()
id = int64(0)
val = &mcnmodel.McnGetDataSummaryReply{}
generateDate = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.AddCacheMcnDataSummary(c, id, val, generateDate)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMcndaoCacheMcnDataSummary(t *testing.T) {
convey.Convey("CacheMcnDataSummary", t, func(ctx convey.C) {
var (
c = context.Background()
id = int64(0)
generateDate = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.CacheMcnDataSummary(c, id, generateDate)
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 TestMcndaoDelMcnDataSummary(t *testing.T) {
convey.Convey("DelMcnDataSummary", t, func(ctx convey.C) {
var (
c = context.Background()
id = int64(0)
generateDate = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.DelMcnDataSummary(c, id, generateDate)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,116 @@
package mcndao
import (
"context"
"fmt"
"time"
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/library/log"
"github.com/jinzhu/gorm"
)
//go:generate $GOPATH/src/go-common/app/tool/cache/gen
type _cache interface {
//cache: -nullcache=&mcnmodel.McnSign{ID:-1} -check_null_code=$!=nil&&$.ID==-1
McnSign(c context.Context, mcnmid int64) (up *mcnmodel.McnSign, err error)
//cache: -nullcache=&mcnmodel.McnGetDataSummaryReply{IsNull:true} -check_null_code=$!=nil&&$.IsNull
McnDataSummary(c context.Context, mcnmid int64, generateDate time.Time) (res *mcnmodel.McnGetDataSummaryReply, err error)
//cache: -nullcache=&mcnmodel.UpPermissionCache{IsNull:true} -check_null_code=$!=nil&&$.IsNull
UpPermission(c context.Context, signID int64, mid int64) (data *mcnmodel.UpPermissionCache, err error)
}
//go:generate $GOPATH/src/go-common/app/tool/cache/mc
type _mc interface {
//mc: -key=mcnSignCacheKey -expire=d.mcnSignExpire -encode=json
AddCacheMcnSign(c context.Context, mcnmid int64, up *mcnmodel.McnSign) (err error)
//mc: -key=mcnSignCacheKey
CacheMcnSign(c context.Context, mcnmid int64) (up *mcnmodel.McnSign, err error)
//mc: -key=mcnSignCacheKey
DelCacheMcnSign(c context.Context, mcnmid int64) (err error)
//mc: -key=mcnDataCacheKey -expire=d.mcnDataExpire -encode=json
AddCacheMcnDataSummary(c context.Context, mcnmid int64, data *mcnmodel.McnGetDataSummaryReply, generateDate time.Time) (err error)
//mc: -key=mcnDataCacheKey
CacheMcnDataSummary(c context.Context, mcnmid int64, generateDate time.Time) (data *mcnmodel.McnGetDataSummaryReply, err error)
//mc: -key=mcnDataCacheKey
DelMcnDataSummary(c context.Context, mcnmid int64, generateDate time.Time) (err error)
//mc: -key=mcnPublicationPriceKey -expire=0 -encode=json
AddCachePublicationPrice(c context.Context, signID int64, data *mcnmodel.PublicationPriceCache, mid int64) (err error)
//mc: -key=mcnPublicationPriceKey
CachePublicationPrice(c context.Context, signID int64, mid int64) (data *mcnmodel.PublicationPriceCache, err error)
//mc: -key=mcnPublicationPriceKey
DelPublicationPrice(c context.Context, signID int64, mid int64) (err error)
//mc: -key=mcnUpPermissionKey -expire=d.mcnSignExpire -encode=json
AddCacheUpPermission(c context.Context, signID int64, data *mcnmodel.UpPermissionCache, mid int64) (err error)
//mc: -key=mcnUpPermissionKey
CacheUpPermission(c context.Context, signID int64, mid int64) (data *mcnmodel.UpPermissionCache, err error)
//mc: -key=mcnUpPermissionKey
DelUpPermission(c context.Context, signID int64, mid int64) (err error)
}
func mcnSignCacheKey(mcnmid int64) string {
return fmt.Sprintf("mcn_s_%d", mcnmid)
}
//RawMcnSign raw db .
func (d *Dao) RawMcnSign(c context.Context, mcnmid int64) (up *mcnmodel.McnSign, err error) {
up, _, err = d.GetMcnSignState("*", mcnmid)
if err != nil {
if err == gorm.ErrRecordNotFound {
err = nil
return
}
log.Error("error get state, err=%s", err)
return
}
return
}
//AsyncDelCacheMcnSign delete in async way
func (d *Dao) AsyncDelCacheMcnSign(id int64) (err error) {
return d.cache.Do(context.Background(), func(c context.Context) {
d.DelCacheMcnSign(c, id)
})
}
func mcnDataCacheKey(signID int64, generateDate time.Time) string {
var key = fmt.Sprintf("mcn_data_%d_%s", signID, generateDate.Format(dateFmt))
return key
}
//RawMcnDataSummary raw get
func (d *Dao) RawMcnDataSummary(c context.Context, signID int64, generateDate time.Time) (res *mcnmodel.McnGetDataSummaryReply, err error) {
return d.GetMcnDataSummaryWithDiff(signID, mcnmodel.McnDataTypeDay, generateDate)
}
func mcnPublicationPriceKey(signID int64, mid int64) string {
return fmt.Sprintf("mcn_pubprice_%d_%d", signID, mid)
}
func mcnUpPermissionKey(signID int64, mid int64) string {
var s = fmt.Sprintf("mcn_upperm_%d_%d", signID, mid)
log.Info("key=%s", s)
return s
}
//RawUpPermission get permissino from db
func (d *Dao) RawUpPermission(c context.Context, signID int64, mid int64) (res *mcnmodel.UpPermissionCache, err error) {
upList, err := d.GetUpBind("up_mid=? and sign_id=? and state in (?)", mid, signID, UpSignedStates)
if err != nil {
log.Error("get up from db fail, err=%v, signid=%d, mid=%d", err, signID, mid)
return
}
if len(upList) == 0 {
log.Warn("up not found, sign_id=%d, mid=%d", signID, mid)
return
}
res = new(mcnmodel.UpPermissionCache)
res.Permission = upList[0].Permission
return
}

View File

@@ -0,0 +1,85 @@
package mcndao
import (
"context"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestMcndaomcnSignCacheKey(t *testing.T) {
convey.Convey("mcnSignCacheKey", t, func(ctx convey.C) {
var (
mcnmid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := mcnSignCacheKey(mcnmid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoRawMcnSign(t *testing.T) {
convey.Convey("RawMcnSign", t, func(ctx convey.C) {
var (
c = context.Background()
mcnmid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
up, err := d.RawMcnSign(c, mcnmid)
ctx.Convey("Then err should be nil.up should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(up, convey.ShouldBeNil)
})
})
})
}
func TestMcndaoAsyncDelCacheMcnSign(t *testing.T) {
convey.Convey("AsyncDelCacheMcnSign", t, func(ctx convey.C) {
var (
id = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.AsyncDelCacheMcnSign(id)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMcndaomcnDataCacheKey(t *testing.T) {
convey.Convey("mcnDataCacheKey", t, func(ctx convey.C) {
var (
signID = int64(0)
generateDate = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := mcnDataCacheKey(signID, generateDate)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoRawMcnDataSummary(t *testing.T) {
convey.Convey("RawMcnDataSummary", t, func(ctx convey.C) {
var (
c = context.Background()
id = int64(0)
generateDate = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.RawMcnDataSummary(c, id, generateDate)
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)
})
})
})
}

View File

@@ -0,0 +1,426 @@
package mcndao
import (
"context"
"fmt"
"sort"
"time"
"go-common/app/admin/main/up/util"
"go-common/app/admin/main/up/util/mathutil"
"go-common/app/interface/main/mcn/conf"
"go-common/app/interface/main/mcn/dao/cache"
"go-common/app/interface/main/mcn/dao/global"
"go-common/app/interface/main/mcn/model/mcnmodel"
arcgrpc "go-common/app/service/main/archive/api"
"go-common/library/log"
"github.com/bluele/gcache"
)
// RankByTid .
// 存储rank的缓存
// 对每种排行榜的分类进行缓存
// 对排序进行实时计算
// 先去localcache中取取不到的话去db中取
type RankByTid struct {
// [tid][datatype] rank list
TidMap map[int16]map[mcnmodel.DataType][]mcnmodel.RankDataInterface
TidTypeListMap map[mcnmodel.DataType][]*mcnmodel.TidnameInfo
}
//RankFunc rank func
type RankFunc func(signId int64) (result *RankByTid, err error)
type tidnameUnique struct {
tidInfoMap map[mcnmodel.DataType]map[int16]*mcnmodel.TidnameInfo
}
func newTidNameUnique() *tidnameUnique {
return &tidnameUnique{tidInfoMap: make(map[mcnmodel.DataType]map[int16]*mcnmodel.TidnameInfo)}
}
func (t *tidnameUnique) addTid(tid int16, name string, datatype mcnmodel.DataType) {
var dmap map[int16]*mcnmodel.TidnameInfo
var ok bool
if dmap, ok = t.tidInfoMap[datatype]; !ok {
dmap = make(map[int16]*mcnmodel.TidnameInfo)
t.tidInfoMap[datatype] = dmap
}
dmap[tid] = &mcnmodel.TidnameInfo{Tid: tid, Name: name}
}
func (t *tidnameUnique) getList(datatype mcnmodel.DataType) (typeList []*mcnmodel.TidnameInfo) {
for _, v := range t.tidInfoMap[datatype] {
typeList = append(typeList, v)
}
return
}
func (t *tidnameUnique) export(dmap map[mcnmodel.DataType][]*mcnmodel.TidnameInfo) {
for dataType, tidMap := range t.tidInfoMap {
var typeList []*mcnmodel.TidnameInfo
for k, v := range tidMap {
if k == 0 {
continue
}
typeList = append(typeList, v)
}
dmap[dataType] = typeList
}
}
// // 排序根据increase数量做倒序
// type rankByFansIncreaseDesc []*mcnmodel.RankUpFansInfo
// func (s rankByFansIncreaseDesc) Len() int {
// return len(s)
// }
// func (s rankByFansIncreaseDesc) Swap(i, j int) {
// s[i], s[j] = s[j], s[i]
// }
// func (s rankByFansIncreaseDesc) Less(i, j int) bool {
// return s[i].FansIncrease > s[j].FansIncrease
// }
type sortRankFunc func(p1, p2 mcnmodel.RankDataInterface) bool
type rankDataSorter struct {
datas []mcnmodel.RankDataInterface
by sortRankFunc // Closure used in the Less method.
}
// Len is part of sort.Interface.
func (s *rankDataSorter) Len() int {
return len(s.datas)
}
// Swap is part of sort.Interface.
func (s *rankDataSorter) Swap(i, j int) {
s.datas[i], s.datas[j] = s.datas[j], s.datas[i]
}
// Less is part of sort.Interface. It is implemented by calling the "by" closure in the sorter.
func (s *rankDataSorter) Less(i, j int) bool {
return s.by(s.datas[i], s.datas[j])
}
func byValueDesc(p1, p2 mcnmodel.RankDataInterface) bool {
return p1.GetValue() > p2.GetValue()
}
//GetList get list
func (s *RankByTid) GetList(tid int16, dataType mcnmodel.DataType) (res []mcnmodel.RankDataInterface) {
if s.TidMap == nil {
return
}
tMap, ok := s.TidMap[tid]
if !ok || tMap == nil {
return
}
if res, ok = tMap[dataType]; !ok {
res = nil
}
return
}
var nulltidlist = make([]*mcnmodel.TidnameInfo, 0)
//GetTypeList get type's list
func (s *RankByTid) GetTypeList(dataType mcnmodel.DataType) (res []*mcnmodel.TidnameInfo) {
res = s.TidTypeListMap[dataType]
if res == nil {
res = nulltidlist
}
return
}
func (s *RankByTid) addRank(v mcnmodel.RankDataInterface) {
var dmap, allMap map[mcnmodel.DataType][]mcnmodel.RankDataInterface
if s.TidMap == nil {
s.TidMap = make(map[int16]map[mcnmodel.DataType][]mcnmodel.RankDataInterface)
}
var ok bool
if v.GetTid() != 0 {
if dmap, ok = s.TidMap[v.GetTid()]; !ok {
dmap = make(map[mcnmodel.DataType][]mcnmodel.RankDataInterface)
s.TidMap[v.GetTid()] = dmap
}
dmap[v.GetDataType()] = append(dmap[v.GetDataType()], v)
}
if allMap, ok = s.TidMap[0]; !ok {
allMap = make(map[mcnmodel.DataType][]mcnmodel.RankDataInterface)
s.TidMap[0] = allMap
}
allMap[v.GetDataType()] = append(allMap[v.GetDataType()], v)
}
func (s *RankByTid) addTidMap(v *tidnameUnique) {
if s.TidTypeListMap == nil {
s.TidTypeListMap = make(map[mcnmodel.DataType][]*mcnmodel.TidnameInfo)
}
v.export(s.TidTypeListMap)
}
//Truncate truncate all the sorted list by max item number
func (s *RankByTid) Truncate(max int) {
for _, v := range s.TidMap {
for k2, v2 := range v {
var length = len(v2)
if length == 0 {
continue
}
var m = mathutil.Min(max, length)
v[k2] = v2[0:m]
}
}
}
// Sort sort by sorting function
func (s *RankByTid) Sort(sortFunc sortRankFunc) {
for _, v := range s.TidMap {
for k2, v2 := range v {
var sorter = &rankDataSorter{
datas: v2,
by: sortFunc,
}
sort.Sort(sorter)
v[k2] = v2
}
}
}
type keyFunc func(int64) string
type loadRankFunc func(signID int64, date time.Time) (result *RankByTid, err error)
// GetRankUpFans get fans
func (d *Dao) GetRankUpFans(signID int64) (result *RankByTid, err error) {
return d.getRankCache(signID, cacheKeyRankFans, d.loadRankUpFansCache)
}
// GetRankArchiveLikes get fans
func (d *Dao) GetRankArchiveLikes(signID int64) (result *RankByTid, err error) {
return d.getRankCache(signID, cacheKeyRankArchiveLikes, d.loadRankArchiveLikesCache)
}
func (d *Dao) getRankCache(signID int64, keyCalc keyFunc, load loadRankFunc) (result *RankByTid, err error) {
var key = keyCalc(signID)
v, err := d.localcache.Get(key)
if err != nil {
if err == gcache.KeyNotFoundError {
// load cache
v, err = load(signID, time.Now())
if err != nil {
log.Error("load cache error, signID=%d, err=%s", signID, err)
return
}
d.localcache.SetWithExpire(key, v, time.Duration(conf.Conf.RankCache.ExpireTime))
} else {
log.Error("get from gcache err, signID=%d, err=%s", signID, err)
return
}
}
if v == nil {
return
}
result, _ = v.(*RankByTid)
return
}
func cacheKeyRankFans(signID int64) string {
return fmt.Sprintf("rank_fans_%d", signID)
}
func cacheKeyRankArchiveLikes(signID int64) string {
return fmt.Sprintf("rank_likes_%d", signID)
}
var dataTypes = []mcnmodel.DataType{
mcnmodel.DataTypeAccumulate,
mcnmodel.DataTypeDay,
mcnmodel.DataTypeWeek,
mcnmodel.DataTypeMonth,
mcnmodel.DataTypeActiveFans,
}
// --------------------------------------- load rank up fans -------------------------------
func (d *Dao) loadRankUpFansCache(signID int64, date time.Time) (result *RankByTid, err error) {
rawRanks, err := d.RawRankUpFans(signID, date)
if err != nil {
log.Error("fail to get raw rank up fans, signid=%d, err=%s", signID, err)
return
}
result = new(RankByTid)
if len(rawRanks) == 0 {
log.Info("up fans rank data is empty, sign id=%d", signID)
return
}
var midMap = make(map[int64]struct{})
//var accumulateMap = make(map[int64]*mcnmodel.McnRankUpFan)
// 获取mid列表
for _, v := range rawRanks {
midMap[v.UpMid] = struct{}{}
//if v.DataType == mcnmodel.DataTypeAccumulate {
// accumulateMap[v.UpMid] = v
//}
}
var mids []int64
for k := range midMap {
mids = append(mids, k)
}
// 获取账号信息,头像
accInfos, err := global.GetInfos(context.Background(), mids)
if err != nil || accInfos == nil {
log.Warn("get infos fail, err=%s", err)
}
var tidUnique = newTidNameUnique()
// 组装信息
for _, v := range rawRanks {
var info mcnmodel.RankUpFansInfo
info.Copy(v)
if account, ok := accInfos[v.UpMid]; ok {
info.Name = account.Name
info.UpFaceLink = account.Face
info.TidName = cache.GetTidName(int64(info.Tid))
if info.TidName == "" {
info.TidName = "其他"
}
tidUnique.addTid(info.Tid, info.TidName, info.DataType)
}
//if accumulateData, ok := accumulateMap[v.UpMid]; ok {
// info.FansAccumulate = accumulateData.Value1
//}
result.addRank(&info)
}
result.addTidMap(tidUnique)
// 排序
result.Sort(byValueDesc)
// 截断到10个截断需要在排序之后
result.Truncate(10)
return
}
//RawRankUpFans get from db
func (d *Dao) RawRankUpFans(signID int64, date time.Time) (result []*mcnmodel.McnRankUpFan, err error) {
// 有X种类型
// 昨日、上周、上月、累计
// 每种类型取最近日期的数据
for _, typ := range dataTypes {
var tmpResult []*mcnmodel.McnRankUpFan
e := d.mcndb.Raw(`select * from mcn_rank_up_fans where data_type=? and sign_id=?
and generate_date=(select generate_date from mcn_rank_up_fans where data_type=? and sign_id=? and generate_date <= ? order by generate_date desc limit 1)`,
typ, signID, typ, signID, date).
Find(&tmpResult).Error
if e != nil {
log.Error("fail to get rank, type=%d, sign id=%d, err=%s", typ, signID, e)
continue
}
result = append(result, tmpResult...)
}
log.Info("get rank from db, sign id=%d, len=%d, date=%s", signID, len(result), date.Format(dateFmt))
return
}
//ReloadRank reload rank from db
func (d *Dao) ReloadRank(signID int64) (err error) {
// load cache
v, err := d.loadRankUpFansCache(signID, time.Now())
if err != nil {
log.Error("load cache error, signID=%d, err=%s", signID, err)
return
}
var key = cacheKeyRankFans(signID)
d.localcache.SetWithExpire(key, v, time.Hour)
log.Info("reload rank cache, sign id=%d", signID)
return
}
// ----------------------------------------- load rank archive likes ------------------------------------
func (d *Dao) loadRankArchiveLikesCache(signID int64, date time.Time) (result *RankByTid, err error) {
rawArchiveLike, err := d.RawRankArchiveLikes(signID, date)
if err != nil {
log.Error("fail to get raw rank up fans, signid=%d, err=%s", signID, err)
return
}
result = new(RankByTid)
if len(rawArchiveLike) == 0 {
log.Info("archive likes rank data is empty, sign id=%d", signID)
return
}
// 获取 aid列表
var aids []int64
//var accumulateMap = make(map[int64]*mcnmodel.McnRankArchiveLike)
for _, v := range rawArchiveLike {
aids = append(aids, v.ArchiveID)
//if v.DataType == mcnmodel.DataTypeAccumulate {
// accumulateMap[v.ArchiveID] = v
//}
}
aids = util.Unique(aids)
// 获取archive信息
arcsReply, err := global.GetArcGRPC().Arcs(context.Background(), &arcgrpc.ArcsRequest{Aids: aids})
if err != nil {
log.Error("fail to get archive info, sign_id=%d err=%s", signID, err)
return
}
archiveDataMap := arcsReply.Arcs
var tidUnique = newTidNameUnique()
// 组装archive信息
for _, v := range rawArchiveLike {
var info = mcnmodel.RankArchiveLikeInfo{}
info.CopyFromDB(v)
var archive, ok = archiveDataMap[v.ArchiveID]
if !ok {
continue
}
info.CopyFromArchive(archive)
tidUnique.addTid(info.Tid, info.TidName, info.DataType)
//if accumulateData, ok := accumulateMap[v.ArchiveID]; ok {
// info.LikesAccumulate = accumulateData.LikeCount
//}
result.addRank(&info)
}
result.addTidMap(tidUnique)
// 排序
result.Sort(byValueDesc)
result.Truncate(10)
return
}
//RawRankArchiveLikes get from db
func (d *Dao) RawRankArchiveLikes(signID int64, date time.Time) (result []*mcnmodel.McnRankArchiveLike, err error) {
// 有X种类型
// 昨日、上周、上月、累计
// 每种类型取最近日期的数据
for _, typ := range dataTypes {
var tmpResult []*mcnmodel.McnRankArchiveLike
e := d.mcndb.Raw(`select * from mcn_rank_archive_likes where data_type=? and sign_id=?
and generate_date=(select generate_date from mcn_rank_archive_likes where data_type=? and sign_id=? and generate_date <= ? order by generate_date desc limit 1)`,
typ, signID, typ, signID, date).
Find(&tmpResult).Error
if e != nil {
log.Error("fail to get rank, type=%d, sign id=%d, err=%s", typ, signID, e)
continue
}
result = append(result, tmpResult...)
}
log.Info("get rank from db, sign id=%d, len=%d, date=%s", signID, len(result), date.Format(dateFmt))
return
}

View File

@@ -0,0 +1,193 @@
package mcndao
import (
"testing"
"time"
"go-common/app/interface/main/mcn/model/mcnmodel"
"github.com/smartystreets/goconvey/convey"
)
func TestMcndaobyValueDesc(t *testing.T) {
convey.Convey("byValueDesc", t, func(ctx convey.C) {
var (
p1 = &mcnmodel.RankUpFansInfo{Mid: 1}
p2 = &mcnmodel.RankUpFansInfo{Mid: 2}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := byValueDesc(p1, p2)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoGetRankUpFans(t *testing.T) {
convey.Convey("GetRankUpFans", t, func(ctx convey.C) {
var (
signID = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.GetRankUpFans(signID)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoGetRankArchiveLikes(t *testing.T) {
convey.Convey("GetRankArchiveLikes", t, func(ctx convey.C) {
var (
signID = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.GetRankArchiveLikes(signID)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaogetRankCache(t *testing.T) {
convey.Convey("getRankCache", t, func(ctx convey.C) {
var (
signID = int64(1)
keyCalc keyFunc
load loadRankFunc
)
keyCalc = cacheKeyRankFans
load = d.loadRankUpFansCache
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.getRankCache(signID, keyCalc, load)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
if result == nil {
ctx.So(result, convey.ShouldBeNil)
} else {
ctx.So(result, convey.ShouldNotBeNil)
}
})
})
})
}
func TestMcndaocacheKeyRankFans(t *testing.T) {
convey.Convey("cacheKeyRankFans", t, func(ctx convey.C) {
var (
signID = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := cacheKeyRankFans(signID)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaocacheKeyRankArchiveLikes(t *testing.T) {
convey.Convey("cacheKeyRankArchiveLikes", t, func(ctx convey.C) {
var (
signID = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := cacheKeyRankArchiveLikes(signID)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoloadRankUpFansCache(t *testing.T) {
convey.Convey("loadRankUpFansCache", t, func(ctx convey.C) {
var (
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.loadRankUpFansCache(signID, date)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoRawRankUpFans(t *testing.T) {
convey.Convey("RawRankUpFans", t, func(ctx convey.C) {
var (
signID = int64(1)
date = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.RawRankUpFans(signID, date)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
if len(result) == 0 {
ctx.So(result, convey.ShouldBeNil)
} else {
ctx.So(result, convey.ShouldNotBeNil)
}
})
})
})
}
func TestMcndaoReloadRank(t *testing.T) {
convey.Convey("ReloadRank", t, func(ctx convey.C) {
var (
signID = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.ReloadRank(signID)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMcndaoloadRankArchiveLikesCache(t *testing.T) {
convey.Convey("loadRankArchiveLikesCache", t, func(ctx convey.C) {
var (
signID = int64(0)
date = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.loadRankArchiveLikesCache(signID, date)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoRawRankArchiveLikes(t *testing.T) {
convey.Convey("RawRankArchiveLikes", t, func(ctx convey.C) {
var (
signID = int64(1)
date = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.RawRankArchiveLikes(signID, date)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
if len(result) == 0 {
ctx.So(result, convey.ShouldBeEmpty)
} else {
ctx.So(result, convey.ShouldNotBeNil)
}
})
})
})
}

View File

@@ -0,0 +1,183 @@
package mcndao
import (
"context"
"sort"
"time"
"go-common/app/interface/main/mcn/conf"
"go-common/app/interface/main/mcn/dao/cache"
"go-common/app/interface/main/mcn/dao/global"
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/library/log"
"github.com/bluele/gcache"
)
// RecommendPoolCache .
type RecommendPoolCache struct {
// map[tid] list
UpTidMap map[int16][]*mcnmodel.McnGetRecommendPoolInfo
TidTypeList []*mcnmodel.TidnameInfo
}
func (r *RecommendPoolCache) add(v *mcnmodel.McnGetRecommendPoolInfo) {
if v == nil {
return
}
if r.UpTidMap == nil {
r.UpTidMap = make(map[int16][]*mcnmodel.McnGetRecommendPoolInfo)
}
r.UpTidMap[v.ActiveTid] = append(r.UpTidMap[v.ActiveTid], v)
if v.ActiveTid != 0 {
// 加入到全部分类中
r.UpTidMap[0] = append(r.UpTidMap[0], v)
}
}
//RecommendSortFunc sort func
type RecommendSortFunc func(p1, p2 *mcnmodel.McnGetRecommendPoolInfo) bool
//RecommendDataSorter data sorter
type RecommendDataSorter struct {
Datas []*mcnmodel.McnGetRecommendPoolInfo
By RecommendSortFunc // Closure used in the Less method.
}
// Len is part of sort.Interface.
func (s *RecommendDataSorter) Len() int {
return len(s.Datas)
}
// Swap is part of sort.Interface.
func (s *RecommendDataSorter) Swap(i, j int) {
s.Datas[i], s.Datas[j] = s.Datas[j], s.Datas[i]
}
// Less is part of sort.Interface. It is implemented by calling the "by" closure in the sorter.
func (s *RecommendDataSorter) Less(i, j int) bool {
return s.By(s.Datas[i], s.Datas[j])
}
// RecommendSortByFansDesc .
func RecommendSortByFansDesc(p1, p2 *mcnmodel.McnGetRecommendPoolInfo) bool {
return p1.FansCount > p2.FansCount
}
// RecommendSortByFansAsc .
func RecommendSortByFansAsc(p1, p2 *mcnmodel.McnGetRecommendPoolInfo) bool {
return p1.FansCount < p2.FansCount
}
// RecommendSortByMonthFansDesc .
func RecommendSortByMonthFansDesc(p1, p2 *mcnmodel.McnGetRecommendPoolInfo) bool {
return p1.FansCountIncreaseMonth > p2.FansCountIncreaseMonth
}
// RecommendSortByArchiveCountDesc .
func RecommendSortByArchiveCountDesc(p1, p2 *mcnmodel.McnGetRecommendPoolInfo) bool {
return p1.ArchiveCount > p2.ArchiveCount
}
type loadRecommandFunc func() (res *RecommendPoolCache, err error)
func cacheKeyRecommend(int64) string {
return "recommend"
}
//rawGetRecommendPool get recommend pool
func (d *Dao) rawGetRecommendPool() (res []*mcnmodel.McnGetRecommendPoolInfo, err error) {
var dbresult []*mcnmodel.McnUpRecommendPool
err = d.mcndb.Where("state=?", mcnmodel.MCNUPRecommendStateOn).Find(&dbresult).Error
if err != nil {
log.Error("fail to get recommend pool, err=%s", err)
return
}
for _, v := range dbresult {
var info = &mcnmodel.McnGetRecommendPoolInfo{}
info.Copy(v)
res = append(res, info)
}
return
}
func (d *Dao) loadRecommendPool() (res *RecommendPoolCache, err error) {
recommendInfos, err := d.rawGetRecommendPool()
if err != nil {
log.Error("get recommend fail, err=%s", err)
return
}
var midMap = make(map[int64]struct{})
// 获取mid列表
for _, v := range recommendInfos {
midMap[v.UpMid] = struct{}{}
}
var mids []int64
for k := range midMap {
mids = append(mids, k)
}
// 获取账号信息,头像
accInfos, err := global.GetInfos(context.Background(), mids)
if err != nil || accInfos == nil {
log.Warn("get infos fail, err=%s", err)
}
var tidUnique = newTidNameUnique()
res = new(RecommendPoolCache)
for _, v := range recommendInfos {
if account, ok := accInfos[v.UpMid]; ok {
v.UpName = account.Name
}
v.TidName = cache.GetTidName(int64(v.ActiveTid))
// 这里DataTypeAccumulate只是用来记录一下
tidUnique.addTid(v.ActiveTid, v.TidName, mcnmodel.DataTypeAccumulate)
res.add(v)
}
res.TidTypeList = tidUnique.getList(mcnmodel.DataTypeAccumulate)
// 进行默认排序,按照粉丝数,降序
for k := range res.UpTidMap {
sort.Sort(&RecommendDataSorter{Datas: res.UpTidMap[k], By: RecommendSortByFansDesc})
}
return
}
func (d *Dao) getRecommendCache(keyCalc keyFunc, load loadRecommandFunc) (result *RecommendPoolCache, err error) {
var key = keyCalc(0)
v, err := d.localcache.Get(key)
if err != nil {
if err == gcache.KeyNotFoundError {
// load cache
v, err = load()
if err != nil {
log.Error("load cache error, key=%s. err=%s", key, err)
return
}
d.localcache.SetWithExpire(key, v, time.Duration(conf.Conf.RankCache.RecommendPoolExpireTime))
} else {
log.Error("get from gcache err, key=%s, err=%s", key, err)
return
}
}
if v == nil {
return
}
result, _ = v.(*RecommendPoolCache)
return
}
//GetRecommendPool get recommend pool
func (d *Dao) GetRecommendPool() (res *RecommendPoolCache, err error) {
res, err = d.getRecommendCache(cacheKeyRecommend, d.loadRecommendPool)
if err != nil {
log.Error("fail to get recommend pool, err=%s", err)
return
}
return
}

View File

@@ -0,0 +1,162 @@
package mcndao
import (
"go-common/app/interface/main/mcn/model/mcnmodel"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestMcndaoadd(t *testing.T) {
convey.Convey("add", t, func(ctx convey.C) {
var (
v = &mcnmodel.McnGetRecommendPoolInfo{}
s = &RecommendPoolCache{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
s.add(v)
ctx.Convey("No return values", func(ctx convey.C) {
})
})
})
}
func TestMcndaoLen(t *testing.T) {
var (
s = &RecommendDataSorter{}
)
convey.Convey("Len", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := s.Len()
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoRecommendSortByFansDesc(t *testing.T) {
convey.Convey("RecommendSortByFansDesc", t, func(ctx convey.C) {
var (
p1 = &mcnmodel.McnGetRecommendPoolInfo{}
p2 = &mcnmodel.McnGetRecommendPoolInfo{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := RecommendSortByFansDesc(p1, p2)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoRecommendSortByFansAsc(t *testing.T) {
convey.Convey("RecommendSortByFansAsc", t, func(ctx convey.C) {
var (
p1 = &mcnmodel.McnGetRecommendPoolInfo{}
p2 = &mcnmodel.McnGetRecommendPoolInfo{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := RecommendSortByFansAsc(p1, p2)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoRecommendSortByMonthFansDesc(t *testing.T) {
convey.Convey("RecommendSortByMonthFansDesc", t, func(ctx convey.C) {
var (
p1 = &mcnmodel.McnGetRecommendPoolInfo{}
p2 = &mcnmodel.McnGetRecommendPoolInfo{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := RecommendSortByMonthFansDesc(p1, p2)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoRecommendSortByArchiveCountDesc(t *testing.T) {
convey.Convey("RecommendSortByArchiveCountDesc", t, func(ctx convey.C) {
var (
p1 = &mcnmodel.McnGetRecommendPoolInfo{}
p2 = &mcnmodel.McnGetRecommendPoolInfo{}
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := RecommendSortByArchiveCountDesc(p1, p2)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaocacheKeyRecommend(t *testing.T) {
convey.Convey("cacheKeyRecommend", t, func(ctx convey.C) {
var (
a1 = int64(0)
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := cacheKeyRecommend(a1)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaorawGetRecommendPool(t *testing.T) {
convey.Convey("rawGetRecommendPool", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.rawGetRecommendPool()
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(len(res), convey.ShouldBeGreaterThanOrEqualTo, 0)
})
})
})
}
func TestMcndaoloadRecommendPool(t *testing.T) {
convey.Convey("loadRecommendPool", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.loadRecommendPool()
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 TestMcndaogetRecommendCache(t *testing.T) {
convey.Convey("getRecommendCache", t, func(ctx convey.C) {
var (
keyCalc = cacheKeyRecommend
load = d.loadRecommendPool
)
ctx.Convey("When everything gose positive", func(ctx convey.C) {
result, err := d.getRecommendCache(keyCalc, load)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoGetRecommendPool(t *testing.T) {
convey.Convey("GetRecommendPool", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
res, err := d.GetRecommendPool()
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,255 @@
package mcndao
import (
"time"
adminmodel "go-common/app/admin/main/mcn/model"
"go-common/app/interface/main/mcn/model"
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/app/interface/main/mcn/tool/validate"
"go-common/library/ecode"
"go-common/library/log"
"github.com/jinzhu/gorm"
"github.com/pkg/errors"
)
var (
signNotInStates = []model.MCNSignState{model.MCNSignStateOnDelete, model.MCNSignStateOnPreOpen, model.MCNSignStateOnExpire, model.MCNSignStateOnClear}
// 从高到低,先找到的返回
// 状态优先级:
// 0 封禁
// 1 签约
// 2
statePriority = []model.MCNSignState{
model.MCNSignStateOnBlock,
model.MCNSignStateOnSign,
model.MCNSignStateOnReject,
model.MCNSignStateOnReview,
model.MCNSignStateNoApply,
}
// mcnSign = mcnmodel.McnSign{}
// mcnUp = mcnmodel.McnUp{}
// UpPermissionApplyCannotApplyStates 在这此状态下不能再申请改变Up主
UpPermissionApplyCannotApplyStates = []adminmodel.MCNUPPermissionState{
adminmodel.MCNUPPermissionStateNoAuthorize, // 待Up主同意
adminmodel.MCNUPPermissionStateReview, // 待审核
}
// UpSignedStates up signed state
UpSignedStates = []model.MCNUPState{
model.MCNUPStateOnSign,
model.MCNUPStateOnPreOpen,
}
)
// GetMcnSignState .
// mcnList, it's all mcn sign found with the state
// state, the mcn's state of qualified, if multiple state found, will be return in priority
func (d *Dao) GetMcnSignState(fields string, mcnMid int64) (mcn *mcnmodel.McnSign, state model.MCNSignState, err error) {
var mcnList []*mcnmodel.McnSign
if err = d.mcndb.Select(fields).Where("mcn_mid=? and state not in(?)", mcnMid, signNotInStates).Find(&mcnList).Error; err != nil {
err = errors.WithStack(err)
return
}
if len(mcnList) == 0 {
log.Warn("mcn not exist, mcn id=%d", mcnMid)
err = ecode.NothingFound
return
}
var stateMap = make(map[model.MCNSignState]*mcnmodel.McnSign)
for _, v := range mcnList {
stateMap[model.MCNSignState(v.State)] = v
}
for _, v := range statePriority {
if mcnValue, ok := stateMap[v]; ok {
state = v
mcn = mcnValue
break
}
}
return
}
// GetUpBind .
func (d *Dao) GetUpBind(query interface{}, args ...interface{}) (upList []*mcnmodel.McnUp, err error) {
if err = d.mcndb.Select("*").Where(query, args...).Find(&upList).Error; err != nil {
if err == gorm.ErrRecordNotFound {
err = nil
} else {
log.Error("fail to get bind up from db, err=%s", err)
return
}
}
return
}
// BindUp .
func (d *Dao) BindUp(up *mcnmodel.McnUp, sign *mcnmodel.McnSign, arg *mcnmodel.McnBindUpApplyReq) (result *mcnmodel.McnUp, affectedRow int64, err error) {
if arg == nil || sign == nil {
return nil, 0, ecode.ServerErr
}
var db *gorm.DB
if up == nil {
up = &mcnmodel.McnUp{
SignID: sign.ID,
}
}
arg.CopyTo(up)
// 如果绑定自己,那么直接接受
if sign.McnMid == arg.UpMid {
up.State = model.MCNUPStateOnSign
// 签约周期为MCN的签约周期
if up.BeginDate == 0 {
up.BeginDate = sign.BeginDate
}
if up.EndDate == 0 {
up.EndDate = sign.EndDate
}
var (
now = time.Now()
date = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local)
)
if up.BeginDate.Time().After(date) {
up.State = model.MCNUPStateOnPreOpen
}
} else {
// 清除状态为未授权
up.State = model.MCNUPStateNoAuthorize
if !validate.RegHTTPCheck.MatchString(arg.ContractLink) || !validate.RegHTTPCheck.MatchString(arg.UpAuthLink) {
log.Error("contract link or up auth link is not http, arg=%v", arg)
err = ecode.RequestErr
return
}
}
// 判断开始时间与结束时间
if up.BeginDate == 0 || up.EndDate < up.BeginDate {
log.Error("begin date is after end date, arg=%v", arg)
err = ecode.MCNUpBindUpDateError
return
}
db = d.mcndb.Save(up)
affectedRow, err = db.RowsAffected, db.Error
if err != nil {
log.Error("save bind up info fail, err=%s, sign=%v", err, sign)
err = ecode.ServerErr
}
result = up
return
}
// UpdateBindUp .
func (d *Dao) UpdateBindUp(values map[string]interface{}, query interface{}, args ...interface{}) (affectedRow int64, err error) {
var db = d.mcndb.Table(mcnmodel.TableNameMcnUp).Where(query, args...).Updates(values)
affectedRow, err = db.RowsAffected, db.Error
if err != nil {
log.Error("fail to update bind up, err=%s", err)
}
return
}
//UpConfirm up confrim
func (d *Dao) UpConfirm(arg *mcnmodel.McnUpConfirmReq, state model.MCNUPState) (err error) {
var tx = d.mcndb.Begin()
defer func() {
if r := recover(); r != nil || err != nil {
tx.Rollback()
}
}()
var changeMap = map[string]interface{}{
"state": state,
"state_change_time": time.Now(),
}
if arg.Choice {
changeMap["confirm_time"] = time.Now()
}
err = tx.Table(mcnmodel.TableNameMcnUp).
Where("id=? and up_mid=? and state=?", arg.BindID, arg.UpMid, model.MCNUPStateNoAuthorize).
Updates(changeMap).Error
if err != nil {
log.Error("fail to update db, err=%s", err)
return
}
// 表示同意
if arg.Choice {
// 驳回其他的绑定请求
err = tx.Table(mcnmodel.TableNameMcnUp).
Where("id !=? and up_mid=? and state=?", arg.BindID, arg.UpMid, model.MCNUPStateNoAuthorize).
Updates(map[string]interface{}{
"state": model.MCNUPStateOnRefuse,
"state_change_time": time.Now(),
}).Error
if err != nil {
log.Error("fail to update db, err=%s", err)
return
}
}
return tx.Commit().Error
}
// GetBindInfo .
func (d *Dao) GetBindInfo(arg *mcnmodel.McnUpGetBindReq) (res *mcnmodel.McnGetBindReply, err error) {
var result mcnmodel.McnGetBindReply
err = d.mcndb.Raw(`select s.company_name, s.mcn_mid, u.up_auth_link, u.id as bind_id, u.permission as new_permission
from mcn_up as u inner join mcn_sign as s
on s.id = u.sign_id
where u.id = ? and u.up_mid=? and u.state = 0;`, arg.BindID, arg.UpMid).Find(&result).Error
res = &result
return
}
//GetMcnOldInfo 获取冷却中的信息
func (d *Dao) GetMcnOldInfo(mcnMid int64) (res *mcnmodel.McnSign, err error) {
res = new(mcnmodel.McnSign)
err = d.mcndb.Where("mcn_mid=? and state=?", mcnMid, model.MCNSignStateOnCooling).Order("id desc").Limit(1).Find(res).Error
if err != nil && err != gorm.ErrRecordNotFound {
log.Error("fail to get db, err=%s", err)
return
}
return
}
//GetUpPermissionApply 从permission apply表中读取数据
func (d *Dao) GetUpPermissionApply(fields string, query interface{}, args ...interface{}) (res []*mcnmodel.McnUpPermissionApply, err error) {
err = d.mcndb.Select(fields).Where(query, args...).Find(&res).Error
if err != nil {
log.Error("fail to get db, err=%v", err)
return
}
return
}
// GetUpPermissionBindInfo .
func (d *Dao) GetUpPermissionBindInfo(arg *mcnmodel.McnUpGetBindReq) (res *mcnmodel.McnGetBindReply, err error) {
var result mcnmodel.McnGetBindReply
err = d.mcndb.Raw(`select s.company_name, u.mcn_mid, u.up_auth_link, u.id as bind_id, u.old_permission, u.new_permission
from mcn_up_permission_apply as u inner join mcn_sign as s
on s.id = u.sign_id
where u.id = ? and u.up_mid=? and u.state = 0;`, arg.BindID, arg.UpMid).Find(&result).Error
res = &result
return
}
//UpPermissionConfirm up confrim
func (d *Dao) UpPermissionConfirm(arg *mcnmodel.McnUpConfirmReq, state adminmodel.MCNUPPermissionState) (err error) {
var db = d.mcndb
var changeMap = map[string]interface{}{
"state": state,
}
err = db.Table(mcnmodel.TableMcnUpPermissionApply).
Where("id=? and up_mid=? and state=?", arg.BindID, arg.UpMid, adminmodel.MCNUPPermissionStateNoAuthorize).
Updates(changeMap).Error
if err != nil {
log.Error("fail to update db, err=%s", err)
return
}
return
}

View File

@@ -0,0 +1,134 @@
package mcndao
import (
"testing"
"go-common/app/interface/main/mcn/model"
"go-common/app/interface/main/mcn/model/mcnmodel"
"go-common/library/ecode"
"github.com/smartystreets/goconvey/convey"
)
func TestMcndaoGetMcnSignState(t *testing.T) {
convey.Convey("GetMcnSignState", t, func(ctx convey.C) {
var (
fields = "*"
mcnMid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
mcn, state, err := d.GetMcnSignState(fields, mcnMid)
ctx.Convey("Then err should be nil.mcn,state should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldEqual, -404)
ctx.So(state, convey.ShouldNotBeNil)
ctx.So(mcn, convey.ShouldBeNil)
})
})
})
}
func TestMcndaoGetUpBind(t *testing.T) {
convey.Convey("GetUpBind", t, func(ctx convey.C) {
var (
query = "1=?"
args = "0"
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
upList, err := d.GetUpBind(query, args)
ctx.Convey("Then err should be nil.upList should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(upList, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoBindUp(t *testing.T) {
convey.Convey("BindUp", t, func(ctx convey.C) {
var (
up = &mcnmodel.McnUp{}
sign = &mcnmodel.McnSign{}
arg = &mcnmodel.McnBindUpApplyReq{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, affectedRow, err := d.BindUp(up, sign, arg)
ctx.Convey("Then err should be nil.result,affectedRow should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldEqual, 82010)
ctx.So(affectedRow, convey.ShouldEqual, 0)
ctx.So(result, convey.ShouldBeNil)
})
})
})
}
func TestMcndaoUpdateBindUp(t *testing.T) {
convey.Convey("UpdateBindUp", t, func(ctx convey.C) {
var (
values map[string]interface{}
query = interface{}(0)
args = interface{}(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
affectedRow, err := d.UpdateBindUp(values, query, args)
ctx.Convey("Then err should be nil.affectedRow should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affectedRow, convey.ShouldNotBeNil)
})
})
})
}
func TestMcndaoUpConfirm(t *testing.T) {
convey.Convey("UpConfirm", t, func(ctx convey.C) {
var (
arg = &mcnmodel.McnUpConfirmReq{}
state model.MCNUPState
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.UpConfirm(arg, state)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMcndaoGetBindInfo(t *testing.T) {
convey.Convey("GetBindInfo", t, func(ctx convey.C) {
var (
arg = &mcnmodel.McnUpGetBindReq{}
)
arg.BindID = 10
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.GetBindInfo(arg)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
if err == ecode.NothingFound {
ctx.So(err, convey.ShouldNotBeNil)
} else {
ctx.So(err, convey.ShouldBeNil)
}
if res != nil {
ctx.So(res, convey.ShouldNotBeNil)
} else {
ctx.So(res, convey.ShouldBeNil)
}
})
})
})
}
func TestMcndaoGetMcnOldInfo(t *testing.T) {
convey.Convey("GetMcnOldInfo", t, func(ctx convey.C) {
var (
mcnMid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.GetMcnOldInfo(mcnMid)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldEqual, -404)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,56 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"msg.go",
],
importpath = "go-common/app/interface/main/mcn/dao/msg",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/mcn/conf:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster: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"],
)
go_test(
name = "go_default_test",
srcs = [
"dao_test.go",
"msg_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/mcn/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
"//vendor/gopkg.in/h2non/gock.v1:go_default_library",
],
)

View File

@@ -0,0 +1,28 @@
package msg
import (
"go-common/app/interface/main/mcn/conf"
bm "go-common/library/net/http/blademaster"
)
const (
msgurl = "/api/notify/send.user.notify.do"
)
// Dao .
type Dao struct {
c *conf.Config
client *bm.Client
msgURL string
}
// New new a Dao and return.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
// http client
client: bm.NewClient(c.HTTPClient),
msgURL: c.Host.Msg + msgurl,
}
return
}

View File

@@ -0,0 +1,48 @@
package msg
import (
"flag"
"os"
"strings"
"testing"
"go-common/app/interface/main/mcn/conf"
"gopkg.in/h2non/gock.v1"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.mcn-interface")
flag.Set("conf_token", "49e4671bafbf93059aeb602685052ca0")
flag.Set("tree_id", "58909")
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/mcn-interface.toml")
}
if os.Getenv("UT_LOCAL_TEST") != "" {
flag.Set("conf", "../../cmd/mcn-interface.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
d.client.SetTransport(gock.DefaultTransport)
os.Exit(m.Run())
}
func httpMock(method, url string) *gock.Request {
r := gock.New(url)
r.Method = strings.ToUpper(method)
return r
}

View File

@@ -0,0 +1,61 @@
package msg
import (
"context"
"net/url"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/xstr"
"github.com/pkg/errors"
)
// MutliSendSysMsg Mutli send sys msg.
func (d *Dao) MutliSendSysMsg(c context.Context, allUids []int64, mc, title string, context string, ip string) (err error) {
var times int
ulen := len(allUids)
if ulen%100 == 0 {
times = ulen / 100
} else {
times = ulen/100 + 1
}
var uids []int64
for i := 0; i < times; i++ {
if i == times-1 {
uids = allUids[i*100:]
} else {
uids = allUids[i*100 : (i+1)*100]
}
if err = d.SendSysMsg(c, uids, mc, title, context, ip); err != nil {
continue
}
}
return
}
// SendSysMsg send sys msg.
func (d *Dao) SendSysMsg(c context.Context, uids []int64, mc, title string, context string, ip string) (err error) {
params := url.Values{}
params.Set("mc", mc)
params.Set("title", title)
params.Set("data_type", "4")
params.Set("context", context)
params.Set("mid_list", xstr.JoinInts(uids))
var res struct {
Code int `json:"code"`
Data *struct {
Status int8 `json:"status"`
Remark string `json:"remark"`
} `json:"data"`
}
if err = d.client.Post(c, d.msgURL, ip, params, &res); err != nil {
return
}
if res.Code != 0 {
err = errors.Wrapf(ecode.Int(res.Code), "SendSysMsg d.client.Post(%s,%d)", d.msgURL+"?"+params.Encode(), res.Code)
} else {
log.Info("send msg ok, resdata=%+v", res.Data)
}
return
}

View File

@@ -0,0 +1,51 @@
package msg
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
"gopkg.in/h2non/gock.v1"
)
func TestMsgMutliSendSysMsg(t *testing.T) {
convey.Convey("MutliSendSysMsg", t, func(ctx convey.C) {
var (
c = context.Background()
allUids = []int64{}
mc = ""
title = ""
context = ""
ip = ""
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.MutliSendSysMsg(c, allUids, mc, title, context, ip)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestMsgSendSysMsg(t *testing.T) {
convey.Convey("SendSysMsg", t, func(ctx convey.C) {
var (
c = context.Background()
uids = []int64{}
mc = ""
title = ""
context = ""
ip = ""
)
defer gock.OffAll()
httpMock("POST", "http://message.bilibili.co/api/notify/send.user.notify.do").Reply(200).JSON(`{"code": 0}`)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.SendSysMsg(c, uids, mc, title, context, ip)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}