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,54 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"abtest_test.go",
"dao_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/resource/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
"//vendor/gopkg.in/h2non/gock.v1:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"abtest.go",
"dao.go",
],
importpath = "go-common/app/service/main/resource/dao/abtest",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/resource/conf:go_default_library",
"//app/service/main/resource/model: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"],
)

View File

@@ -0,0 +1,32 @@
package abtest
import (
"context"
"fmt"
"net/url"
"go-common/app/service/main/resource/model"
"go-common/library/log"
)
// AbTest get abtest data from data-platform.
func (d *Dao) AbTest(c context.Context, names, ipaddr string) (adr []*model.AbTest, err error) {
params := url.Values{}
params.Set("groupNames", names)
var res struct {
Code int `json:"code"`
Data []*model.AbTest `json:"expItems"`
Msg string `json:"msg"`
}
if err = d.httpClient.Get(c, d.testURL, ipaddr, params, &res); err != nil {
log.Error("AbTest url(%s) error(%v)", d.testURL+"?"+params.Encode(), err)
return
}
if res.Code != 0 {
err = fmt.Errorf("AbTest api failed(%d)", res.Code)
log.Error("CpmsApp url(%s) res code(%d) or res.data(%v)", d.testURL+"?"+params.Encode(), res.Code, res.Data)
return
}
adr = res.Data
return
}

View File

@@ -0,0 +1,39 @@
package abtest
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestAbtestAbTest(t *testing.T) {
convey.Convey("Abtest", t, func() {
var (
c = context.Background()
names = "test"
ipaddr = "0.0.0.0"
)
convey.Convey("When everything is correct", func(ctx convey.C) {
adr, err := d.AbTest(context.TODO(), "", "")
ctx.Convey("Then error should be niladr should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(adr, convey.ShouldNotBeNil)
})
})
convey.Convey("When http request gets 404 error", func(ctx convey.C) {
httpMock("GET", d.testURL).Reply(404)
_, err := d.AbTest(c, names, ipaddr)
ctx.Convey("Then error should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
convey.Convey("When http request gets code != 0", func(ctx convey.C) {
httpMock("GET", d.testURL).Reply(200).JSON(`{"code":-3,"message":"faild","data":{}}`)
_, err := d.AbTest(c, names, ipaddr)
ctx.Convey("Then error should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,28 @@
package abtest
import (
"go-common/app/service/main/resource/conf"
httpx "go-common/library/net/http/blademaster"
)
// Dao define db struct
type Dao struct {
c *conf.Config
// cpt
httpClient *httpx.Client
testURL string
}
const (
_abTestURL = "/abserver/v1/app/query-exp"
)
// New init mysql db
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
httpClient: httpx.NewClient(c.HTTPClient),
testURL: c.Host.DataPlat + _abTestURL,
}
return
}

View File

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

View File

@@ -0,0 +1,60 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"dao_test.go",
"redis_test.go",
"vdoad_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/resource/conf:go_default_library",
"//library/cache/redis:go_default_library",
"//library/database/sql:go_default_library",
"//vendor/github.com/bouk/monkey:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"redis.go",
"vdoad.go",
],
importpath = "go-common/app/service/main/resource/dao/ads",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/resource/conf:go_default_library",
"//app/service/main/resource/model:go_default_library",
"//library/cache/redis:go_default_library",
"//library/database/sql:go_default_library",
"//library/log:go_default_library",
"//vendor/github.com/dgryski/go-farm: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,40 @@
package ads
import (
"context"
"time"
"go-common/app/service/main/resource/conf"
"go-common/library/cache/redis"
xsql "go-common/library/database/sql"
)
// Dao is resource dao.
type Dao struct {
db *xsql.DB
c *conf.Config
// redis
redis *redis.Pool
expire int32
}
// New init mysql db
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
db: xsql.NewMySQL(c.DB.Ads),
redis: redis.NewPool(c.Redis.Ads.Config),
expire: int32(time.Duration(c.Redis.Ads.Expire) / time.Second),
}
return
}
// Close close the resource.
func (d *Dao) Close() {
d.db.Close()
}
// Ping check dao health.
func (d *Dao) Ping(c context.Context) error {
return d.db.Ping(c)
}

View File

@@ -0,0 +1,64 @@
package ads
import (
"context"
"flag"
"os"
"testing"
"go-common/app/service/main/resource/conf"
"go-common/library/cache/redis"
"github.com/smartystreets/goconvey/convey"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.app-svr.resource-service")
flag.Set("conf_token", "y79sErNhxggjvULS0O8Czas9PaxHBF5o")
flag.Set("tree_id", "3232")
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/resource-service-test.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
m.Run()
os.Exit(0)
}
// func CleanCache() {
// pool := redis.NewPool(conf.Conf.Redis.Ads.Config)
// pool.Get(context.TODO()).Do("FLUSHDB")
// }
func WithDao(f func(d *Dao)) func() {
return func() {
convey.Reset(func() {
pool := redis.NewPool(conf.Conf.Redis.Ads.Config)
pool.Get(context.TODO()).Do("FLUSHDB")
})
f(d)
}
}
func TestDaoPing(t *testing.T) {
convey.Convey("Ping", t, func(ctx convey.C) {
err := d.Ping(context.TODO())
ctx.Convey("Err should be nil", func() {
ctx.So(err, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,94 @@
package ads
import (
"context"
"fmt"
"go-common/library/cache/redis"
"go-common/library/log"
"github.com/dgryski/go-farm"
)
const (
_prefixBuvid = "buvid:%d"
)
func (d *Dao) keyBuvid(buvid string) (key string) {
num := int64(farm.Hash32([]byte(buvid)))
key = fmt.Sprintf(_prefixBuvid, num%d.c.HashNum)
return
}
// ExistsAuth if existes buvid in redis.
func (d *Dao) ExistsAuth(c context.Context, key string) (ok bool, err error) {
var conn = d.redis.Get(c)
defer conn.Close()
if ok, err = redis.Bool(conn.Do("EXISTS", key)); err != nil {
log.Error("EXISTS key(%s), error(%v)", key, err)
}
return
}
// BuvidCount get buvid count info from redis.
func (d *Dao) BuvidCount(c context.Context, faid int64, buvid string) (res int64, err error) {
var (
key = d.keyBuvid(buvid)
conn = d.redis.Get(c)
field = faid
)
defer conn.Close()
if res, err = redis.Int64(conn.Do("HGET", key, field)); err != nil {
if err != redis.ErrNil {
log.Error("BuvidCount conn.Send HGET(%v, %v) error(%v)", key, field, err)
return
}
err = nil
}
return
}
// AddBuvidCount add buvid count info into redis.
func (d *Dao) AddBuvidCount(c context.Context, buvidCounts map[string]map[int64]int64) (err error) {
var (
key string
count int
conn = d.redis.Get(c)
faid int64
playCount int64
ok bool
)
defer conn.Close()
for buvid, buvidCount := range buvidCounts {
key = d.keyBuvid(buvid)
if ok, err = d.ExistsAuth(c, key); err != nil {
log.Error("EXISTS key(%s) error(%v)", key, err)
return
}
for faid, playCount = range buvidCount {
if err = conn.Send("HSET", key, faid, playCount); err != nil {
log.Error("HSET key(%s) field(%d) playCount(%d) error(%v)", key, faid, playCount, err)
return
}
count++
}
if !ok {
if err = conn.Send("EXPIRE", key, d.expire); err != nil {
log.Error("EXPIRE key(%s) expire(%v) error(%v)", key, d.expire, err)
return
}
count++
}
}
if err = conn.Flush(); err != nil {
log.Error("BuvidCount conn.Flush error(%v)", err)
return
}
for i := 0; i < count; i++ {
if _, err = conn.Receive(); err != nil {
log.Error("BuvidCount conn.Receive error(%v)", err)
return
}
}
return
}

View File

@@ -0,0 +1,60 @@
package ads
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestAdsBuvidCache(t *testing.T) {
var (
buvidCache = map[string]map[int64]int64{
"123456": {
10097289: 1,
10097290: 5,
},
"234567": {
10097288: 3,
10098523: 1,
},
}
res int64
err error
)
convey.Convey("AddBuvidCount - add cache", t, WithDao(func(d *Dao) {
err = d.AddBuvidCount(context.Background(), buvidCache)
convey.Convey("Error should be nil", func() {
convey.So(err, convey.ShouldBeNil)
})
convey.Convey("BuvidCount - get cache", func() {
convey.Convey("Case 1: faid = 10097290, buvid = 123456", func() {
res, err = d.BuvidCount(context.Background(), 10097290, "123456")
convey.Convey("Error should be nil, res should be 5", func() {
convey.So(err, convey.ShouldBeNil)
convey.So(res, convey.ShouldEqual, 5)
})
})
convey.Convey("Case 2: faid = 10097288, buvid = 234567", func() {
res, err := d.BuvidCount(context.Background(), 10097288, "234567")
convey.Convey("Error should be nil, res should be 3", func() {
convey.So(err, convey.ShouldBeNil)
convey.So(res, convey.ShouldEqual, 3)
})
})
})
convey.Convey("keyBuvid", func() {
key := d.keyBuvid("234567")
convey.Convey("key should not be nil", func() {
convey.So(key, convey.ShouldNotBeNil)
})
convey.Convey("ExistsAuth - expire cache", func() {
res, err := d.ExistsAuth(context.Background(), key)
convey.Convey("Error should be nil, res should be true", func() {
convey.So(err, convey.ShouldBeNil)
convey.So(res, convey.ShouldEqual, true)
})
})
})
}))
}

View File

@@ -0,0 +1,49 @@
package ads
import (
"context"
"database/sql"
"time"
"go-common/app/service/main/resource/model"
xsql "go-common/library/database/sql"
"go-common/library/log"
)
const (
_videoAdsSQL = `SELECT name,contract_id,aid,season_id,typeid,ad_cid,ad_strategy,ad_url,ad_order,skipable,note,agency_name,agency_country,
agency_area,price,verified,state,front_aid,target,platform,type,user_set,play_count,mtime FROM video_ads WHERE state=0 AND verified=1 AND starttime<? AND endtime>? ORDER BY mtime,ctime ASC`
)
// VideoAds get video_ads
func (dao *Dao) VideoAds(c context.Context) (ads []*model.VideoAD, err error) {
var (
rows *xsql.Rows
now = time.Now()
)
if rows, err = dao.db.Query(c, _videoAdsSQL, now, now); err != nil {
log.Error("dao.Exec(%v, %v), err (%v)", now, now, err)
return
}
defer rows.Close()
for rows.Next() {
ad := &model.VideoAD{}
var (
agencyCountry sql.NullInt64
agencyArea sql.NullInt64
price sql.NullFloat64
)
if err = rows.Scan(&ad.Name, &ad.ContractID, &ad.Aids, &ad.SeasonID, &ad.TypeID, &ad.AdCid, &ad.AdStrategy,
&ad.AdURL, &ad.AdOrder, &ad.Skipable, &ad.Note, &ad.AgencyName, &agencyCountry, &agencyArea,
&price, &ad.Verified, &ad.State, &ad.FrontAid, &ad.Target, &ad.Platform, &ad.Type, &ad.UserSet, &ad.PlayCount, &ad.MTime); err != nil {
log.Error("rows.Scan(), err (%v)", err)
return
}
ad.AgencyCountry = int(agencyCountry.Int64)
ad.AgencyArea = int(agencyArea.Int64)
ad.Price = float32(price.Float64)
ads = append(ads, ad)
}
err = rows.Err()
return
}

View File

@@ -0,0 +1,35 @@
package ads
import (
"context"
"fmt"
"reflect"
"testing"
xsql "go-common/library/database/sql"
"github.com/bouk/monkey"
"github.com/smartystreets/goconvey/convey"
)
func TestAdsVideoAds(t *testing.T) {
convey.Convey("VideoAds", t, func(ctx convey.C) {
ctx.Convey("When everything is correct", func(ctx convey.C) {
res, err := d.VideoAds(context.Background())
ctx.Convey("Error should be nil, res should not be empty(No Data)", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.SkipSo(res, convey.ShouldNotBeEmpty)
})
})
ctx.Convey("When db.Query gets error", func(ctx convey.C) {
guard := monkey.PatchInstanceMethod(reflect.TypeOf(d.db), "Query", func(_ *xsql.DB, _ context.Context, _ string, _ ...interface{}) (*xsql.Rows, error) {
return nil, fmt.Errorf("db.Query error")
})
defer guard.Unpatch()
_, err := d.VideoAds(context.Background())
ctx.Convey("Error should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,55 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"dao_test.go",
"wechat_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/resource/conf:go_default_library",
"//app/service/main/resource/model: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 = [
"dao.go",
"wechat.go",
],
importpath = "go-common/app/service/main/resource/dao/alarm",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/resource/conf:go_default_library",
"//app/service/main/resource/model: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"],
)

View File

@@ -0,0 +1,69 @@
package alarm
import (
"context"
"net/http"
"strings"
"time"
"go-common/app/service/main/resource/conf"
"go-common/app/service/main/resource/model"
"go-common/library/log"
httpx "go-common/library/net/http/blademaster"
)
// Dao is redis dao.
type Dao struct {
c *conf.Config
netClient *http.Client
httpClient *httpx.Client
}
// New is new redis dao.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
httpClient: httpx.NewClient(c.HTTPClient),
netClient: &http.Client{
Timeout: 3 * time.Second,
},
}
return d
}
func (d *Dao) CheckURL(originURL string, wis []*model.ResWarnInfo) {
var (
url string
req *http.Request
resp *http.Response
err error
)
if strings.HasPrefix(originURL, "https://") {
log.Info("CheckURL url(%s) is https ,replace to http", originURL)
url = strings.Replace(originURL, "https://", "http://", -1)
} else if !strings.HasPrefix(originURL, "http://") {
log.Info("CheckURL url(%s) don't have https and http", originURL)
url = "http://" + originURL
} else {
url = originURL
}
if req, err = http.NewRequest("GET", url, nil); err != nil {
log.Error("CheckURL NewRequest(%v) error(%v)", url, err)
return
}
req.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8")
req.Header.Add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36")
resp, err = d.netClient.Do(req)
if err != nil {
log.Error("CheckURL url(%s) originURL(%s) error(%v)", url, originURL, err)
} else if resp.StatusCode != http.StatusOK {
log.Error("CheckURL url(%s) originURL(%s) code(%v) not OK ", url, originURL, resp.StatusCode)
var sends = make(map[string][]*model.ResWarnInfo)
for _, wi := range wis {
sends[wi.UserName] = append(sends[wi.UserName], wi)
}
for userName, send := range sends {
d.sendWeChartURL(context.TODO(), resp.StatusCode, userName, send)
}
}
}

View File

@@ -0,0 +1,63 @@
package alarm
import (
"flag"
"os"
"strings"
"testing"
"github.com/smartystreets/goconvey/convey"
"go-common/app/service/main/resource/conf"
"go-common/app/service/main/resource/model"
"gopkg.in/h2non/gock.v1"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.app-svr.resource-service")
flag.Set("conf_token", "y79sErNhxggjvULS0O8Czas9PaxHBF5o")
flag.Set("tree_id", "3232")
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/resource-service-test.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
d.httpClient.SetTransport(gock.DefaultTransport)
m.Run()
os.Exit(0)
}
func httpMock(method, url string) *gock.Request {
r := gock.New(url)
r.Method = strings.ToUpper(method)
return r
}
func TestDaoCheckURL(t *testing.T) {
var (
originURL = "https://www.bilibili.com"
wis = []*model.ResWarnInfo{}
)
convey.Convey("CheckURL", t, func(ctx convey.C) {
httpMock("GET", "http://www.bilibili.com").Reply(200)
d.CheckURL(originURL, wis)
ctx.Convey("no return values", func() {
})
})
}

View File

@@ -0,0 +1,182 @@
package alarm
import (
"context"
"crypto/md5"
"encoding/hex"
"encoding/json"
"fmt"
"net/http"
"net/url"
"strconv"
"strings"
"time"
"go-common/app/service/main/resource/model"
"go-common/library/log"
)
var (
_states = map[int8]string{
int8(0): "开放浏览",
int8(-1): "待审",
int8(-2): "打回稿件回收站",
int8(-3): "网警锁定删除",
int8(-4): "锁定稿件",
// -5: "锁定稿件开放浏览",
int8(-6): "修复待审",
int8(-7): "暂缓审核",
// -8: "补档待审",
int8(-9): "等待转码",
int8(-10): "延迟发布",
int8(-11): "视频源待修",
// -12: "上传失败",
int8(-13): "允许评论待审",
// -14: "临时回收站",
int8(-15): "分发中",
int8(-16): "转码失败",
int8(-30): "创建已提交",
int8(-40): "UP主定时发布",
int8(-100): "UP主删除",
}
_codes = map[int]string{
404: "页面未找到",
502: "服务端异常",
504: "SLB超时",
}
)
func stateDescribe(state int8) string {
des, ok := _states[state]
if ok {
return des
}
return strconv.Itoa(int(state))
}
const (
_warnTitle = `
【线上投放告警】您有一个投放发生了异常,请尽快确认是否影响投放。
%v
以上内容确认后,如有异常请联系相关人员手动处理。`
_offLineTitle = `
【线上投放下线告警】您有一个投放内容变不可见状态,已自动下线。请尽快补充投放。
%v
以上投放所涉及的排期申请已经置为 <申请未投放>。`
_archiveContent = `
投放ID%d
稿件ID%d
投放标题:%s
投放位置:%s (位置ID%d)
投放时间段:%s - %s
当前稿件状态:%s
`
_urlContent = `
投放ID%d
URL%v
投放标题:%s
投放位置:%s (位置ID%d)
投放时间段:%s - %s
错误信息:%v(错误码: %v)
`
)
type wxParams struct {
Username string `json:"username"`
Content string `json:"content"`
Token string `json:"token"`
Timestamp int64 `json:"timestamp"`
Sign string `json:"signature"`
}
type resp struct {
Status int64 `json:"status"`
Msg string `json:"msg"`
}
// SendWeChart send message to QYWX
func (d *Dao) SendWeChart(c context.Context, ns int8, userName string, res []*model.ResWarnInfo, titleType string) (err error) {
var (
users = append(d.c.WeChantUsers, userName)
newStateStr = stateDescribe(ns)
contents []string
)
for _, re := range res {
stime := re.STime.Time().Format("2006-01-02 15:04:05")
etime := re.ETime.Time().Format("2006-01-02 15:04:05")
contents = append(contents, fmt.Sprintf(_archiveContent, re.AssignmentID, re.AID, re.AssignmentName, re.ResourceName, re.ResourceID, stime, etime, newStateStr))
}
params := url.Values{}
params.Set("username", strings.Join(users, ","))
if titleType == "warn" {
params.Set("content", fmt.Sprintf(_warnTitle, strings.Join(contents, "")))
} else {
params.Set("content", fmt.Sprintf(_offLineTitle, strings.Join(contents, "")))
}
params.Set("token", d.c.WeChatToken)
params.Set("timestamp", strconv.FormatInt(time.Now().Unix(), 10))
mh := md5.Sum([]byte(params.Encode() + d.c.WeChatSecret))
params.Set("signature", hex.EncodeToString(mh[:]))
p := &wxParams{
Username: params.Get("username"),
Content: params.Get("content"),
Token: params.Get("token"),
Sign: params.Get("signature"),
}
p.Timestamp, _ = strconv.ParseInt(params.Get("timestamp"), 10, 64)
bs, _ := json.Marshal(p)
payload := strings.NewReader(string(bs))
req, _ := http.NewRequest("POST", "http://bap.bilibili.co/api/v1/message/add", payload)
req.Header.Add("content-type", "application/json; charset=utf-8")
v := &resp{}
if err = d.httpClient.Do(context.TODO(), req, v); err != nil {
log.Error("s.httpClient.Do error(%v)", err)
}
return
}
// sendWeChartURL send message to QYWX
func (d *Dao) sendWeChartURL(c context.Context, code int, userName string, res []*model.ResWarnInfo) (err error) {
var (
users = append(d.c.WeChantUsers, userName)
codeInfo string
contents []string
)
if codeInfo = _codes[code]; codeInfo == "" {
codeInfo = "未知错误,请手动确认"
}
for _, re := range res {
stime := re.STime.Time().Format("2006-01-02 15:04:05")
etime := re.ETime.Time().Format("2006-01-02 15:04:05")
contents = append(contents, fmt.Sprintf(_urlContent, re.AssignmentID, re.URL, re.AssignmentName, re.ResourceName, re.ResourceID, stime, etime, codeInfo, code))
}
params := url.Values{}
params.Set("username", strings.Join(users, ","))
params.Set("content", fmt.Sprintf(_warnTitle, strings.Join(contents, "")))
params.Set("token", d.c.WeChatToken)
params.Set("timestamp", strconv.FormatInt(time.Now().Unix(), 10))
mh := md5.Sum([]byte(params.Encode() + d.c.WeChatSecret))
params.Set("signature", hex.EncodeToString(mh[:]))
p := &wxParams{
Username: params.Get("username"),
Content: params.Get("content"),
Token: params.Get("token"),
Sign: params.Get("signature"),
}
p.Timestamp, _ = strconv.ParseInt(params.Get("timestamp"), 10, 64)
bs, _ := json.Marshal(p)
payload := strings.NewReader(string(bs))
req, _ := http.NewRequest("POST", "http://bap.bilibili.co/api/v1/message/add", payload)
req.Header.Add("content-type", "application/json; charset=utf-8")
v := &resp{}
if err = d.httpClient.Do(context.TODO(), req, v); err != nil {
log.Error("s.httpClient.Do error(%v)", err)
}
return
}

View File

@@ -0,0 +1,72 @@
package alarm
import (
"context"
"testing"
"go-common/app/service/main/resource/model"
"github.com/smartystreets/goconvey/convey"
)
func TestAlarmstateDescribe(t *testing.T) {
convey.Convey("stateDescribe", t, func(ctx convey.C) {
ctx.Convey("When state = 0 is in the const map", func(ctx convey.C) {
res := stateDescribe(0)
ctx.Convey("Then res should equal 开放浏览", func(ctx convey.C) {
ctx.So(res, convey.ShouldEqual, "开放浏览")
})
})
ctx.Convey("When state = -99 is not in the const map", func(ctx convey.C) {
res := stateDescribe(-99)
ctx.Convey("Then res should equal -99", func(ctx convey.C) {
ctx.So(res, convey.ShouldEqual, "-99")
})
})
})
}
func TestAlarmSendWeChart(t *testing.T) {
convey.Convey("SendWeChart", t, func() {
convey.Convey("When everything is correct", func(ctx convey.C) {
httpMock("POST", "http://bap.bilibili.co/api/v1/message/add").Reply(200).JSON("{}")
err := d.SendWeChart(context.Background(), 1, "", []*model.ResWarnInfo{{}}, "unit test msg")
ctx.Convey("Then err should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
convey.Convey("When set http request gets 404", func(ctx convey.C) {
httpMock("POST", "http://bap.bilibili.co/api/v1/message/add").Reply(404)
err := d.SendWeChart(context.Background(), 1, "", []*model.ResWarnInfo{{}}, "unit test msg")
ctx.Convey("Then err should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
convey.Convey("When set titleType == \"warn\"", func(ctx convey.C) {
httpMock("POST", "http://bap.bilibili.co/api/v1/message/add").Reply(200).JSON("{}")
err := d.SendWeChart(context.Background(), 1, "", []*model.ResWarnInfo{{}}, "warn")
ctx.Convey("Then err should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestAlarmsendWeChartURL(t *testing.T) {
convey.Convey("sendWeChartURL", t, func() {
convey.Convey("When everything is correct", func(ctx convey.C) {
httpMock("POST", "http://bap.bilibili.co/api/v1/message/add").Reply(200).JSON("{}")
err := d.sendWeChartURL(context.Background(), 1, "", []*model.ResWarnInfo{{}})
ctx.Convey("Then err should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
convey.Convey("When set http request gets 404", func(ctx convey.C) {
httpMock("POST", "http://bap.bilibili.co/api/v1/message/add").Reply(404)
err := d.sendWeChartURL(context.Background(), 1, "", []*model.ResWarnInfo{{}})
ctx.Convey("Then err should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
})
}

View File

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

View File

@@ -0,0 +1,63 @@
package cpm
import (
"context"
"fmt"
"net/url"
"strconv"
locmdl "go-common/app/service/main/location/model"
"go-common/app/service/main/resource/model"
"go-common/library/log"
)
// CpmsAPP get ads from cpm platform.
func (d *Dao) CpmsAPP(c context.Context, aid, mid int64, build int, resource, mobiApp, device, buvid, network, openEvent, adExtra string, ip *locmdl.Info) (adr *model.ADRequest, err error) {
params := url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("build", strconv.Itoa(build))
params.Set("buvid", buvid)
params.Set("resource", resource)
params.Set("mobi_app", mobiApp)
params.Set("ip", ip.Addr)
if aid != 0 {
params.Set("aid", strconv.FormatInt(aid, 10))
}
if device != "" {
params.Set("device", device)
}
if ip.Country != "" {
params.Set("country", ip.Country)
}
if ip.Province != "" {
params.Set("province", ip.Province)
}
if ip.City != "" {
params.Set("city", ip.City)
}
if network != "" {
params.Set("network", network)
}
if openEvent != "" {
params.Set("open_event", openEvent)
}
if adExtra != "" {
params.Set("ad_extra", adExtra)
}
var res struct {
Code int `json:"code"`
Data *model.ADRequest `json:"data"`
Msg string `json:"message"`
}
if err = d.httpClient.Get(c, d.cpmAppURL, ip.Addr, params, &res); err != nil {
log.Error("CpmsAPP url(%s) error(%v)", d.cpmAppURL+"?"+params.Encode(), err)
return
}
if res.Code != 0 {
err = fmt.Errorf("CpmsAPP api failed(%d)", res.Code)
log.Error("CpmsApp url(%s) res code(%d) or res.data(%v)", d.cpmAppURL+"?"+params.Encode(), res.Code, res.Data)
return
}
adr = res.Data
return
}

View File

@@ -0,0 +1,36 @@
package cpm
import (
"context"
"testing"
"go-common/app/service/main/location/model"
"github.com/smartystreets/goconvey/convey"
)
func TestCpmCpmsAPP(t *testing.T) {
convey.Convey("When cpm returns code = 0", t, func(ctx convey.C) {
data := `{"code":0,"message":"successed","data":{}}`
httpMock("GET", d.cpmAppURL).Reply(200).JSON(data)
_, err := d.CpmsAPP(context.Background(), 0, 182504479, 6190, "457", "iphone", "phone", "222", "wifi", "", "", &model.Info{Addr: "218.4.147.222"})
ctx.Convey("Then Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
convey.Convey("When cpm returns code != 0", t, func(ctx convey.C) {
data := `{"code":-3,"message":"faild","data":{}}`
httpMock("GET", d.cpmAppURL).Reply(200).JSON(data)
_, err := d.CpmsAPP(context.Background(), 0, 182504479, 6190, "457", "iphone", "phone", "222", "wifi", "", "", &model.Info{Addr: "218.4.147.222"})
ctx.Convey("Then Error should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
convey.Convey("When cpm http request gets 404", t, func(ctx convey.C) {
httpMock("GET", d.cpmAppURL).Reply(404)
_, err := d.CpmsAPP(context.Background(), 0, 182504479, 6190, "457", "iphone", "phone", "222", "wifi", "", "", &model.Info{Addr: "218.4.147.222"})
ctx.Convey("Then Error should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,31 @@
package cpm
import (
"go-common/app/service/main/resource/conf"
httpx "go-common/library/net/http/blademaster"
)
// Dao define db struct
type Dao struct {
c *conf.Config
// cpt
httpClient *httpx.Client
cpmPCURL string
cpmAppURL string
}
const (
_cpmPCURL = "/bce/api/bce/pc"
_cpmAppURL = "/bce/api/bce/wise"
)
// New init mysql db
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
httpClient: httpx.NewClient(c.HTTPClient),
cpmPCURL: c.Host.Ad + _cpmPCURL,
cpmAppURL: c.Host.Ad + _cpmAppURL,
}
return
}

View File

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

View File

@@ -0,0 +1,52 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"dao_test.go",
"special_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/resource/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"special.go",
],
importpath = "go-common/app/service/main/resource/dao/manager",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/resource/api/v1:go_default_library",
"//app/service/main/resource/conf:go_default_library",
"//library/database/sql: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,28 @@
package manager
import (
"go-common/app/service/main/resource/conf"
"go-common/library/database/sql"
)
//Dao manager dao
type Dao struct {
db *sql.DB
c *conf.Config
}
//New new manager dao
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
db: sql.NewMySQL(c.DB.Manager),
}
return
}
// Close close db resource.
func (d *Dao) Close() {
if d.db != nil {
d.db.Close()
}
}

View File

@@ -0,0 +1,35 @@
package manager
import (
"flag"
"go-common/app/service/main/resource/conf"
"os"
"testing"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "prod" {
flag.Set("app_id", "main.app-svr.resource-service")
flag.Set("conf_token", "y79sErNhxggjvULS0O8Czas9PaxHBF5o")
flag.Set("tree_id", "3232")
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/resource-service-test.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
os.Exit(m.Run())
}

View File

@@ -0,0 +1,30 @@
package manager
import (
"context"
pb "go-common/app/service/main/resource/api/v1"
)
const (
_specialSQL = "SELECT `id`,`title`,`desc`,`cover`,`scover`,`re_type`,`re_value`,`corner`,`size`,`card` FROM special_card"
)
//Specials get specials cars from DB
func (d *Dao) Specials(c context.Context) (sps map[int64]*pb.SpecialReply, err error) {
rows, err := d.db.Query(c, _specialSQL)
if err != nil {
return
}
defer rows.Close()
sps = make(map[int64]*pb.SpecialReply)
for rows.Next() {
sc := &pb.SpecialReply{}
if err = rows.Scan(&sc.Id, &sc.Title, &sc.Desc, &sc.Cover, &sc.Scover, &sc.ReType, &sc.ReValue, &sc.Corner, &sc.Siz, &sc.Card); err != nil {
return
}
sps[sc.Id] = sc
}
err = rows.Err()
return
}

View File

@@ -0,0 +1,23 @@
package manager
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestManagerSpecials(t *testing.T) {
convey.Convey("Specials", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
sps, err := d.Specials(c)
ctx.Convey("Then err should be nil.sps should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(sps, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,57 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"banner_test.go",
"dao_test.go",
"resource_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/resource/conf:go_default_library",
"//library/database/sql:go_default_library",
"//vendor/github.com/bouk/monkey:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"banner.go",
"dao.go",
"resource.go",
],
importpath = "go-common/app/service/main/resource/dao/resource",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/resource/conf:go_default_library",
"//app/service/main/resource/model:go_default_library",
"//library/database/sql:go_default_library",
"//library/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,102 @@
package resource
import (
"context"
"fmt"
"time"
"go-common/app/service/main/resource/model"
"go-common/library/log"
)
var (
_bannerSQL = `SELECT rm.id,ra.position_id,rm.name,rm.url,rm.pic,ra.position,ra.platform,ra.rule,ra.atype,ra.stime FROM resource_assignment AS ra,resource_material AS rm
WHERE ra.resource_group_id>0 AND ra.category=0 AND ra.stime<? AND ra.etime>? AND ra.state=0 AND ra.audit_state IN (2,3,4) AND
ra.id=rm.resource_assignment_id AND rm.audit_state=2 AND rm.category=0 ORDER BY ra.position ASC,ra.weight DESC,rm.ctime DESC`
_categorySQL = `SELECT rm.id,ra.resource_id,rm.name,rm.url,rm.pic,ra.position,ra.platform,ra.rule,ra.atype,ra.stime FROM resource_assignment AS ra,resource_material AS rm
WHERE ra.id=rm.resource_assignment_id AND rm.id IN (SELECT max(rm.id) FROM resource_assignment AS ra,resource_material AS rm WHERE ra.resource_group_id>0 AND ra.category=1
AND ra.stime<? AND ra.etime>? AND ra.state=0 AND ra.audit_state IN (2,3,4) AND ra.id=rm.resource_assignment_id AND rm.audit_state=2 AND rm.category=1 GROUP BY rm.resource_assignment_id) ORDER BY rand()`
_bannerLimitSQL = "SELECT rule FROM default_one WHERE id=2"
)
// Banner get active banner from new db.
func (d *Dao) Banner(c context.Context) (res map[int8]map[int][]*model.Banner, err error) {
var (
now = time.Now()
ok bool
pm map[string]string
)
rows, err := d.db.Query(c, _bannerSQL, now, now)
if err != nil {
log.Error("query error(%v)", err)
return
}
defer rows.Close()
res = map[int8]map[int][]*model.Banner{}
pm = make(map[string]string)
for rows.Next() {
b := &model.Banner{}
if err = rows.Scan(&b.ID, &b.ParentID, &b.Title, &b.Value, &b.Image, &b.Rank, &b.Plat, &b.Rule, &b.Type, &b.Start); err != nil {
log.Error("rows.Scan error(%v)", err)
res = nil
return
}
pindex := fmt.Sprintf("%d_%d_%d", b.Plat, b.ParentID, b.Rank)
if _, ok = pm[pindex]; ok {
continue
}
b.BannerChange()
if plm, ok := res[b.Plat]; ok {
plm[b.ParentID] = append(plm[b.ParentID], b)
} else {
res[b.Plat] = map[int][]*model.Banner{
b.ParentID: []*model.Banner{b},
}
}
pm[pindex] = pindex
}
err = rows.Err()
return
}
// Category get category banner from new db.
func (d *Dao) Category(c context.Context) (res map[int8]map[int][]*model.Banner, err error) {
var now = time.Now()
rows, err := d.db.Query(c, _categorySQL, now, now)
if err != nil {
log.Error("query error(%v)", err)
return
}
defer rows.Close()
res = map[int8]map[int][]*model.Banner{}
for rows.Next() {
b := &model.Banner{}
if err = rows.Scan(&b.ID, &b.ParentID, &b.Title, &b.Value, &b.Image, &b.Rank, &b.Plat, &b.Rule, &b.Type, &b.Start); err != nil {
log.Error("rows.Scan error(%v)", err)
res = nil
return
}
b.BannerChange()
if plm, ok := res[b.Plat]; ok {
plm[b.ParentID] = append(plm[b.ParentID], b)
} else {
res[b.Plat] = map[int][]*model.Banner{
b.ParentID: []*model.Banner{b},
}
}
}
err = rows.Err()
return
}
// Limit get app banner limit num.
func (d *Dao) Limit(c context.Context) (res map[int]int, err error) {
row := d.db.QueryRow(c, _bannerLimitSQL)
b := &model.Limit{}
if err = row.Scan(&b.Rule); err != nil {
log.Error("Limit row.Scan error(%v)", err)
return
}
res = b.LimitChange()
return
}

View File

@@ -0,0 +1,65 @@
package resource
import (
"context"
"fmt"
"reflect"
"testing"
xsql "go-common/library/database/sql"
"github.com/bouk/monkey"
"github.com/smartystreets/goconvey/convey"
)
func TestResourceBanner(t *testing.T) {
convey.Convey("Banner", t, func(ctx convey.C) {
ctx.Convey("When Everything is correct", func(ctx convey.C) {
_, err := d.Banner(context.Background())
ctx.Convey("Error shouold be nil, res should not be empty(No Data)", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
ctx.Convey("When db.Query gets error", func(ctx convey.C) {
guard := monkey.PatchInstanceMethod(reflect.TypeOf(d.db), "Query", func(_ *xsql.DB, _ context.Context, _ string, _ ...interface{}) (*xsql.Rows, error) {
return nil, fmt.Errorf("db.Query error")
})
defer guard.Unpatch()
_, err := d.Banner(context.Background())
ctx.Convey("Error should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
})
}
func TestResourceCategory(t *testing.T) {
convey.Convey("Category", t, func(ctx convey.C) {
ctx.Convey("When everything is correct", func(ctx convey.C) {
_, err := d.Category(context.Background())
ctx.Convey("Error shouold be nil, res should not be empty(No Data)", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
ctx.Convey("When db.Query gets error", func(ctx convey.C) {
guard := monkey.PatchInstanceMethod(reflect.TypeOf(d.db), "Query", func(_ *xsql.DB, _ context.Context, _ string, _ ...interface{}) (*xsql.Rows, error) {
return nil, fmt.Errorf("db.Query error")
})
defer guard.Unpatch()
_, err := d.Category(context.Background())
ctx.Convey("Error should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
})
}
func TestResourceLimit(t *testing.T) {
convey.Convey("Limit", t, func(ctx convey.C) {
res, err := d.Limit(context.Background())
ctx.Convey("Error shouold be nil, res should not be empty", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeEmpty)
})
})
}

View File

@@ -0,0 +1,38 @@
package resource
import (
"context"
"go-common/app/service/main/resource/conf"
xsql "go-common/library/database/sql"
)
// Dao is resource dao.
type Dao struct {
db *xsql.DB
c *conf.Config
}
// New init mysql db
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
db: xsql.NewMySQL(c.DB.Res),
}
return
}
// BeginTran begin transcation.
func (d *Dao) BeginTran(c context.Context) (tx *xsql.Tx, err error) {
return d.db.Begin(c)
}
// Close close the resource.
func (d *Dao) Close() {
d.db.Close()
}
// Ping check dao health.
func (d *Dao) Ping(c context.Context) error {
return d.db.Ping(c)
}

View File

@@ -0,0 +1,58 @@
package resource
import (
"context"
"flag"
"os"
"testing"
"go-common/app/service/main/resource/conf"
"go-common/library/database/sql"
"github.com/smartystreets/goconvey/convey"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.app-svr.resource-service")
flag.Set("conf_token", "y79sErNhxggjvULS0O8Czas9PaxHBF5o")
flag.Set("tree_id", "3232")
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/resource-service-test.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
m.Run()
os.Exit(0)
}
func WithReopenDB(f func(d *Dao)) func() {
return func() {
convey.Reset(func() {
d.db = sql.NewMySQL(d.c.DB.Res)
})
f(d)
}
}
func TestDaoPing(t *testing.T) {
convey.Convey("Ping", t, func(ctx convey.C) {
err := d.Ping(context.TODO())
ctx.Convey("Err should be nil", func() {
ctx.So(err, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,269 @@
package resource
import (
"context"
"fmt"
"strings"
"time"
"database/sql"
"go-common/app/service/main/resource/model"
xsql "go-common/library/database/sql"
"go-common/library/log"
)
const (
_headerResIds = "142,925,926,927,1576,1580,1584,1588,1592,1596,1600,1604,1608,1612,1616,1620,1622,1634,1920,2210,2260"
)
var (
_allResSQL = `SELECT id,platform,name,parent,counter,position,rule,size,preview,description,mark,ctime,mtime,level,type,is_ad FROM resource ORDER BY counter desc,position ASC`
_allAssignSQL = fmt.Sprintf(`SELECT id,name,contract_id,resource_id,pic,litpic,url,rule,weight,agency,price,atype,username FROM resource_assignment
WHERE resource_group_id=0 AND stime<? AND etime>? AND state=0 AND resource_id IN (%s) ORDER BY weight,stime desc`, _headerResIds)
_allAssignNewSQL = `SELECT ra.id,rm.id,rm.name,ra.contract_id,ra.resource_id,rm.pic,rm.litpic,rm.url,ra.rule,ra.position,
ra.agency,ra.price,ra.stime,ra.etime,ra.apply_group_id,rm.ctime,rm.mtime,rm.atype,ra.username,rm.player_category FROM resource_assignment AS ra,resource_material AS rm
WHERE ra.resource_group_id>0 AND ra.category=0 AND ra.stime<? AND ra.etime>? AND ra.state=0 AND ra.audit_state IN (2,3,4) AND
ra.id=rm.resource_assignment_id AND rm.audit_state=2 AND rm.category=0 ORDER BY ra.position ASC,ra.weight DESC,rm.mtime DESC`
_categoryAssignSQL = fmt.Sprintf(`SELECT ra.id,rm.id,rm.name,ra.contract_id,ra.resource_id,rm.pic,rm.litpic,rm.url,ra.rule,ra.position,ra.agency,ra.price,
ra.stime,ra.etime,ra.apply_group_id,rm.ctime,rm.mtime,rm.atype,ra.username,rm.player_category FROM resource_assignment AS ra,resource_material AS rm
WHERE ra.id=rm.resource_assignment_id AND rm.id IN (SELECT max(rm.id) FROM resource_assignment AS ra,resource_material AS rm WHERE ra.resource_group_id>0
AND ra.category=1 AND ra.position_id NOT IN (%s) AND ra.stime<? AND ra.etime>? AND ra.state=0 AND ra.audit_state IN (2,3,4) AND ra.id=rm.resource_assignment_id AND
rm.audit_state=2 AND rm.category=1 GROUP BY rm.resource_assignment_id) ORDER BY rand()`, _headerResIds)
_defBannerSQL = `SELECT id,name,contract_id,resource_id,pic,litpic,url,rule,weight,agency,price,atype,username FROM default_one WHERE state=0`
// index-icon
_indexIconSQL = `SELECT id,type,title,state,link,icon,weight,user_name,sttime,endtime,deltime,ctime,mtime FROM icon WHERE state=1 AND deltime=0 AND (type=1 OR (type=2 AND sttime>0))`
_playIconSQL = `SELECT icon1,hash1,icon2,hash2,stime FROM bar_icon WHERE stime<? AND etime>? AND is_deleted=0`
// cmtbox
_cmtboxSQL = `SELECT id,load_cid,server,port,size_factor,speed_factor,max_onscreen,style,style_param,top_margin,state,ctime,mtime FROM cmtbox WHERE state=1`
// update resource assignment etime
_updateResourceAssignmentEtime = `UPDATE resource_assignment SET etime=? WHERE id=?`
// update resource apply status
_updateResourceApplyStatus = `UPDATE resource_apply SET audit_state=? WHERE apply_group_id IN (%s)`
// insert resource logs
_inResourceLogger = `INSERT INTO resource_logger (uname,uid,module,oid,content) VALUES (?,?,?,?,?)`
)
// Resources get resource infos from db
func (d *Dao) Resources(c context.Context) (rscs []*model.Resource, err error) {
var size sql.NullString
rows, err := d.db.Query(c, _allResSQL)
if err != nil {
log.Error("d.Resources query error (%v)", err)
return
}
defer rows.Close()
for rows.Next() {
rsc := &model.Resource{}
if err = rows.Scan(&rsc.ID, &rsc.Platform, &rsc.Name, &rsc.Parent, &rsc.Counter, &rsc.Position, &rsc.Rule, &size, &rsc.Previce,
&rsc.Desc, &rsc.Mark, &rsc.CTime, &rsc.MTime, &rsc.Level, &rsc.Type, &rsc.IsAd); err != nil {
log.Error("Resources rows.Scan err (%v)", err)
return
}
rsc.Size = size.String
rscs = append(rscs, rsc)
}
err = rows.Err()
return
}
// Assignment get assigment from db
func (d *Dao) Assignment(c context.Context) (asgs []*model.Assignment, err error) {
rows, err := d.db.Query(c, _allAssignSQL, time.Now(), time.Now())
if err != nil {
log.Error("d.Assignment query error (%v)", err)
return
}
defer rows.Close()
for rows.Next() {
asg := &model.Assignment{}
if err = rows.Scan(&asg.ID, &asg.Name, &asg.ContractID, &asg.ResID, &asg.Pic, &asg.LitPic,
&asg.URL, &asg.Rule, &asg.Weight, &asg.Agency, &asg.Price, &asg.Atype, &asg.Username); err != nil {
log.Error("Assignment rows.Scan err (%v)", err)
return
}
asg.AsgID = asg.ID
asgs = append(asgs, asg)
}
err = rows.Err()
return
}
// AssignmentNew get resource_assigment from new db
func (d *Dao) AssignmentNew(c context.Context) (asgs []*model.Assignment, err error) {
var (
ok bool
pm map[string]string
)
rows, err := d.db.Query(c, _allAssignNewSQL, time.Now(), time.Now())
if err != nil {
log.Error("d.AssignmentNew query error (%v)", err)
return
}
defer rows.Close()
pm = make(map[string]string)
for rows.Next() {
asg := &model.Assignment{}
if err = rows.Scan(&asg.AsgID, &asg.ID, &asg.Name, &asg.ContractID, &asg.ResID, &asg.Pic, &asg.LitPic,
&asg.URL, &asg.Rule, &asg.Weight, &asg.Agency, &asg.Price, &asg.STime, &asg.ETime, &asg.ApplyGroupID, &asg.CTime, &asg.MTime, &asg.Atype, &asg.Username, &asg.PlayerCategory); err != nil {
log.Error("AssignmentNew rows.Scan err (%v)", err)
return
}
if (asg.ResID == 2054) || (asg.ResID == 2055) || (asg.ResID == 2056) ||
(asg.ResID == 2073) || (asg.ResID == 2074) || (asg.ResID == 2075) ||
(asg.ResID == 1671) || (asg.ResID == 1672) || (asg.ResID == 1673) ||
(asg.ResID == 2315) || (asg.ResID == 2316) || (asg.ResID == 2317) ||
(asg.ResID == 2489) || (asg.ResID == 2490) || (asg.ResID == 2491) ||
(asg.ResID == 2459) || (asg.ResID == 2460) || (asg.ResID == 2461) ||
(asg.ResID == 2469) || (asg.ResID == 2470) || (asg.ResID == 2471) ||
(asg.ResID == 2479) || (asg.ResID == 2480) || (asg.ResID == 2481) ||
(asg.ResID == 2499) || (asg.ResID == 2500) || (asg.ResID == 2501) ||
(asg.ResID == 2606) || (asg.ResID == 2607) || (asg.ResID == 2608) || (asg.ResID == 2609) || (asg.ResID == 2610) ||
(asg.ResID == 2618) || (asg.ResID == 2619) || (asg.ResID == 2620) || (asg.ResID == 2621) || (asg.ResID == 2622) || (asg.ResID == 2623) ||
(asg.ResID == 2556) || (asg.ResID == 2557) || (asg.ResID == 2558) || (asg.ResID == 2559) || (asg.ResID == 2560) ||
(asg.ResID == 2991) || (asg.ResID == 2992) || (asg.ResID == 2993) {
asg.ContractID = "rec_video"
}
pindex := fmt.Sprintf("%d_%d", asg.ResID, asg.Weight)
if _, ok = pm[pindex]; ok {
continue
}
asgs = append(asgs, asg)
pm[pindex] = pindex
}
err = rows.Err()
return
}
// CategoryAssignment get recommend resource_assigment from db
func (d *Dao) CategoryAssignment(c context.Context) (asgs []*model.Assignment, err error) {
rows, err := d.db.Query(c, _categoryAssignSQL, time.Now(), time.Now())
if err != nil {
log.Error("d.CategoryAssignment query error (%v)", err)
return
}
defer rows.Close()
for rows.Next() {
asg := &model.Assignment{}
if err = rows.Scan(&asg.AsgID, &asg.ID, &asg.Name, &asg.ContractID, &asg.ResID, &asg.Pic, &asg.LitPic,
&asg.URL, &asg.Rule, &asg.Weight, &asg.Agency, &asg.Price, &asg.STime, &asg.ETime, &asg.ApplyGroupID, &asg.CTime, &asg.MTime, &asg.Atype, &asg.Username, &asg.PlayerCategory); err != nil {
log.Error("CategoryAssignment rows.Scan err (%v)", err)
return
}
if (asg.ResID == 2048) || (asg.ResID == 2066) || (asg.ResID == 1670) || (asg.ResID == 2308) || (asg.ResID == 2521) || (asg.ResID == 2979) {
asg.ContractID = "rec_video"
}
asgs = append(asgs, asg)
}
err = rows.Err()
return
}
// DefaultBanner get default banner info
func (d *Dao) DefaultBanner(c context.Context) (asg *model.Assignment, err error) {
row := d.db.QueryRow(c, _defBannerSQL)
asg = &model.Assignment{}
if err = row.Scan(&asg.ID, &asg.Name, &asg.ContractID, &asg.ResID, &asg.Pic, &asg.LitPic,
&asg.URL, &asg.Rule, &asg.Weight, &asg.Agency, &asg.Price, &asg.Atype, &asg.Username); err != nil {
if err == sql.ErrNoRows {
asg = nil
err = nil
} else {
log.Error("d.DefaultBanner.Scan error(%v)", err)
}
}
return
}
// IndexIcon get index icon.
func (d *Dao) IndexIcon(c context.Context) (icons map[int][]*model.IndexIcon, err error) {
rows, err := d.db.Query(c, _indexIconSQL)
if err != nil {
log.Error("d.IndexIcon query error (%v)", err)
return
}
defer rows.Close()
icons = make(map[int][]*model.IndexIcon)
for rows.Next() {
var link string
icon := &model.IndexIcon{}
if err = rows.Scan(&icon.ID, &icon.Type, &icon.Title, &icon.State, &link, &icon.Icon,
&icon.Weight, &icon.UserName, &icon.StTime, &icon.EndTime, &icon.DelTime, &icon.CTime, &icon.MTime); err != nil {
log.Error("IndexIcon rows.Scan err (%v)", err)
return
}
icon.Links = strings.Split(link, ",")
icons[icon.Type] = append(icons[icon.Type], icon)
}
err = rows.Err()
return
}
// PlayerIcon get play icon
func (d *Dao) PlayerIcon(c context.Context) (re *model.PlayerIcon, err error) {
row := d.db.QueryRow(c, _playIconSQL, time.Now(), time.Now())
re = &model.PlayerIcon{}
if err = row.Scan(&re.URL1, &re.Hash1, &re.URL2, &re.Hash2, &re.CTime); err != nil {
if err == sql.ErrNoRows {
re = nil
err = nil
} else {
log.Error("d.PlayerIcon.Scan error(%v)", err)
}
}
return
}
// Cmtbox sql live danmaku box
func (d *Dao) Cmtbox(c context.Context) (res map[int64]*model.Cmtbox, err error) {
rows, err := d.db.Query(c, _cmtboxSQL)
if err != nil {
log.Error("d.db.Query error (%v)", err)
return
}
defer rows.Close()
res = make(map[int64]*model.Cmtbox)
for rows.Next() {
re := &model.Cmtbox{}
if err = rows.Scan(&re.ID, &re.LoadCID, &re.Server, &re.Port, &re.SizeFactor, &re.SpeedFactor, &re.MaxOnscreen,
&re.Style, &re.StyleParam, &re.TopMargin, &re.State, &re.CTime, &re.MTime); err != nil {
log.Error("Cmtbox rows.Scan err (%v)", err)
return
}
res[re.ID] = re
}
err = rows.Err()
return
}
// TxOffLine off line resource
func (d *Dao) TxOffLine(tx *xsql.Tx, id int) (row int64, err error) {
res, err := tx.Exec(_updateResourceAssignmentEtime, time.Now(), id)
if err != nil {
log.Error("TxOffLine tx.Exec() error(%v)", err)
return
}
row, err = res.RowsAffected()
return
}
// TxFreeApply free apply
func (d *Dao) TxFreeApply(tx *xsql.Tx, ids []string) (row int64, err error) {
res, err := tx.Exec(fmt.Sprintf(_updateResourceApplyStatus, strings.Join(ids, ",")), model.ApplyNoAssignment)
if err != nil {
log.Error("TxFreeApply tx.Exec() error(%v)", err)
return
}
row, err = res.RowsAffected()
return
}
// TxInResourceLogger add resource log
func (d *Dao) TxInResourceLogger(tx *xsql.Tx, module, content string, oid int) (row int64, err error) {
res, err := tx.Exec(_inResourceLogger, "rejob", 1203, module, oid, content)
if err != nil {
log.Error("TxInResourceLogger tx.Exec() error(%v)", err)
return
}
row, err = res.RowsAffected()
return
}

View File

@@ -0,0 +1,241 @@
package resource
import (
"context"
"database/sql"
"fmt"
"reflect"
"testing"
xsql "go-common/library/database/sql"
"github.com/bouk/monkey"
"github.com/smartystreets/goconvey/convey"
)
func TestResourceResources(t *testing.T) {
convey.Convey("Resources", t, func(ctx convey.C) {
ctx.Convey("When everything is correct", func(ctx convey.C) {
res, err := d.Resources(context.Background())
ctx.Convey("Error should be nil, res should not be empty", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeEmpty)
})
})
ctx.Convey("When db.Query gets error", func(ctx convey.C) {
guard := monkey.PatchInstanceMethod(reflect.TypeOf(d.db), "Query", func(_ *xsql.DB, _ context.Context, _ string, _ ...interface{}) (*xsql.Rows, error) {
return nil, fmt.Errorf("db.Query error")
})
defer guard.Unpatch()
_, err := d.Resources(context.Background())
ctx.Convey("Error should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
})
}
// Set d.close() to get reversal case
func TestResourceAssignment(t *testing.T) {
convey.Convey("Assignment", t, func(ctx convey.C) {
convey.Convey("When everything is correct,", func(ctx convey.C) {
asgs, err := d.Assignment(context.Background())
ctx.Convey("Error should be nil, asgs should not be nil(No Data)", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(asgs, convey.ShouldBeNil)
})
})
convey.Convey("When set db closed", WithReopenDB(func(d *Dao) {
d.Close()
_, err := d.Assignment(context.Background())
convey.Convey("Error should not be nil", func(ctx convey.C) {
convey.So(err, convey.ShouldNotBeNil)
})
}))
})
}
func TestResourceAssignmentNew(t *testing.T) {
convey.Convey("AssignmentNew", t, func(ctx convey.C) {
ctx.Convey("When everything is correct", func(ctx convey.C) {
_, err := d.AssignmentNew(context.Background())
ctx.Convey("Error should be nil, asgs should not be empty(No Data)", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestResourceCategoryAssignment(t *testing.T) {
convey.Convey("CategoryAssignment", t, func(ctx convey.C) {
_, err := d.CategoryAssignment(context.Background())
ctx.Convey("Error should be nil, res should not be empty(No Data)", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
ctx.Convey("When db.Query gets error", func(ctx convey.C) {
guard := monkey.PatchInstanceMethod(reflect.TypeOf(d.db), "Query", func(_ *xsql.DB, _ context.Context, _ string, _ ...interface{}) (*xsql.Rows, error) {
return nil, fmt.Errorf("db.Query error")
})
defer guard.Unpatch()
_, err := d.CategoryAssignment(context.Background())
ctx.Convey("Error should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
})
}
func TestResourceDefaultBanner(t *testing.T) {
convey.Convey("DefaultBanner", t, func(ctx convey.C) {
res, err := d.DefaultBanner(context.Background())
ctx.Convey("Error should be nil, res should not be empty", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeEmpty)
})
})
}
func TestResourceIndexIcon(t *testing.T) {
convey.Convey("IndexIcon", t, func(ctx convey.C) {
ctx.Convey("When everything is correct", func(ctx convey.C) {
_, err := d.IndexIcon(context.Background())
ctx.Convey("Error should be nil, res should not be empty(No Data)", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
ctx.Convey("When db.Query gets error", func(ctx convey.C) {
guard := monkey.PatchInstanceMethod(reflect.TypeOf(d.db), "Query", func(_ *xsql.DB, _ context.Context, _ string, _ ...interface{}) (*xsql.Rows, error) {
return nil, fmt.Errorf("db.Query error")
})
defer guard.Unpatch()
_, err := d.IndexIcon(context.Background())
ctx.Convey("Error should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
})
}
func TestResourcePlayerIcon(t *testing.T) {
convey.Convey("PlayerIcon", t, func(ctx convey.C) {
res, err := d.PlayerIcon(context.Background())
ctx.Convey("Error should be nil, res should not be empty", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeEmpty)
})
})
}
func TestResourceCmtbox(t *testing.T) {
var (
c = context.TODO()
)
convey.Convey("Cmtbox", t, func(ctx convey.C) {
ctx.Convey("When everything is correct", func(ctx convey.C) {
res, err := d.Cmtbox(c)
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)
})
})
ctx.Convey("When db.Query gets error", func(ctx convey.C) {
guard := monkey.PatchInstanceMethod(reflect.TypeOf(d.db), "Query", func(_ *xsql.DB, _ context.Context, _ string, _ ...interface{}) (*xsql.Rows, error) {
return nil, fmt.Errorf("db.Query error")
})
defer guard.Unpatch()
_, err := d.Cmtbox(context.Background())
ctx.Convey("Error should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
})
}
func TestResourceTxOffLine(t *testing.T) {
var (
tx, _ = d.BeginTran(context.TODO())
id = int(0)
)
convey.Convey("TxOffLine", t, func(ctx convey.C) {
ctx.Convey("When everything is correct", func(ctx convey.C) {
row, err := d.TxOffLine(tx, id)
ctx.Convey("Then err should be nil.row should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(row, convey.ShouldNotBeNil)
})
})
ctx.Convey("When tx.Exec gets error", func(ctx convey.C) {
guard := monkey.PatchInstanceMethod(reflect.TypeOf(tx), "Exec", func(_ *xsql.Tx, _ string, _ ...interface{}) (sql.Result, error) {
return nil, fmt.Errorf("tx.Exec error")
})
defer guard.Unpatch()
_, err := d.TxOffLine(tx, id)
ctx.Convey("Then err should be not nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
ctx.Reset(func() {
tx.Rollback()
})
})
}
func TestResourceTxFreeApply(t *testing.T) {
var (
tx, _ = d.BeginTran(context.TODO())
ids = []string{"0", "1"}
)
convey.Convey("TxFreeApply", t, func(ctx convey.C) {
ctx.Convey("When everything is correct", func(ctx convey.C) {
row, err := d.TxFreeApply(tx, ids)
ctx.Convey("Then err should be nil.row should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(row, convey.ShouldNotBeNil)
})
})
ctx.Convey("When tx.Exec gets error", func(ctx convey.C) {
guard := monkey.PatchInstanceMethod(reflect.TypeOf(tx), "Exec", func(_ *xsql.Tx, _ string, _ ...interface{}) (sql.Result, error) {
return nil, fmt.Errorf("tx.Exec error")
})
defer guard.Unpatch()
_, err := d.TxFreeApply(tx, ids)
ctx.Convey("Then err should be not nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
ctx.Reset(func() {
tx.Rollback()
})
})
}
func TestResourceTxInResourceLogger(t *testing.T) {
var (
tx, _ = d.BeginTran(context.TODO())
module = ""
content = ""
oid = int(0)
)
convey.Convey("TxInResourceLogger", t, func(ctx convey.C) {
ctx.Convey("When everyting is correct", func(ctx convey.C) {
row, err := d.TxInResourceLogger(tx, module, content, oid)
ctx.Convey("Then err should be nil.row should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(row, convey.ShouldNotBeNil)
})
})
ctx.Convey("When tx.Exec gets error", func(ctx convey.C) {
guard := monkey.PatchInstanceMethod(reflect.TypeOf(tx), "Exec", func(_ *xsql.Tx, _ string, _ ...interface{}) (sql.Result, error) {
return nil, fmt.Errorf("tx.Exec error")
})
defer guard.Unpatch()
_, err := d.TxInResourceLogger(tx, module, content, oid)
ctx.Convey("Then err should be not nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
ctx.Reset(func() {
tx.Rollback()
})
})
}

View File

@@ -0,0 +1,61 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"audit_test.go",
"card_test.go",
"dao_test.go",
"relate_test.go",
"sidebar_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/resource/conf:go_default_library",
"//library/database/sql:go_default_library",
"//vendor/github.com/bouk/monkey:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"audit.go",
"card.go",
"dao.go",
"relate.go",
"sidebar.go",
],
importpath = "go-common/app/service/main/resource/dao/show",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/resource/conf:go_default_library",
"//app/service/main/resource/model:go_default_library",
"//library/database/sql:go_default_library",
"//library/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,35 @@
package show
import (
"context"
"go-common/library/log"
)
var (
_auditSQL = "SELECT mobi_app,build FROM audit"
)
// Audit get audit.
func (d *Dao) Audit(c context.Context) (res map[string][]int, err error) {
res = make(map[string][]int)
rows, err := d.db.Query(c, _auditSQL)
if err != nil {
log.Error("d.audit error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
var (
mobiApp string
build int
)
if err = rows.Scan(&mobiApp, &build); err != nil {
log.Error("d.audit rows.Scan error(%v)", err)
res = nil
return
}
res[mobiApp] = append(res[mobiApp], build)
}
err = rows.Err()
return
}

View File

@@ -0,0 +1,36 @@
package show
import (
"context"
"fmt"
"reflect"
"testing"
xsql "go-common/library/database/sql"
"github.com/bouk/monkey"
"github.com/smartystreets/goconvey/convey"
)
// TestDaoAudit test audit.
func TestDaoAudit(t *testing.T) {
convey.Convey("Audit", t, func(ctx convey.C) {
ctx.Convey("When everything is correct", func(ctx convey.C) {
res, err := d.Audit(context.Background())
ctx.Convey("Error should be nil, res should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
ctx.Convey("When db.Query gets error", func(ctx convey.C) {
guard := monkey.PatchInstanceMethod(reflect.TypeOf(d.db), "Query", func(_ *xsql.DB, _ context.Context, _ string, _ ...interface{}) (*xsql.Rows, error) {
return nil, fmt.Errorf("db.Query error")
})
defer guard.Unpatch()
_, err := d.Audit(context.Background())
ctx.Convey("Error should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,76 @@
package show
import (
"context"
"strconv"
"time"
"go-common/app/service/main/resource/model"
"go-common/library/log"
)
var (
_appPosRecSQL = "SELECT r.id,r.tab,r.resource_id,r.type,r.title,r.cover,r.re_type,r.re_value,r.plat_ver,r.desc,r.tag_id FROM app_pos_rec AS r WHERE r.stime<? AND r.etime>? AND r.state=1 AND r.resource_id=3 ORDER BY r.weight ASC"
_appContentRSQL = "SELECT c.id,c.module,c.rec_id,c.ctype,c.cvalue,c.ctitle,c.tag_id FROM app_content AS c, app_pos_rec AS r WHERE c.rec_id=r.id AND r.state=1 AND r.stime<? AND r.etime>? AND c.module=1"
)
// PosRecs get pos resrouce
func (d *Dao) PosRecs(c context.Context, now time.Time) (res map[int8][]*model.Card, err error) {
res = map[int8][]*model.Card{}
rows, err := d.db.Query(c, _appPosRecSQL, now, now)
if err != nil {
log.Error("d.PosRecs error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
card := &model.Card{}
if err = rows.Scan(&card.ID, &card.Tab, &card.RegionID, &card.Type, &card.Title, &card.Cover, &card.Rtype, &card.Rvalue, &card.PlatVer, &card.Desc, &card.TagID); err != nil {
log.Error("d.PosRecs rows.Scan error(%v)", err)
res = nil
return
}
for _, limit := range card.CardPlatChange() {
tmpc := &model.Card{}
*tmpc = *card
tmpc.Plat = limit.Plat
tmpc.Build = limit.Build
tmpc.Condition = limit.Condition
tmpc.PlatVer = ""
tmpc.TypeStr = model.GotoDaily
tmpc.Goto = model.GotoDaily
tmpc.Param = tmpc.Rvalue
tmpc.URI = model.FillURI(tmpc.Goto, tmpc.Param)
res[tmpc.Plat] = append(res[tmpc.Plat], tmpc)
}
}
err = rows.Err()
return
}
// RecContents get resource contents
func (d *Dao) RecContents(c context.Context, now time.Time) (res map[int][]*model.Content, aids map[int][]int64, err error) {
res = map[int][]*model.Content{}
aids = map[int][]int64{}
rows, err := d.db.Query(c, _appContentRSQL, now, now)
if err != nil {
log.Error("d.RecContents error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
card := &model.Content{}
if err = rows.Scan(&card.ID, &card.Module, &card.RecID, &card.Type, &card.Value, &card.Title, &card.TagID); err != nil {
log.Error("d.RecContents rows.Scan error(%v)", err)
res = nil
return
}
res[card.RecID] = append(res[card.RecID], card)
if card.Type == model.CardGotoAv {
aidInt, _ := strconv.ParseInt(card.Value, 10, 64)
aids[card.RecID] = append(aids[card.RecID], aidInt)
}
}
err = rows.Err()
return
}

View File

@@ -0,0 +1,59 @@
package show
import (
"context"
"fmt"
"reflect"
"testing"
"time"
xsql "go-common/library/database/sql"
"github.com/bouk/monkey"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoPosRecs(t *testing.T) {
convey.Convey("PosRecs", t, func(ctx convey.C) {
ctx.Convey("When everything is correct", func(ctx convey.C) {
res, err := d.PosRecs(context.Background(), time.Now())
ctx.Convey("Error should be nil, res should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
ctx.Convey("When db.Query gets error", func(ctx convey.C) {
guard := monkey.PatchInstanceMethod(reflect.TypeOf(d.db), "Query", func(_ *xsql.DB, _ context.Context, _ string, _ ...interface{}) (*xsql.Rows, error) {
return nil, fmt.Errorf("db.Query error")
})
defer guard.Unpatch()
_, err := d.PosRecs(context.Background(), time.Now())
ctx.Convey("Error should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoRecContents(t *testing.T) {
convey.Convey("RecContents", t, func(ctx convey.C) {
ctx.Convey("When everything is correct", func() {
res, aids, err := d.RecContents(context.Background(), time.Now())
ctx.Convey("Error should be nil, res, aids should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
ctx.So(aids, convey.ShouldNotBeNil)
})
})
ctx.Convey("When db.Query gets error", func(ctx convey.C) {
guard := monkey.PatchInstanceMethod(reflect.TypeOf(d.db), "Query", func(_ *xsql.DB, _ context.Context, _ string, _ ...interface{}) (*xsql.Rows, error) {
return nil, fmt.Errorf("db.Query error")
})
defer guard.Unpatch()
_, _, err := d.RecContents(context.Background(), time.Now())
ctx.Convey("Error should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,33 @@
package show
import (
"context"
"go-common/app/service/main/resource/conf"
xsql "go-common/library/database/sql"
)
// Dao is resource dao.
type Dao struct {
db *xsql.DB
c *conf.Config
}
// New init mysql db
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
db: xsql.NewMySQL(c.DB.Show),
}
return
}
// Close close the resource.
func (d *Dao) Close() {
d.db.Close()
}
// Ping check dao health.
func (d *Dao) Ping(c context.Context) error {
return d.db.Ping(c)
}

View File

@@ -0,0 +1,48 @@
package show
import (
"context"
"flag"
"os"
"testing"
"go-common/app/service/main/resource/conf"
"github.com/smartystreets/goconvey/convey"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.app-svr.resource-service")
flag.Set("conf_token", "y79sErNhxggjvULS0O8Czas9PaxHBF5o")
flag.Set("tree_id", "3232")
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/resource-service-test.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
m.Run()
os.Exit(0)
}
func TestDaoPing(t *testing.T) {
convey.Convey("Ping", t, func(ctx convey.C) {
err := d.Ping(context.TODO())
ctx.Convey("Err should be nil", func() {
ctx.So(err, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,47 @@
package show
import (
"context"
"encoding/json"
"time"
"go-common/app/service/main/resource/model"
"go-common/library/log"
)
const (
_relateSQL = "SELECT `id`,`param`,`title`,`rec_reason`,`position`,`plat_ver`,`stime`,`etime`,`pgc_ids` FROM app_rcmd_pos WHERE `state`=1 AND `goto`='special' AND `pgc_relation`=1 AND `stime`<? AND `etime`>?"
)
// Relate get all relate rec.
func (d *Dao) Relate(c context.Context, now time.Time) (relates []*model.Relate, err error) {
rows, err := d.db.Query(c, _relateSQL, now, now)
if err != nil {
log.Error("d.Relate.Query error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
r := &model.Relate{}
var verStr string
if err = rows.Scan(&r.ID, &r.Param, &r.Title, &r.RecReason, &r.Position, &verStr, &r.STime, &r.ETime, &r.PgcIDs); err != nil {
log.Error("d.Relate.rows.Scan error(%v)", err)
return
}
if verStr != "" {
var verStruct []*model.Version
if err = json.Unmarshal([]byte(verStr), &verStruct); err != nil {
log.Error("json.Unmarshal(%s) error(%v)", verStr, err)
return
}
vm := make(map[int8][]*model.Version, len(verStruct))
for _, v := range verStruct {
vm[v.Plat] = append(vm[v.Plat], v)
}
r.Versions = vm
}
relates = append(relates, r)
}
err = rows.Err()
return
}

View File

@@ -0,0 +1,20 @@
package show
import (
"context"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoRelate(t *testing.T) {
convey.Convey("Relate", t, func(ctx convey.C) {
ctx.Convey("When everything is correct", func(ctx convey.C) {
_, err := d.Relate(context.Background(), time.Now())
ctx.Convey("Error should be nil, res should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,43 @@
package show
import (
"context"
"time"
"go-common/app/service/main/resource/model"
"go-common/library/log"
)
const (
_selSideSQL = `SELECT s.id,s.plat,s.module,s.name,s.logo,s.logo_white,s.param,s.rank,l.build,l.conditions,s.tip,s.need_login,s.white_url,s.logo_selected,s.tab_id,s.red_dot_url,lang.name FROM
sidebar AS s,sidebar_limit AS l,language AS lang WHERE s.state=1 AND s.id=l.s_id AND lang.id=s.lang_id AND s.online_time<? ORDER BY s.rank DESC,l.id ASC`
)
// SideBar get side bar.
func (d *Dao) SideBar(ctx context.Context, now time.Time) (ss []*model.SideBar, limits map[int64][]*model.SideBarLimit, err error) {
rows, err := d.db.Query(ctx, _selSideSQL, now)
if err != nil {
log.Error("d.db.Query error(%v)", err)
return
}
defer rows.Close()
limits = make(map[int64][]*model.SideBarLimit)
for rows.Next() {
s := &model.SideBar{}
if err = rows.Scan(&s.ID, &s.Plat, &s.Module, &s.Name, &s.Logo, &s.LogoWhite, &s.Param, &s.Rank, &s.Build, &s.Conditions, &s.Tip, &s.NeedLogin, &s.WhiteURL, &s.LogoSelected, &s.TabID, &s.Red, &s.Language); err != nil {
log.Error("row.Scan error(%v)", err)
return
}
if _, ok := limits[s.ID]; !ok {
ss = append(ss, s)
}
limit := &model.SideBarLimit{
ID: s.ID,
Build: s.Build,
Condition: s.Conditions,
}
limits[s.ID] = append(limits[s.ID], limit)
}
err = rows.Err()
return
}

View File

@@ -0,0 +1,36 @@
package show
import (
"context"
"fmt"
"reflect"
"testing"
"time"
xsql "go-common/library/database/sql"
"github.com/bouk/monkey"
"github.com/smartystreets/goconvey/convey"
)
// Test_SideBar test dao side bar
func TestDaoSideBar(t *testing.T) {
convey.Convey("SidebBar", t, func(ctx convey.C) {
ctx.Convey("When everyting is correct", func(ctx convey.C) {
_, _, err := d.SideBar(context.Background(), time.Now())
ctx.Convey("Error should be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
ctx.Convey("When db.Query gets error", func(ctx convey.C) {
guard := monkey.PatchInstanceMethod(reflect.TypeOf(d.db), "Query", func(_ *xsql.DB, _ context.Context, _ string, _ ...interface{}) (*xsql.Rows, error) {
return nil, fmt.Errorf("db.Query error")
})
defer guard.Unpatch()
_, _, err := d.SideBar(context.Background(), time.Now())
ctx.Convey("Error should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
})
}