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,50 @@
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"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//app/service/main/resource/model:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["abtest.go"],
importpath = "go-common/app/interface/main/app-resource/service/abtest",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//app/interface/main/app-resource/dao/abtest:go_default_library",
"//app/interface/main/app-resource/model/experiment:go_default_library",
"//app/service/main/resource/model: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,128 @@
package abtest
import (
"context"
"time"
"go-common/app/interface/main/app-resource/conf"
expdao "go-common/app/interface/main/app-resource/dao/abtest"
"go-common/app/interface/main/app-resource/model/experiment"
"go-common/app/service/main/resource/model"
"go-common/library/log"
farm "github.com/dgryski/go-farm"
)
var (
_emptyExperiment = []*experiment.Experiment{}
_defaultExperiment = map[int8][]*experiment.Experiment{
model.PlatAndroid: []*experiment.Experiment{
&experiment.Experiment{
ID: 10,
Name: "默认值",
Strategy: "default_value",
Desc: "默认值为不匹配处理",
TrafficGroup: "0",
},
},
}
)
type Service struct {
dao *expdao.Dao
// tick
tick time.Duration
epm map[int8][]*experiment.Experiment
c *conf.Config
}
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
dao: expdao.New(c),
// tick
tick: time.Duration(c.Tick),
epm: map[int8][]*experiment.Experiment{},
}
s.loadAbTest()
go s.tickproc()
return
}
// TemporaryABTests 临时的各种abtest垃圾需求
func (s *Service) TemporaryABTests(c context.Context, buvid string) (tests *experiment.ABTestV2) {
id := farm.Hash32([]byte(buvid))
n := int(id % 100)
autoPlay := 1
if n > s.c.ABTest.Range {
autoPlay = 2
}
tests = &experiment.ABTestV2{
AutoPlay: autoPlay,
}
return
}
func (s *Service) Experiment(c context.Context, plat int8, build int) (eps []*experiment.Experiment) {
if es, ok := s.epm[plat]; ok {
LOOP:
for _, ep := range es {
for _, l := range ep.Limit {
if model.InvalidBuild(build, l.Build, l.Condition) {
continue LOOP
}
}
eps = append(eps, ep)
}
}
if eps == nil {
if es, ok := _defaultExperiment[plat]; ok {
eps = es
} else {
eps = _emptyExperiment
}
}
return
}
// tickproc tick load cache.
func (s *Service) tickproc() {
for {
time.Sleep(s.tick)
s.loadAbTest()
}
}
func (s *Service) loadAbTest() {
c := context.TODO()
lm, err := s.dao.ExperimentLimit(c)
if err != nil {
log.Error("s.dao.ExperimentLimit error(%v)", err)
return
}
ids := make([]int64, 0, len(lm))
for id := range lm {
ids = append(ids, id)
}
if len(ids) == 0 {
return
}
eps, err := s.dao.ExperimentByIDs(c, ids)
if err != nil {
log.Error("s.dao.ExperimentByIDs(%v) error(%v)", ids, err)
return
}
epm := make(map[int8][]*experiment.Experiment, len(eps))
for _, ep := range eps {
if l, ok := lm[ep.ID]; ok {
ep.Limit = l
}
epm[ep.Plat] = append(epm[ep.Plat], ep)
}
s.epm = epm
}
// AbServer is
func (s *Service) AbServer(c context.Context, buvid, device, mobiAPP, filteredStr string, build int, mid int64) (a interface{}, err error) {
return s.dao.AbServer(c, buvid, device, mobiAPP, filteredStr, build, mid)
}

View File

@@ -0,0 +1,43 @@
package abtest
import (
"context"
"encoding/json"
"flag"
"fmt"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/app-resource/conf"
"go-common/app/service/main/resource/model"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-resource-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestExperiment(t *testing.T) {
Convey("get Experiment data", t, WithService(func(s *Service) {
res := s.Experiment(context.TODO(), model.PlatAndroid, 100)
result, _ := json.Marshal(res)
fmt.Printf("test Experiment (%v) \n", string(result))
So(res, ShouldNotBeEmpty)
}))
}

View File

@@ -0,0 +1,47 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["audit_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["audit.go"],
importpath = "go-common/app/interface/main/app-resource/service/audit",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//app/interface/main/app-resource/dao/audit:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,61 @@
package audit
import (
"context"
"time"
"go-common/app/interface/main/app-resource/conf"
auditdao "go-common/app/interface/main/app-resource/dao/audit"
"go-common/library/ecode"
"go-common/library/log"
)
// Service audit service.
type Service struct {
dao *auditdao.Dao
// tick
tick time.Duration
// cache
auditCache map[string]map[int]struct{}
}
// New new a audit service.
func New(c *conf.Config) (s *Service) {
s = &Service{
dao: auditdao.New(c),
// tick
tick: time.Duration(c.Tick),
// cache
auditCache: map[string]map[int]struct{}{},
}
s.loadAuditCache()
go s.cacheproc()
return
}
// Audit
func (s *Service) Audit(c context.Context, mobiApp string, build int) (err error) {
if plats, ok := s.auditCache[mobiApp]; ok {
if _, ok = plats[build]; ok {
return ecode.OK
}
}
return ecode.NotModified
}
// cacheproc load all cache.
func (s *Service) cacheproc() {
for {
time.Sleep(s.tick)
s.loadAuditCache()
}
}
func (s *Service) loadAuditCache() {
as, err := s.dao.Audits(context.TODO())
if err != nil {
log.Error("s.dao.Audits error(%v)", err)
return
}
s.auditCache = as
}

View File

@@ -0,0 +1,38 @@
package audit
import (
"context"
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/app-resource/conf"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-resource-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestAudit(t *testing.T) {
Convey("get Audit data", t, WithService(func(s *Service) {
err := s.Audit(context.TODO(), "", 1)
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,50 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["broadcast_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//app/interface/main/app-resource/model:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["broadcast.go"],
importpath = "go-common/app/interface/main/app-resource/service/broadcast",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//app/interface/main/app-resource/dao/broadcast:go_default_library",
"//app/interface/main/app-resource/model:go_default_library",
"//app/interface/main/app-resource/model/broadcast:go_default_library",
"//app/service/main/broadcast/api/grpc/v1: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,61 @@
package broadcast
import (
"context"
"go-common/app/interface/main/app-resource/conf"
broaddao "go-common/app/interface/main/app-resource/dao/broadcast"
"go-common/app/interface/main/app-resource/model"
"go-common/app/interface/main/app-resource/model/broadcast"
warden "go-common/app/service/main/broadcast/api/grpc/v1"
"go-common/library/log"
)
type Service struct {
c *conf.Config
dao *broaddao.Dao
}
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
dao: broaddao.New(c),
}
return
}
// ServerList warden server list
func (s *Service) ServerList(c context.Context, plat int8) (res *broadcast.ServerListReply, err error) {
var (
data *warden.ServerListReply
platform string
)
if model.IsIOS(plat) {
platform = "ios"
} else if model.IsAndroid(plat) {
platform = "android"
}
if data, err = s.dao.ServerList(c, platform); err != nil {
log.Error("ServerList s.dao.ServerList error(%v)", err)
err = nil
res = &broadcast.ServerListReply{
Domain: "broadcast.chat.bilibili.com",
TCPPort: 7821,
WsPort: 7822,
WssPort: 7823,
Heartbeat: 30,
HeartbeatMax: 3,
Nodes: []string{"broadcast.chat.bilibili.com"},
Backoff: &broadcast.Backoff{
MaxDelay: 120,
BaseDelay: 3,
Factor: 1.6,
Jitter: 0.2,
},
}
return
}
res = &broadcast.ServerListReply{}
res.ServerListChange(data)
return
}

View File

@@ -0,0 +1,40 @@
package broadcast
import (
"context"
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/app-resource/conf"
"go-common/app/interface/main/app-resource/model"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-resource-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestServerList(t *testing.T) {
Convey("get ServerList data", t, WithService(func(s *Service) {
res, err := s.ServerList(context.Background(), model.PlatAndroid)
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,45 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["domain_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["domain.go"],
importpath = "go-common/app/interface/main/app-resource/service/domain",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//app/interface/main/app-resource/model/domain: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,29 @@
package domain
import (
"go-common/app/interface/main/app-resource/conf"
"go-common/app/interface/main/app-resource/model/domain"
)
// Service domain service.
type Service struct {
c *conf.Config
domains []string
}
// New new domain service.
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
}
return
}
// Domain get domain all
func (s *Service) Domain() (res *domain.Domain) {
res = &domain.Domain{
Domains: s.c.Domain.Addr,
ImageDomains: s.c.Domain.ImageAddr,
}
return
}

View File

@@ -0,0 +1,41 @@
package domain
import (
"encoding/json"
"flag"
"fmt"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/app-resource/conf"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-resource-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestDomain(t *testing.T) {
Convey("get Domain data", t, WithService(func(s *Service) {
res := s.Domain()
result, _ := json.Marshal(res)
fmt.Printf("test Domain (%v) \n", string(result))
So(res, ShouldNotBeEmpty)
}))
}

View File

@@ -0,0 +1,47 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["guide_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["guide.go"],
importpath = "go-common/app/interface/main/app-resource/service/guide",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//app/interface/main/app-resource/model/guide:go_default_library",
"//library/log:go_default_library",
"//library/log/infoc: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,116 @@
package guide
import (
"encoding/json"
"hash/crc32"
"io/ioutil"
"os"
"strconv"
"time"
"go-common/app/interface/main/app-resource/conf"
"go-common/app/interface/main/app-resource/model/guide"
"go-common/library/log"
"go-common/library/log/infoc"
)
var (
_emptyinterest = []*guide.Interest{}
)
// Service interest service.
type Service struct {
c *conf.Config
cache []*guide.Interest
interestPath string
// infoc
logCh chan interface{}
inf2 *infoc.Infoc
}
// New new a interest service.
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
cache: []*guide.Interest{},
interestPath: c.InterestJSONFile,
// infoc
logCh: make(chan interface{}, 1024),
inf2: infoc.New(c.InterestInfoc),
}
s.loadInterestJSON()
return
}
// Interest buvid or time gray
func (s *Service) Interest(mobiApp, buvid string, now time.Time) (res []*guide.Interest) {
res = s.cache
// if buvid != "" && mobiApp == "android" {
// if crc32.ChecksumIEEE([]byte(reverseString(buvid)))%5 < 2 {
// log.Info("interest_buvid_miss")
// res = _emptyinterest
// return
// }
// }
if len(res) == 0 {
log.Info("interest_null")
res = _emptyinterest
return
}
log.Info("interest_hit")
return
}
// Interest2 is
func (s *Service) Interest2(mobiApp, device, deviceid, buvid string, build int, now time.Time) (res *guide.InterestTM) {
res = &guide.InterestTM{}
// switch group := int(crc32.ChecksumIEEE([]byte(buvid)) % 20); group {
// case 9, 18:
// res = &guide.InterestTM{
// Interests: s.cache,
// }
// }
id := crc32.ChecksumIEEE([]byte(reverseString(buvid))) % 100
if id < 5 {
res.FeedType = 1
}
switch mobiApp {
case "iphone_b", "android_b":
res.FeedType = 0
}
//infoc
b, _ := json.Marshal(&s.cache)
s.inf2.Info(mobiApp, device, strconv.Itoa(build), buvid, deviceid, now.Format("2006-01-02 15:04:05"), strconv.Itoa(res.FeedType), string(b))
log.Info("interest_infoc_index(%s,%s,%s,%s,%s,%s,%s)_list(%s)", mobiApp, device, strconv.Itoa(build), buvid, deviceid,
now.Format("2006-01-02 15:04:05"), strconv.Itoa(res.FeedType), string(b))
return
}
func reverseString(s string) string {
runes := []rune(s)
for from, to := 0, len(runes)-1; from < to; from, to = from+1, to-1 {
runes[from], runes[to] = runes[to], runes[from]
}
return string(runes)
}
// loadInterestJSON load interest json
func (s *Service) loadInterestJSON() {
file, err := os.Open(s.interestPath)
if err != nil {
log.Error("os.Open(%s) error(%v)", s.interestPath, err)
return
}
defer file.Close()
bs, err := ioutil.ReadAll(file)
if err != nil {
log.Error("ioutil.ReadAll err %v", err)
return
}
res := []*guide.Interest{}
if err = json.Unmarshal(bs, &res); err != nil {
log.Error("json.Unmarshal() file(%s) error(%v)", s.interestPath, err)
}
s.cache = res
log.Info("loadInterestJSON success")
}

View File

@@ -0,0 +1,50 @@
package guide
import (
"encoding/json"
"flag"
"fmt"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/app-resource/conf"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-resource-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestGuide(t *testing.T) {
Convey("get guide data", t, WithService(func(s *Service) {
res := s.Interest("iphone", "", time.Now())
result, _ := json.Marshal(res)
fmt.Printf("test guide (%v) \n", string(result))
So(res, ShouldNotBeEmpty)
}))
}
func Test_Guide2(t *testing.T) {
Convey("Guide2", t, WithService(func(s *Service) {
res := s.Interest2("ssss11", "ssss11", "ssss11", "ssss11", 1, time.Now())
result, _ := json.Marshal(res)
Printf("test guide (%v) \n", string(result))
So(res, ShouldNotBeEmpty)
}))
}

View File

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

View File

@@ -0,0 +1,395 @@
package module
import (
"context"
"strconv"
"strings"
"time"
"go-common/app/interface/main/app-resource/conf"
moduledao "go-common/app/interface/main/app-resource/dao/module"
"go-common/app/interface/main/app-resource/model/module"
"go-common/library/ecode"
"go-common/library/log"
)
var (
_emptylist = []*module.ResourcePool{}
)
// Service module service.
type Service struct {
dao *moduledao.Dao
tick time.Duration
resourceCache map[string]*module.ResourcePool
conditionsCache map[int]*module.Condition
}
// New new a module service.
func New(c *conf.Config) (s *Service) {
s = &Service{
dao: moduledao.New(c),
tick: time.Duration(c.Tick),
resourceCache: map[string]*module.ResourcePool{},
conditionsCache: make(map[int]*module.Condition),
}
s.loadCache()
go s.loadproc()
return
}
func (s *Service) FormCondition(versions []*module.Versions) (res map[string]map[string]int) {
res = make(map[string]map[string]int)
for _, pools := range versions {
var (
re map[string]int
ok bool
)
for _, resource := range pools.Resource {
if re, ok = res[pools.PoolName]; !ok {
re = make(map[string]int)
res[pools.PoolName] = re
}
var tmpVer int
switch tmp := resource.Version.(type) {
case string:
tmpVer, _ = strconv.Atoi(tmp)
case float64:
tmpVer = int(tmp)
}
re[resource.ResourceName] = tmpVer
}
}
return
}
// List get All or by poolname
func (s *Service) List(c context.Context, mobiApp, device, platform, poolName, env string, build, sysver, level, scale, arch int,
versions []*module.Versions, now time.Time) (res []*module.ResourcePool) {
var (
resTmp []*module.ResourcePool
versionsMap = s.FormCondition(versions)
)
if poolName != "" {
if pool, ok := s.resourceCache[poolName]; ok {
resTmp = append(resTmp, pool)
}
} else {
for _, l := range s.resourceCache {
resTmp = append(resTmp, l)
}
}
if len(resTmp) == 0 {
res = _emptylist
return
}
for _, resPool := range resTmp {
var (
existRes = map[string]*module.Resource{}
existResTotal = map[string]struct{}{}
resPoolTmp = &module.ResourcePool{Name: resPool.Name}
ok bool
)
for _, re := range resPool.Resources {
if re == nil {
continue
}
if !s.checkCondition(c, mobiApp, device, platform, env, build, sysver, level, scale, arch, re.Condition, now) {
continue
}
var t *module.Resource
if _, ok = existResTotal[re.Name]; ok {
continue
}
if t, ok = existRes[re.Name]; ok {
if re.Increment == module.Total {
tmp := &module.Resource{}
*tmp = *t
tmp.TotalMD5 = re.MD5
existResTotal[tmp.Name] = struct{}{}
resPoolTmp.Resources = append(resPoolTmp.Resources, tmp)
continue
}
} else {
var (
resVer map[string]int
ver int
)
if resVer, ok = versionsMap[resPool.Name]; ok {
if ver, ok = resVer[re.Name]; ok {
if re.Increment == module.Incremental && re.FromVer != ver {
continue
}
} else if !ok && re.Increment == module.Incremental {
continue
}
} else if !ok && re.Increment == module.Incremental {
continue
}
tmp := &module.Resource{}
*tmp = *re
existRes[tmp.Name] = tmp
if re.Increment == module.Total {
tmp.TotalMD5 = re.MD5
existResTotal[tmp.Name] = struct{}{}
resPoolTmp.Resources = append(resPoolTmp.Resources, tmp)
}
}
}
if len(resPoolTmp.Resources) == 0 {
continue
}
res = append(res, resPoolTmp)
}
return
}
// Resource get by poolname and resourcename
func (s *Service) Resource(c context.Context, mobiApp, device, platform, poolName, resourceName, env string,
ver, build, sysver, level, scale, arch int, now time.Time) (res *module.Resource, err error) {
if resPoolTmp, ok := s.resourceCache[poolName]; ok {
if resPoolTmp == nil {
err = ecode.NothingFound
return
}
var (
resTmp *module.Resource
existRes = map[string]struct{}{}
)
for _, resTmp = range resPoolTmp.Resources {
if resTmp == nil {
continue
}
if resTmp != nil && resTmp.Name == resourceName {
if !s.checkCondition(c, mobiApp, device, platform, env, build, sysver, level, scale, arch, resTmp.Condition, now) {
continue
}
if ver == 0 {
if resTmp.Increment == module.Incremental {
continue
}
} else {
if resTmp.Increment == module.Incremental && resTmp.FromVer != ver {
continue
}
}
if resTmp.Increment == module.Total && resTmp.Version == ver {
err = ecode.NotModified
break
}
if _, ok := existRes[resTmp.Name]; !ok {
res = &module.Resource{}
*res = *resTmp
existRes[resTmp.Name] = struct{}{}
}
if resTmp.Increment == module.Total && res != nil {
res.TotalMD5 = resTmp.MD5
break
}
}
}
}
if err != nil {
return
}
if res == nil {
err = ecode.NothingFound
}
return
}
func (s *Service) checkCondition(c context.Context, mobiApp, device, platform, env string, build, sysver, level, scale, arch int, condition *module.Condition, now time.Time) bool {
if condition == nil {
return true
}
if env == module.EnvRelease && condition.Valid == 0 {
return false
} else if env == module.EnvTest && condition.ValidTest == 0 {
return false
} else if env == module.EnvDefault && condition.Default != 1 {
return false
}
if !condition.STime.Time().IsZero() && now.Unix() < int64(condition.STime) {
return false
}
if !condition.ETime.Time().IsZero() && now.Unix() > int64(condition.ETime) {
return false
}
NETX:
for column, cv := range condition.Columns {
switch column {
case "plat": // whith list
for _, v := range cv {
if strings.TrimSpace(v.Value) == platform {
continue NETX
}
}
return false
case "mobi_app": // whith list
for _, v := range cv {
if strings.TrimSpace(v.Value) == mobiApp {
continue NETX
}
}
return false
case "device": // blace list
for _, v := range cv {
if strings.TrimSpace(v.Value) == device {
return false
}
}
case "build": // build < lt gt > build ge >= build, le <= build
for _, v := range cv {
value, _ := strconv.Atoi(strings.TrimSpace(v.Value))
if invalidModelBuild(build, value, v.Condition) {
return false
}
}
case "sysver":
if sysver > 0 {
for _, v := range cv {
value, _ := strconv.Atoi(strings.TrimSpace(v.Value))
if invalidModelBuild(sysver, value, v.Condition) {
return false
}
}
}
case "scale": // whith list
if scale > 0 {
for _, v := range cv {
value, _ := strconv.Atoi(strings.TrimSpace(v.Value))
if value == scale {
continue NETX
}
}
return false
}
case "arch": // whith list
if arch > 0 {
for _, v := range cv {
value, _ := strconv.Atoi(strings.TrimSpace(v.Value))
if value == arch {
continue NETX
}
}
return false
}
}
}
return true
}
// ModuleUpdateCache update module cache
func (s *Service) ModuleUpdateCache() (err error) {
err = s.loadCache()
return
}
// load update cache
func (s *Service) loadCache() (err error) {
configsTmp, err := s.dao.ResourceConfig(context.TODO())
if err != nil {
log.Error("s.dao.ResourceConfig error(%v)", err)
return
}
limitTmp, err := s.dao.ResourceLimit(context.TODO())
if err != nil {
log.Error("s.dao.ResourceLimit error(%v)", err)
return
}
for _, config := range configsTmp {
if limit, ok := limitTmp[config.ID]; ok {
config.Columns = limit
}
}
s.conditionsCache = configsTmp
log.Info("module conditions success")
tmpResourceDev, err := s.dao.ModuleDev(context.TODO())
if err != nil {
log.Error("s.dao.ModuleDev error(%v)", err)
return
}
tmpResources, err := s.dao.ModuleAll(context.TODO())
if err != nil {
log.Error("s.dao.ModuleAll error(%v)", err)
return
}
tmpResourcePoolCaches := map[string]*module.ResourcePool{}
for _, resPool := range tmpResourceDev {
if resPool == nil {
continue
}
var tmpResourcePoolCache = &module.ResourcePool{ID: resPool.ID, Name: resPool.Name}
for _, res := range resPool.Resources {
if res == nil {
continue
}
if re, ok := tmpResources[res.ID]; ok {
var tmpre []*module.Resource
for _, r := range re {
if r.URL == "" || r.MD5 == "" {
continue
}
if c, ok := s.conditionsCache[r.ResID]; ok {
r.Condition = c
// all level
if c != nil {
for column, cv := range c.Columns {
switch column {
case "level":
for _, v := range cv {
value, _ := strconv.Atoi(strings.TrimSpace(v.Value))
r.Level = value
}
}
}
}
r.IsWifi = c.IsWifi
}
tmpre = append(tmpre, r)
}
if len(tmpre) == 0 {
continue
}
tmpResourcePoolCache.Resources = append(tmpResourcePoolCache.Resources, tmpre...)
}
}
tmpResourcePoolCaches[resPool.Name] = tmpResourcePoolCache
}
s.resourceCache = tmpResourcePoolCaches
log.Info("module resources success")
return
}
// cacheproc load cache data
func (s *Service) loadproc() {
for {
time.Sleep(s.tick)
s.loadCache()
}
}
// invalidModelBuild model build
func invalidModelBuild(srcBuild, cfgBuild int, cfgCond string) bool {
if cfgBuild != 0 && cfgCond != "" {
switch cfgCond {
case "lt":
if cfgBuild <= srcBuild {
return true
}
case "le":
if cfgBuild < srcBuild {
return true
}
case "ge":
if cfgBuild > srcBuild {
return true
}
case "gt":
if cfgBuild >= srcBuild {
return true
}
}
}
return false
}

View File

@@ -0,0 +1,53 @@
package module
import (
"context"
"encoding/json"
"flag"
"fmt"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/app-resource/conf"
"go-common/app/interface/main/app-resource/model/module"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-resource-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestList(t *testing.T) {
Convey("get list data", t, WithService(func(s *Service) {
res := s.List(context.TODO(), "iphone", "phone", "ios", "resourcefile", "1", 4500, 0, 0, 0, 0, []*module.Versions{}, time.Now())
result, _ := json.Marshal(res)
fmt.Printf("test list (%v) \n", string(result))
So(res, ShouldNotBeEmpty)
}))
}
func TestResource(t *testing.T) {
Convey("get Resource data", t, WithService(func(s *Service) {
res, err := s.Resource(context.TODO(), "iphone", "phone", "ios", "resourcefile", "我的测试包222", "1", 21, 3500, 0, 0, 0, 0, time.Now())
result, _ := json.Marshal(res)
fmt.Printf("test Resource (%v) \n", string(result))
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}

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 = ["notice_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//app/interface/main/app-resource/model:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["notice.go"],
importpath = "go-common/app/interface/main/app-resource/service/notice",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//app/interface/main/app-resource/dao/location:go_default_library",
"//app/interface/main/app-resource/dao/notice:go_default_library",
"//app/interface/main/app-resource/model:go_default_library",
"//app/interface/main/app-resource/model/notice:go_default_library",
"//app/service/main/location/model:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/metadata: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,136 @@
package notice
import (
"context"
"encoding/json"
"fmt"
"strconv"
"strings"
"time"
"go-common/app/interface/main/app-resource/conf"
locdao "go-common/app/interface/main/app-resource/dao/location"
ntcdao "go-common/app/interface/main/app-resource/dao/notice"
"go-common/app/interface/main/app-resource/model"
"go-common/app/interface/main/app-resource/model/notice"
locmdl "go-common/app/service/main/location/model"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/metadata"
"github.com/dgryski/go-farm"
)
const (
_initNoticeKey = "notice_key_%d_%d"
_initNoticeVer = "notice_version"
)
var (
_emptyNotice = &notice.Notice{}
)
// Service notice service.
type Service struct {
dao *ntcdao.Dao
loc *locdao.Dao
// tick
tick time.Duration
// cache
cache map[string][]*notice.Notice
}
// New new a notice service.
func New(c *conf.Config) (s *Service) {
s = &Service{
dao: ntcdao.New(c),
loc: locdao.New(c),
// tick
tick: time.Duration(c.Tick),
// cache
cache: map[string][]*notice.Notice{},
}
s.load(time.Now())
go s.loadproc()
return
}
// Notice return Notice to json
func (s *Service) Notice(c context.Context, plat int8, build, typeInt int, ver string) (res *notice.Notice, version string, err error) {
var (
ip = metadata.String(c, metadata.RemoteIP)
pids []string
auths map[string]*locmdl.Auth
)
for _, ntc := range s.cache[fmt.Sprintf(_initNoticeKey, plat, typeInt)] {
if model.InvalidBuild(build, ntc.Build, ntc.Condition) {
continue
}
if ntc.Area != "" {
pids = append(pids, ntc.Area)
}
}
if len(pids) > 0 {
auths, _ = s.loc.AuthPIDs(c, strings.Join(pids, ","), ip)
}
for _, ntc := range s.cache[fmt.Sprintf(_initNoticeKey, plat, typeInt)] {
if model.InvalidBuild(build, ntc.Build, ntc.Condition) {
continue
}
if auth, ok := auths[ntc.Area]; ok && auth.Play == locmdl.Forbidden {
log.Warn("s.invalid area(%v) ip(%v) error(%v)", ntc.Area, ip, err)
continue
}
res = ntc
break
}
if res == nil {
res = _emptyNotice
}
if version = s.hash(res); ver == version {
err = ecode.NotModified
res = nil
}
return
}
// load
func (s *Service) load(now time.Time) {
// get notice
ntcs, err := s.dao.All(context.TODO(), now)
if err != nil {
log.Error("s.dao.GetAll() error(%v)", err)
return
}
// copy cache
tmp := map[string][]*notice.Notice{}
for _, v := range ntcs {
key := fmt.Sprintf(_initNoticeKey, v.Plat, v.Type)
tmp[key] = append(tmp[key], v)
}
s.cache = tmp
log.Info("notice cacheproc success")
}
func (s *Service) hash(v *notice.Notice) string {
bs, err := json.Marshal(v)
if err != nil {
log.Error("json.Marshal error(%v)", err)
return _initNoticeVer
}
return strconv.FormatUint(farm.Hash64(bs), 10)
}
// cacheproc load cache data
func (s *Service) loadproc() {
for {
time.Sleep(s.tick)
s.load(time.Now())
}
}
// Close dao
func (s *Service) Close() {
s.dao.Close()
}

View File

@@ -0,0 +1,40 @@
package notice
import (
"context"
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/app-resource/conf"
"go-common/app/interface/main/app-resource/model"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-resource-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestNotice(t *testing.T) {
Convey("get Notice data", t, WithService(func(s *Service) {
res, _, err := s.Notice(context.TODO(), model.PlatIPhone, 1, 1, "")
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,51 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["param_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//app/interface/main/app-resource/model:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["param.go"],
importpath = "go-common/app/interface/main/app-resource/service/param",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//app/interface/main/app-resource/dao/param:go_default_library",
"//app/interface/main/app-resource/model:go_default_library",
"//app/interface/main/app-resource/model/param:go_default_library",
"//library/ecode: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,104 @@
package param
import (
"context"
"encoding/json"
"fmt"
"strconv"
"time"
"go-common/app/interface/main/app-resource/conf"
"go-common/app/interface/main/app-resource/dao/param"
"go-common/app/interface/main/app-resource/model"
mparam "go-common/app/interface/main/app-resource/model/param"
"go-common/library/ecode"
"go-common/library/log"
farm "github.com/dgryski/go-farm"
)
const (
_initVersion = "param_version"
_platKey = "param_%d"
)
// Service param service.
type Service struct {
dao *param.Dao
tick time.Duration
// model param cache
cache map[string][]*mparam.Param
}
// New new a param service.
func New(c *conf.Config) (s *Service) {
s = &Service{
dao: param.New(c),
tick: time.Duration(c.Tick),
cache: map[string][]*mparam.Param{},
}
s.load()
go s.loadproc()
return
}
// Param return param to string
func (s *Service) Param(plat int8, build int, ver string) (res map[string]string, version string, err error) {
res, version, err = s.getCache(plat, build, ver)
return
}
func (s *Service) getCache(plat int8, build int, ver string) (res map[string]string, version string, err error) {
var (
pk = fmt.Sprintf(_platKey, plat)
)
res = map[string]string{}
for _, p := range s.cache[pk] {
if model.InvalidBuild(build, p.Build, p.Condition) {
continue
}
res[p.Name] = p.Value
}
if version = s.hash(res); version == ver {
err = ecode.NotModified
res = nil
}
return
}
func (s *Service) load() {
tmp, err := s.dao.All(context.TODO())
if err != nil {
log.Error("param s.dao.All() error(%v)", err)
return
}
s.cache = tmp
log.Info("param cacheproc success")
}
// cacheproc load cache data
func (s *Service) loadproc() {
for {
time.Sleep(s.tick)
s.load()
}
}
func (s *Service) hash(v map[string]string) string {
bs, err := json.Marshal(v)
if err != nil {
log.Error("json.Marshal error(%v)", err)
return _initVersion
}
return strconv.FormatUint(farm.Hash64(bs), 10)
}
// key get banner cache key.
func (s *Service) key(plat int8, build int) string {
return fmt.Sprintf("%d_%d", plat, build)
}
// Close dao
func (s *Service) Close() {
s.dao.Close()
}

View File

@@ -0,0 +1,39 @@
package param
import (
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/app-resource/conf"
"go-common/app/interface/main/app-resource/model"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-resource-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestParam(t *testing.T) {
Convey("get Param data", t, WithService(func(s *Service) {
res, _, err := s.Param(model.PlatIPhone, 1, "")
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,45 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["ping_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["ping.go"],
importpath = "go-common/app/interface/main/app-resource/service/ping",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//app/interface/main/app-resource/dao/plugin: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,23 @@
package ping
import (
"context"
"go-common/app/interface/main/app-resource/conf"
pgdao "go-common/app/interface/main/app-resource/dao/plugin"
)
type Service struct {
pgDao *pgdao.Dao
}
func New(c *conf.Config) (s *Service) {
s = &Service{
pgDao: pgdao.New(c),
}
return
}
func (s *Service) Ping(c context.Context) (err error) {
return s.pgDao.PingDB(c)
}

View File

@@ -0,0 +1,38 @@
package ping
import (
"context"
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/app-resource/conf"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-resource-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestPing(t *testing.T) {
Convey("get Ping data", t, WithService(func(s *Service) {
err := s.Ping(context.TODO())
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,47 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["plugin_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["plugin.go"],
importpath = "go-common/app/interface/main/app-resource/service/plugin",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//app/interface/main/app-resource/dao/plugin:go_default_library",
"//app/interface/main/app-resource/model/plugin: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,67 @@
package plugin
import (
"context"
"sort"
"time"
"go-common/app/interface/main/app-resource/conf"
pgdao "go-common/app/interface/main/app-resource/dao/plugin"
"go-common/app/interface/main/app-resource/model/plugin"
"go-common/library/log"
)
type Service struct {
pgDao *pgdao.Dao
tick time.Duration
pluginCache map[string][]*plugin.Plugin
}
func New(c *conf.Config) (s *Service) {
s = &Service{
pgDao: pgdao.New(c),
tick: time.Duration(c.Tick),
pluginCache: map[string][]*plugin.Plugin{},
}
s.load()
go s.loadproc()
return
}
func (s *Service) Plugin(build, baseCode, seed int, name string) (pg *plugin.Plugin) {
if build == 0 || seed == 0 || name == "" {
return
}
if ps, ok := s.pluginCache[name]; ok {
for _, p := range ps {
if ((p.Policy == 1 && baseCode == p.BaseCode) || p.Policy == 2 && baseCode >= p.BaseCode) && seed%100 <= p.Coverage && build >= p.MinBuild && ((p.MaxBuild == 0) || (p.MaxBuild != 0 && build <= p.MaxBuild)) {
pg = p
break
}
}
}
return
}
// load cache data
func (s *Service) load() {
psm, err := s.pgDao.All(context.TODO())
if err != nil {
log.Error("s.pgDao.All() error(%v)", err)
return
}
pgCache := make(map[string][]*plugin.Plugin, len(psm))
for name, ps := range psm {
sort.Sort(plugin.Plugins(ps))
pgCache[name] = ps
}
s.pluginCache = pgCache
}
// cacheproc load cache data
func (s *Service) loadproc() {
for {
time.Sleep(s.tick)
s.load()
}
}

View File

@@ -0,0 +1,37 @@
package plugin
import (
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/app-resource/conf"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-resource-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestPlugin(t *testing.T) {
Convey("get Plugin data", t, WithService(func(s *Service) {
res := s.Plugin(1, 1, 1, "")
So(res, ShouldNotBeEmpty)
}))
}

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 = ["show_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"audit.go",
"cache.go",
"service.go",
"show.go",
],
importpath = "go-common/app/interface/main/app-resource/service/show",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//app/interface/main/app-resource/dao/audit:go_default_library",
"//app/interface/main/app-resource/dao/resource:go_default_library",
"//app/interface/main/app-resource/dao/tab:go_default_library",
"//app/interface/main/app-resource/model:go_default_library",
"//app/interface/main/app-resource/model/abtest:go_default_library",
"//app/interface/main/app-resource/model/show:go_default_library",
"//app/interface/main/app-resource/model/tab:go_default_library",
"//app/service/main/resource/model:go_default_library",
"//library/ecode: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,26 @@
package show
import (
"context"
"go-common/library/log"
)
func (s *Service) loadAuditCache() {
as, err := s.adt.Audits(context.TODO())
if err != nil {
log.Error("s.adt.Audits error(%v)", err)
return
}
s.auditCache = as
}
// Audit show tab data list.
func (s *Service) auditTab(mobiApp string, build int, plat int8) (isAudit bool) {
if plats, ok := s.auditCache[mobiApp]; ok {
if _, ok = plats[build]; ok {
return true
}
}
return false
}

View File

@@ -0,0 +1,98 @@
package show
import (
"context"
"fmt"
"time"
"go-common/app/interface/main/app-resource/model/show"
resource "go-common/app/service/main/resource/model"
"go-common/library/log"
)
func (s *Service) loadTabCache() (err error) {
var (
tmp = map[int64]struct{}{}
ss = map[string][]*show.Tab{}
sideBars *resource.SideBars
)
if sideBars, err = s.rdao.ResSideBar(context.TODO()); err != nil || sideBars == nil {
log.Error("s.sideDao.SideBar error(%v) or nil", err)
return
}
for _, v := range sideBars.SideBar {
if _, ok := tmp[v.ID]; ok {
continue
}
tmp[v.ID] = struct{}{}
st := &show.Tab{}
if !st.TabChange(v, _showAbtest, _deafaultTab) {
continue
}
key := fmt.Sprintf(_initTabKey, st.Plat, st.Language)
ss[key] = append(ss[key], st)
}
if len(ss) == 0 && len(s.tabCache) == 0 {
err = fmt.Errorf("tabCache is null")
return
} else if len(ss) == 0 {
return
}
s.tabCache = ss
s.limitsCahce = sideBars.Limit
log.Info("loadTabCache cache success")
return
}
func (s *Service) loadMenusCache(now time.Time) {
menus, err := s.tdao.Menus(context.TODO(), now)
if err != nil {
log.Error("s.tab.Menus error(%v)", err)
return
}
s.menuCache = menus
log.Info("loadMenusCache cache success")
}
func (s *Service) loadAbTestCache() {
var (
groups string
)
for _, g := range _showAbtest {
groups = groups + g + ","
}
if gLen := len(groups); gLen > 0 {
groups = groups[:gLen-1]
}
res, err := s.rdao.AbTest(context.TODO(), groups)
if err != nil {
log.Error("resource s.rdao.AbTest error(%v)", err)
return
}
s.abtestCache = res
log.Info("loadAbTestCache cache success")
}
func (s *Service) loadCache() (err error) {
now := time.Now()
err = s.loadTabCache()
s.loadMenusCache(now)
s.loadAbTestCache()
s.loadAuditCache()
return
}
func (s *Service) loadCacheproc() {
for {
time.Sleep(s.tick)
s.loadCache()
}
}
func (s *Service) loadShowTabAids() {
tmp := map[int64]struct{}{}
for _, mid := range s.c.ShowTabMids {
tmp[mid] = struct{}{}
}
s.showTabMids = tmp
}

View File

@@ -0,0 +1,52 @@
package show
import (
"time"
"go-common/app/interface/main/app-resource/conf"
adtdao "go-common/app/interface/main/app-resource/dao/audit"
resdao "go-common/app/interface/main/app-resource/dao/resource"
tabdao "go-common/app/interface/main/app-resource/dao/tab"
"go-common/app/interface/main/app-resource/model/show"
"go-common/app/interface/main/app-resource/model/tab"
resource "go-common/app/service/main/resource/model"
)
// Service is showtab service.
type Service struct {
c *conf.Config
//dao
rdao *resdao.Dao
tdao *tabdao.Dao
adt *adtdao.Dao
tick time.Duration
tabCache map[string][]*show.Tab
limitsCahce map[int64][]*resource.SideBarLimit
menuCache []*tab.Menu
abtestCache map[string]*resource.AbTest
showTabMids map[int64]struct{}
auditCache map[string]map[int]struct{} // audit mobi_app builds
}
// New new a showtab service.
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
rdao: resdao.New(c),
tdao: tabdao.New(c),
adt: adtdao.New(c),
tick: time.Duration(c.Tick),
tabCache: map[string][]*show.Tab{},
limitsCahce: map[int64][]*resource.SideBarLimit{},
menuCache: []*tab.Menu{},
abtestCache: map[string]*resource.AbTest{},
showTabMids: map[int64]struct{}{},
auditCache: map[string]map[int]struct{}{},
}
if err := s.loadCache(); err != nil {
panic(err)
}
s.loadShowTabAids()
go s.loadCacheproc()
return
}

View File

@@ -0,0 +1,118 @@
package show
import (
"context"
"encoding/json"
"fmt"
"strconv"
"go-common/app/interface/main/app-resource/model"
"go-common/app/interface/main/app-resource/model/abtest"
"go-common/app/interface/main/app-resource/model/show"
"go-common/library/ecode"
"go-common/library/log"
farm "github.com/dgryski/go-farm"
)
const (
_initTabKey = "tab_%d_%s"
_initVersion = "showtab_version"
_defaultLanguageHans = "hans"
_defaultLanguageHant = "hant"
)
var (
_showAbtest = map[string]string{
"bilibili://pegasus/hottopic": "home_tabbar_server_1",
}
_deafaultTab = map[string]*show.Tab{
"bilibili://pegasus/promo": &show.Tab{
DefaultSelected: 1,
},
}
)
// Tabs show tabs
func (s *Service) Tabs(c context.Context, plat int8, build int, buvid, ver, mobiApp, language string, mid int64) (res map[string][]*show.Tab, version string, a *abtest.List, err error) {
if key := fmt.Sprintf(_initTabKey, plat, language); len(s.tabCache[fmt.Sprintf(key)]) == 0 || language == "" {
if model.IsOverseas(plat) {
var key = fmt.Sprintf(_initTabKey, plat, _defaultLanguageHant)
if len(s.tabCache[fmt.Sprintf(key)]) > 0 {
language = _defaultLanguageHant
} else {
language = _defaultLanguageHans
}
} else {
language = _defaultLanguageHans
}
}
var (
key = fmt.Sprintf(_initTabKey, plat, language)
tmptabs = []*show.Tab{}
)
res = map[string][]*show.Tab{}
if tabs, ok := s.tabCache[key]; ok {
LOOP:
for _, v := range tabs {
for _, l := range s.limitsCahce[v.ID] {
if model.InvalidBuild(build, l.Build, l.Condition) {
continue LOOP
}
}
if !s.c.ShowHotAll {
if ab, ok := s.abtestCache[v.Group]; ok {
if _, ok := s.showTabMids[mid]; !ab.AbTestIn(buvid) && !ok {
continue LOOP
}
a = &abtest.List{}
a.ListChange(ab)
}
}
tmptabs = append(tmptabs, v)
}
}
if !s.auditTab(mobiApp, build, plat) {
if menus := s.menus(plat, build); len(menus) > 0 {
tmptabs = append(tmptabs, menus...)
}
}
for _, v := range tmptabs {
t := &show.Tab{}
*t = *v
t.Pos = len(res[v.ModuleStr]) + 1
res[v.ModuleStr] = append(res[v.ModuleStr], t)
}
if version = s.hash(res); version == ver {
err = ecode.NotModified
res = nil
}
return
}
func (s *Service) menus(plat int8, build int) (res []*show.Tab) {
memuCache := s.menuCache
LOOP:
for _, m := range memuCache {
if vs, ok := m.Versions[model.PlatAPPBuleChange(plat)]; ok {
for _, v := range vs {
if model.InvalidBuild(build, v.Build, v.Condition) {
continue LOOP
}
}
t := &show.Tab{}
t.TabMenuChange(m)
res = append(res, t)
}
}
return
}
func (s *Service) hash(v map[string][]*show.Tab) string {
bs, err := json.Marshal(v)
if err != nil {
log.Error("json.Marshal error(%v)", err)
return _initVersion
}
return strconv.FormatUint(farm.Hash64(bs), 10)
}

View File

@@ -0,0 +1,39 @@
package show
import (
"context"
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/app-resource/conf"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-resource-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestTabs(t *testing.T) {
Convey("get Tabs data", t, WithService(func(s *Service) {
res, _, _, err := s.Tabs(context.TODO(), 1, 1, "xxxx", "xxx", "iphone", "hans", 111)
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}

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 = ["sidebar_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["service.go"],
importpath = "go-common/app/interface/main/app-resource/service/sidebar",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//app/interface/main/app-resource/dao/bplus:go_default_library",
"//app/interface/main/app-resource/dao/resource:go_default_library",
"//app/interface/main/app-resource/dao/white:go_default_library",
"//app/interface/main/app-resource/model:go_default_library",
"//app/interface/main/app-resource/model/sidebar:go_default_library",
"//app/service/main/resource/model:go_default_library",
"//library/log: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,157 @@
package sidebar
import (
"context"
"fmt"
"sync"
"time"
"go-common/app/interface/main/app-resource/conf"
bplusdao "go-common/app/interface/main/app-resource/dao/bplus"
resdao "go-common/app/interface/main/app-resource/dao/resource"
whitedao "go-common/app/interface/main/app-resource/dao/white"
"go-common/app/interface/main/app-resource/model"
"go-common/app/interface/main/app-resource/model/sidebar"
resource "go-common/app/service/main/resource/model"
"go-common/library/log"
"go-common/library/sync/errgroup"
)
const (
_initSidebarKey = "sidebar_%d_%d_%s"
_defaultLanguageHans = "hans"
_defaultLanguageHant = "hant"
)
type Service struct {
c *conf.Config
//dao
res *resdao.Dao
bdao *bplusdao.Dao
wdao *whitedao.Dao
// sidebar
tick time.Duration
sidebarCache map[string][]*sidebar.SideBar
limitsCahce map[int64][]*resource.SideBarLimit
//limit ids
limitIDs map[int64]struct{}
}
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
res: resdao.New(c),
bdao: bplusdao.New(c),
wdao: whitedao.New(c),
tick: time.Duration(c.Tick),
sidebarCache: map[string][]*sidebar.SideBar{},
limitsCahce: map[int64][]*resource.SideBarLimit{},
//limit ids
limitIDs: map[int64]struct{}{},
}
s.loadSidebar()
s.loadLimit(c.SideBarLimit)
go s.tickproc()
return s
}
// SideBar
func (s *Service) SideBar(c context.Context, plat int8, build, module int, mid int64, language string) (ss []*sidebar.SideBar) {
if key := fmt.Sprintf(_initSidebarKey, plat, module, language); len(s.sidebarCache[fmt.Sprintf(key)]) == 0 || language == "" {
if model.IsOverseas(plat) {
key = fmt.Sprintf(_initSidebarKey, plat, module, _defaultLanguageHant)
if len(s.sidebarCache[fmt.Sprintf(key)]) > 0 {
language = _defaultLanguageHant
} else {
language = _defaultLanguageHans
}
} else {
language = _defaultLanguageHans
}
}
var (
key = fmt.Sprintf(_initSidebarKey, plat, module, language)
verify = map[int64]bool{}
mutex sync.Mutex
)
if sidebars, ok := s.sidebarCache[key]; ok {
g, _ := errgroup.WithContext(c)
for _, v := range sidebars {
var (
vid = v.ID
vurl = v.WhiteURL
)
if vurl != "" && mid > 0 {
g.Go(func() (err error) {
var ok bool
if ok, err = s.wdao.WhiteVerify(context.TODO(), mid, vurl); err != nil {
log.Error("s.wdao.WhiteVerify uri(%s) error(%v)", vurl, err)
ok = false
err = nil
}
mutex.Lock()
verify[vid] = ok
mutex.Unlock()
return
})
} else if vurl != "" && mid == 0 {
verify[vid] = false
}
}
g.Wait()
LOOP:
for _, v := range sidebars {
for _, l := range s.limitsCahce[v.ID] {
if model.InvalidBuild(build, l.Build, l.Condition) {
continue LOOP
}
}
if verifybool, ok := verify[v.ID]; ok && !verifybool {
continue LOOP
}
ss = append(ss, v)
}
}
return
}
// tickproc tick load cache.
func (s *Service) tickproc() {
for {
time.Sleep(s.tick)
s.loadSidebar()
}
}
func (s *Service) loadSidebar() {
sideBars, err := s.res.ResSideBar(context.TODO())
if err != nil || sideBars == nil {
log.Error("s.sideDao.SideBar error(%v) or nil", err)
return
}
var (
tmp = map[int64]struct{}{}
ss = map[string][]*sidebar.SideBar{}
)
for _, v := range sideBars.SideBar {
if _, ok := tmp[v.ID]; ok {
continue
}
tmp[v.ID] = struct{}{}
t := &sidebar.SideBar{}
t.Change(v)
key := fmt.Sprintf(_initSidebarKey, t.Plat, t.Module, t.Language)
ss[key] = append(ss[key], t)
}
s.sidebarCache = ss
s.limitsCahce = sideBars.Limit
log.Info("loadSidebar cache success")
}
func (s *Service) loadLimit(limit []int64) {
tmp := map[int64]struct{}{}
for _, l := range limit {
tmp[l] = struct{}{}
}
s.limitIDs = tmp
}

View File

@@ -0,0 +1,38 @@
package sidebar
import (
"context"
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/app-resource/conf"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-resource-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestSideBar(t *testing.T) {
Convey("get SideBar data", t, WithService(func(s *Service) {
res := s.SideBar(context.TODO(), 1, 1, 1, 1, "hans")
So(res, ShouldNotBeEmpty)
}))
}

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 = ["splash_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//app/interface/main/app-resource/model:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["splash.go"],
importpath = "go-common/app/interface/main/app-resource/service/splash",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//app/interface/main/app-resource/dao/ad:go_default_library",
"//app/interface/main/app-resource/dao/location:go_default_library",
"//app/interface/main/app-resource/dao/splash:go_default_library",
"//app/interface/main/app-resource/model:go_default_library",
"//app/interface/main/app-resource/model/splash:go_default_library",
"//app/service/main/location/model:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/metadata:go_default_library",
"//library/sync/errgroup: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,499 @@
package splash
import (
"context"
"encoding/json"
"fmt"
"math"
"strconv"
"strings"
"time"
"go-common/app/interface/main/app-resource/conf"
addao "go-common/app/interface/main/app-resource/dao/ad"
locdao "go-common/app/interface/main/app-resource/dao/location"
spdao "go-common/app/interface/main/app-resource/dao/splash"
"go-common/app/interface/main/app-resource/model"
"go-common/app/interface/main/app-resource/model/splash"
locmdl "go-common/app/service/main/location/model"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/metadata"
"go-common/library/sync/errgroup"
farm "github.com/dgryski/go-farm"
)
const (
_birthType = 2
_vipType = 4
_defaultType = 0
_initVersion = "splash_version"
_initSplashKey = "splash_key_%d_%d_%d"
)
var (
_emptySplashs = []*splash.Splash{}
)
// Service is splash service.
type Service struct {
dao *spdao.Dao
ad *addao.Dao
loc *locdao.Dao
// tick
tick time.Duration
// splash duration
splashTick string
// screen
andScreen map[int8]map[float64][2]int
iosScreen map[int8]map[float64][2]int
// cache
cache map[string][]*splash.Splash
defaultCache map[string][]*splash.Splash
birthCache map[string][]*splash.Splash
vipCache map[string][]*splash.Splash
// splash random
splashRandomIds map[int8]map[int64]struct{}
}
// New new a splash service.
func New(c *conf.Config) *Service {
s := &Service{
dao: spdao.New(c),
ad: addao.New(c),
loc: locdao.New(c),
// tick
tick: time.Duration(c.Tick),
// splash duration
splashTick: c.Duration.Splash,
// screen
andScreen: map[int8]map[float64][2]int{},
iosScreen: map[int8]map[float64][2]int{},
// splash cache
cache: map[string][]*splash.Splash{},
defaultCache: map[string][]*splash.Splash{},
birthCache: map[string][]*splash.Splash{},
vipCache: map[string][]*splash.Splash{},
// splash random
splashRandomIds: map[int8]map[int64]struct{}{},
}
s.load()
s.loadBirth()
s.loadSplashRandomIds(c)
go s.loadproc()
return s
}
// Display dispaly data.
func (s *Service) Display(c context.Context, plat int8, w, h, build int, channel, ver string, now time.Time) (res []*splash.Splash, version string, err error) {
// get from cache
res, version, err = s.getCache(c, plat, w, h, build, channel, ver, now)
return
}
func (s *Service) Birthday(c context.Context, plat int8, w, h int, birth string) (res *splash.Splash, err error) {
// get from cache
res, err = s.getBirthCache(c, plat, w, h, birth)
return
}
// AdList ad splash list
func (s *Service) AdList(c context.Context, plat int8, mobiApp, device, buvid, birth, adExtra string, height, width, build int, mid int64) (res *splash.CmSplash, err error) {
var (
list []*splash.List
show []*splash.Show
config *splash.CmConfig
)
if ok := model.IsOverseas(plat); ok {
err = ecode.NotModified
return
}
g, ctx := errgroup.WithContext(c)
g.Go(func() error {
var e error
if list, config, e = s.ad.SplashList(ctx, mobiApp, device, buvid, birth, adExtra, height, width, build, mid); e != nil {
log.Error("cm s.ad.SplashList error(%v)", e)
return e
}
return nil
})
g.Go(func() error {
var e error
if show, e = s.ad.SplashShow(ctx, mobiApp, device, buvid, birth, adExtra, height, width, build, mid); e != nil {
log.Error("cm s.ad.SplashShow error(%v)", e)
return e
}
return nil
})
if err = g.Wait(); err != nil {
log.Error("cm splash errgroup.WithContext error(%v)", err)
return
}
res = &splash.CmSplash{
CmConfig: config,
List: list,
Show: show,
}
return
}
// getCache cache display data.
func (s *Service) getCache(c context.Context, plat int8, w, h, build int, channel, ver string, now time.Time) (res []*splash.Splash, version string, err error) {
var (
ip = metadata.String(c, metadata.RemoteIP)
screen map[int8]map[float64][2]int
)
if model.IsIOS(plat) {
screen = s.iosScreen
} else if model.IsAndroid(plat) {
screen = s.andScreen
}
// TODO fate go start
var (
fgId int64
oldIdStr string
fgids = s.splashRandomIds[plat]
pids []string
auths map[string]*locmdl.Auth
)
vers := strings.Split(ver, strconv.Itoa(now.Year()))
if len(vers) > 1 {
ver = vers[0]
oldIdStr = vers[1]
}
for id, _ := range fgids {
fgId = id
idStr := strconv.FormatInt(fgId, 10)
if oldIdStr != idStr {
break
}
}
for tSplash, tScreen := range screen {
var ss []*splash.Splash
if ss = s.cache[fmt.Sprintf(_initSplashKey, plat, w, h)]; len(ss) == 0 {
wh := s.similarScreen(plat, w, h, tScreen)
width := wh[0]
height := wh[1]
ss = s.cache[fmt.Sprintf(_initSplashKey, plat, width, height)]
}
for _, splash := range ss {
if splash.Type != tSplash {
continue
}
if splash.Area != "" {
pids = append(pids, splash.Area)
}
}
}
if len(pids) > 0 {
auths, _ = s.loc.AuthPIDs(c, strings.Join(pids, ","), ip)
}
// TODO fate go end
for tSplash, tScreen := range screen {
var (
ss []*splash.Splash
// advance time
advance, _ = time.ParseDuration(s.splashTick)
)
if ss = s.cache[fmt.Sprintf(_initSplashKey, plat, w, h)]; len(ss) == 0 {
wh := s.similarScreen(plat, w, h, tScreen)
width := wh[0]
height := wh[1]
ss = s.cache[fmt.Sprintf(_initSplashKey, plat, width, height)]
}
for _, splash := range ss {
if splash.Type != tSplash {
continue
}
// gt splash start time
if splash.NoPreview == 1 {
if h1 := now.Add(advance); int64(splash.Start) > h1.Unix() {
continue
}
}
// TODO fate go start
if fgids != nil && splash.ID != fgId {
if _, ok := fgids[splash.ID]; ok {
continue
}
}
// TODO fate go end
if model.InvalidBuild(build, splash.Build, splash.Condition) {
continue
}
if splash.Area != "" {
if auth, ok := auths[splash.Area]; ok && auth.Play == locmdl.Forbidden {
log.Warn("s.invalid area(%v) ip(%v) error(%v)", splash.Area, ip, err)
continue
}
}
res = append(res, splash)
}
}
if vSplash := s.getVipCache(plat, w, h, screen, now); vSplash != nil {
res = append(res, vSplash)
}
if dSplash := s.getDefaultCache(plat, w, h, screen, now); dSplash != nil {
res = append(res, dSplash)
}
if len(res) == 0 {
res = _emptySplashs
}
if version = s.hash(res); version == ver {
err = ecode.NotModified
res = nil
}
version = version + strconv.Itoa(now.Year()) + strconv.FormatInt(fgId, 10)
return
}
// getBirthCache get birthday splash.
func (s *Service) getBirthCache(c context.Context, plat int8, w, h int, birth string) (res *splash.Splash, err error) {
var (
screen map[int8]map[float64][2]int
wh [2]int
)
if model.IsIOS(plat) {
screen = s.iosScreen
} else if model.IsAndroid(plat) {
screen = s.andScreen
}
if v, ok := screen[_birthType]; !ok {
return
} else {
wh = s.similarScreen(plat, w, h, v)
w = wh[0]
h = wh[1]
}
sps := s.birthCache[fmt.Sprintf(_initSplashKey, plat, w, h)]
for _, sp := range sps {
if sp.BirthStartMonth == "12" && sp.BirthEndMonth == "01" {
if (sp.BirthStart <= birth && "1231" >= birth) || ("0101" <= birth && sp.BirthEnd >= birth) {
res = sp
return
}
}
if sp.BirthStart <= birth && sp.BirthEnd >= birth {
res = sp
return
}
}
err = ecode.NothingFound
return
}
// getVipCache
func (s *Service) getVipCache(plat int8, w, h int, screen map[int8]map[float64][2]int, now time.Time) (res *splash.Splash) {
var (
ss []*splash.Splash
)
if v, ok := screen[_vipType]; !ok {
return
} else if ss = s.vipCache[fmt.Sprintf(_initSplashKey, plat, w, h)]; len(ss) == 0 {
wh := s.similarScreen(plat, w, h, v)
width := wh[0]
height := wh[1]
ss = s.vipCache[fmt.Sprintf(_initSplashKey, plat, width, height)]
}
if len(ss) == 0 {
return
}
res = ss[(now.Day() % len(ss))]
return
}
// getDefaultCache
func (s *Service) getDefaultCache(plat int8, w, h int, screen map[int8]map[float64][2]int, now time.Time) (res *splash.Splash) {
var (
ss []*splash.Splash
)
if v, ok := screen[_defaultType]; !ok {
return
} else if ss = s.defaultCache[fmt.Sprintf(_initSplashKey, plat, w, h)]; len(ss) == 0 {
wh := s.similarScreen(plat, w, h, v)
width := wh[0]
height := wh[1]
ss = s.defaultCache[fmt.Sprintf(_initSplashKey, plat, width, height)]
}
if len(ss) == 0 {
return
}
res = ss[(now.Day() % len(ss))]
return
}
func (s *Service) hash(v []*splash.Splash) string {
bs, err := json.Marshal(v)
if err != nil {
log.Error("json.Marshal error(%v)", err)
return _initVersion
}
return strconv.FormatUint(farm.Hash64(bs), 10)
}
// cacheproc load splash into cache.
func (s *Service) load() {
res, err := s.dao.ActiveAll(context.TODO())
if err != nil {
log.Error("s.dao.GetActiveAll() error(%v)", err)
return
}
var (
tmp []*splash.Splash
tmpdefault []*splash.Splash
)
for _, r := range res {
if r.Type == _defaultType {
tmpdefault = append(tmpdefault, r)
} else {
tmp = append(tmp, r)
}
}
s.cache = s.dealCache(tmp)
log.Info("splash cacheproc success")
s.defaultCache = s.dealCache(tmpdefault)
log.Info("splash default cacheproc tmpdefault")
resVip, err := s.dao.ActiveVip(context.TODO())
if err != nil {
log.Error("s.dao.ActiveVip() error(%v)", err)
return
}
s.vipCache = s.dealCache(resVip)
log.Info("splash Vip cacheproc success")
}
// loadBirth load birthday splash.
func (s *Service) loadBirth() {
res, err := s.dao.ActiveBirth(context.TODO())
if err != nil {
log.Error("s.dao.ActiveBirthday() error(%v)", err)
return
}
s.birthCache = s.dealCache(res)
log.Info("splash Birthday cacheproc success")
}
// dealCache
func (s *Service) dealCache(sps []*splash.Splash) (res map[string][]*splash.Splash) {
res = map[string][]*splash.Splash{}
tmpand := map[int8]map[float64][2]int{}
tmpios := map[int8]map[float64][2]int{}
for plat, v := range s.andScreen {
for r, value := range v {
if _, ok := tmpand[plat]; ok {
tmpand[plat][r] = value
} else {
tmpand[plat] = map[float64][2]int{
r: value,
}
}
}
}
for plat, v := range s.iosScreen {
for r, value := range v {
if _, ok := tmpios[plat]; ok {
tmpios[plat][r] = value
} else {
tmpios[plat] = map[float64][2]int{
r: value,
}
}
}
}
for _, v := range sps {
v.URI = model.FillURI(v.Goto, v.Param, nil)
key := fmt.Sprintf(_initSplashKey, v.Plat, v.Width, v.Height)
res[key] = append(res[key], v)
// generate screen
if model.IsAndroid(v.Plat) {
if _, ok := tmpand[v.Type]; ok {
tmpand[v.Type][splash.Ratio(v.Width, v.Height)] = [2]int{v.Width, v.Height}
} else {
tmpand[v.Type] = map[float64][2]int{
splash.Ratio(v.Width, v.Height): [2]int{v.Width, v.Height},
}
}
} else if model.IsIOS(v.Plat) {
if _, ok := tmpios[v.Type]; ok {
tmpios[v.Type][splash.Ratio(v.Width, v.Height)] = [2]int{v.Width, v.Height}
} else {
tmpios[v.Type] = map[float64][2]int{
splash.Ratio(v.Width, v.Height): [2]int{v.Width, v.Height},
}
}
}
}
s.andScreen = tmpand
s.iosScreen = tmpios
return
}
func (s *Service) loadSplashRandomIds(c *conf.Config) {
splashIds := map[int8]map[int64]struct{}{}
for k, v := range c.Splash.Random {
key := model.Plat(k, "")
splashIds[key] = map[int64]struct{}{}
for _, idStr := range v {
idInt, _ := strconv.ParseInt(idStr, 10, 64)
splashIds[key][idInt] = struct{}{}
}
}
s.splashRandomIds = splashIds
log.Info("splash Random cache success")
}
// loadproc load process.
func (s *Service) loadproc() {
for {
time.Sleep(s.tick)
s.load()
s.loadBirth()
}
}
// similarScreen android screnn size
func (s *Service) similarScreen(plat int8, w, h int, screen map[float64][2]int) (wh [2]int) {
if model.IsIOS(plat) {
switch {
case w == 750:
h = 1334
case w == 640 && h > 960:
h = 1136
case w == 640:
h = 960
case w == 2732:
h = 2048
case w == 2048:
h = 1536
case w == 1024:
h = 768
case w == 1242:
h = 2208
case w == 1496 || w == 1536:
w = 2048
h = 1536
case w == 748 || w == 768:
w = 1024
h = 768
}
}
min := float64(1<<64 - 1)
for r, s := range screen {
if s[0] == w && s[1] == h {
wh = s
return
}
abs := math.Abs(splash.Ratio(w, h) - r)
if abs < min {
min = abs
wh = s
}
}
return
}
// Close dao
func (s *Service) Close() {
s.dao.Close()
}

View File

@@ -0,0 +1,48 @@
package splash
import (
"context"
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/app-resource/conf"
"go-common/app/interface/main/app-resource/model"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-resource-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestDisplay(t *testing.T) {
Convey("get Display data", t, WithService(func(s *Service) {
res, _, err := s.Display(context.TODO(), model.PlatIPhone, 1, 1, 1, "", "", time.Now())
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}
func TestBirthday(t *testing.T) {
Convey("get Birthday data", t, WithService(func(s *Service) {
res, err := s.Birthday(context.TODO(), model.PlatIPhone, 1, 1, "")
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,50 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["static_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["static.go"],
importpath = "go-common/app/interface/main/app-resource/service/static",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//app/interface/main/app-resource/dao/egg:go_default_library",
"//app/interface/main/app-resource/model:go_default_library",
"//app/interface/main/app-resource/model/static:go_default_library",
"//library/ecode: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,94 @@
package static
import (
"context"
"encoding/json"
"strconv"
"time"
"go-common/app/interface/main/app-resource/conf"
eggdao "go-common/app/interface/main/app-resource/dao/egg"
"go-common/app/interface/main/app-resource/model"
"go-common/app/interface/main/app-resource/model/static"
"go-common/library/ecode"
"go-common/library/log"
farm "github.com/dgryski/go-farm"
)
const (
_initVersion = "static_version"
)
var (
_emptyStatics = []*static.Static{}
)
// Service static service.
type Service struct {
dao *eggdao.Dao
tick time.Duration
cache map[int8][]*static.Static
staticPath string
}
// New new a static service.
func New(c *conf.Config) (s *Service) {
s = &Service{
dao: eggdao.New(c),
tick: time.Duration(c.Tick),
cache: map[int8][]*static.Static{},
staticPath: c.StaticJSONFile,
}
now := time.Now()
s.loadCache(now)
go s.loadCachepro()
return
}
// Static return statics
func (s *Service) Static(plat int8, build int, ver string, now time.Time) (res []*static.Static, version string, err error) {
var (
tmps = s.cache[plat]
)
for _, tmp := range tmps {
if model.InvalidBuild(build, tmp.Build, tmp.Condition) {
continue
}
res = append(res, tmp)
}
if len(res) == 0 {
res = _emptyStatics
}
if version = s.hash(res); version == ver {
err = ecode.NotModified
res = nil
}
return
}
func (s *Service) hash(v []*static.Static) string {
bs, err := json.Marshal(v)
if err != nil {
log.Error("json.Marshal error(%v)", err)
return _initVersion
}
return strconv.FormatUint(farm.Hash64(bs), 10)
}
// loadCache update egg
func (s *Service) loadCache(now time.Time) {
tmp, err := s.dao.Egg(context.TODO(), now)
if err != nil {
log.Error("s.dao.Egg error(%v)", err)
return
}
s.cache = tmp
}
func (s *Service) loadCachepro() {
for {
time.Sleep(s.tick)
s.loadCache(time.Now())
}
}

View File

@@ -0,0 +1,43 @@
package static
import (
"encoding/json"
"flag"
"fmt"
"go-common/app/interface/main/app-resource/conf"
"path/filepath"
"testing"
"time"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-resource-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
// go test -conf="../../cmd/app-resource-test.toml" -v -test.run TestStatic
func TestStatic(t *testing.T) {
Convey("get static data", t, WithService(func(s *Service) {
res, ver, err := s.Static(1, 22222, "", time.Now())
result, err := json.Marshal(res)
fmt.Printf("test static (%v) \n", string(result))
So(res, ShouldNotBeEmpty)
So(ver, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,50 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["version_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["version.go"],
importpath = "go-common/app/interface/main/app-resource/service/version",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//app/interface/main/app-resource/dao/version:go_default_library",
"//app/interface/main/app-resource/model:go_default_library",
"//app/interface/main/app-resource/model/version:go_default_library",
"//library/ecode: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,264 @@
package version
import (
"context"
"time"
"go-common/app/interface/main/app-resource/conf"
verdao "go-common/app/interface/main/app-resource/dao/version"
"go-common/app/interface/main/app-resource/model"
"go-common/app/interface/main/app-resource/model/version"
"go-common/library/ecode"
"go-common/library/log"
farm "github.com/dgryski/go-farm"
)
const (
_defaultChannel = "bili"
)
var (
_emptyVersion = []*version.Version{}
_emptyVersionSo = []*version.VersionSo{}
)
// Service version service.
type Service struct {
dao *verdao.Dao
cache map[int8][]*version.Version
upCache map[int8]map[string][]*version.VersionUpdate
uplimitCache map[int][]*version.UpdateLimit
soCache map[string][]*version.VersionSo
increCache map[int8]map[string][]*version.Incremental
rnCache map[string]map[string]*version.Rn
tick time.Duration
}
// New new a version service.
func New(c *conf.Config) (s *Service) {
s = &Service{
dao: verdao.New(c),
tick: time.Duration(c.Tick),
cache: map[int8][]*version.Version{},
upCache: map[int8]map[string][]*version.VersionUpdate{},
uplimitCache: map[int][]*version.UpdateLimit{},
soCache: map[string][]*version.VersionSo{},
increCache: map[int8]map[string][]*version.Incremental{},
rnCache: map[string]map[string]*version.Rn{},
}
s.load()
go s.loadproc()
return
}
// Version return version
func (s *Service) Version(plat int8) (res []*version.Version, err error) {
if res = s.cache[plat]; res == nil {
res = _emptyVersion
}
return
}
// VersionUpdate return version
func (s *Service) VersionUpdate(build int, plat int8, buvid, sdkint, channel, module, oldID string) (res *version.VersionUpdate, err error) {
var (
gvu, tmp []*version.VersionUpdate
)
if vup, ok := s.upCache[plat]; ok {
if tmp, ok = vup[channel]; !ok || len(tmp) == 0 {
if plat == model.PlatAndroidTVYST {
err = ecode.NotModified
return
}
if tmp, ok = vup[_defaultChannel]; !ok || len(tmp) == 0 {
err = ecode.NotModified
return
}
}
for _, t := range tmp {
tu := &version.VersionUpdate{}
*tu = *t
gvu = append(gvu, tu)
}
} else {
err = ecode.NotModified
return
}
LOOP:
for _, vu := range gvu {
if build >= vu.Build {
err = ecode.NotModified
return
}
if vu.IsGray == 1 {
if len(vu.SdkIntList) > 0 {
if _, ok := vu.SdkIntList[sdkint]; !ok {
continue LOOP
}
}
if module != vu.Model && vu.Model != "" {
continue LOOP
}
if buvid != "" {
id := farm.Hash32([]byte(buvid))
n := int(id % 100)
if vu.BuvidStart > n || n > vu.BuvidEnd {
continue LOOP
}
}
}
if limit, ok := s.uplimitCache[vu.Id]; ok {
var tmpl bool
for i, l := range limit {
if i+1 <= len(limit)-1 {
if ((l.Conditions == "gt" && limit[i+1].Conditions == "lt") && (l.BuildLimit < limit[i+1].BuildLimit)) ||
((l.Conditions == "lt" && limit[i+1].Conditions == "gt") && (l.BuildLimit > limit[i+1].BuildLimit)) {
if (l.Conditions == "gt" && limit[i+1].Conditions == "lt") &&
(build > l.BuildLimit && build < limit[i+1].BuildLimit) {
res = vu
break LOOP
} else if (l.Conditions == "lt" && limit[i+1].Conditions == "gt") &&
(build < l.BuildLimit && build > limit[i+1].BuildLimit) {
res = vu
break LOOP
} else {
tmpl = true
continue
}
}
}
if tmpl {
tmpl = false
continue
}
if model.InvalidBuild(build, l.BuildLimit, l.Conditions) {
continue
} else {
res = vu
break LOOP
}
}
} else {
res = vu
break LOOP
}
}
if res == nil {
err = ecode.NotModified
return
}
res.Incre = s.versionIncrementals(plat, res.Build, oldID)
return
}
// versionIncrementals version incrementals
func (s *Service) versionIncrementals(plat int8, build int, oldID string) (ver *version.Incremental) {
if v, ok := s.increCache[plat]; ok {
if vers, ok := v[oldID]; ok {
for _, value := range vers {
if value.Build == build {
ver = value
return
}
}
}
}
return
}
// VersionSo return version_so
func (s *Service) VersionSo(build, seed, sdkint int, name, model string) (vsdesc *version.VersionSoDesc, err error) {
vSo := s.soCache[name]
if len(vSo) == 0 {
err = ecode.NotModified
return
}
vsdesc = &version.VersionSoDesc{
Package: vSo[0].Package,
Name: vSo[0].Name,
Description: vSo[0].Description,
Clear: vSo[0].Clear,
}
for _, value := range vSo {
if value.Min_build > build || (seed > 0 && seed%100 >= value.Coverage) || (sdkint != value.Sdkint && value.Sdkint != 0) || (model != value.Model && value.Model != "" && value.Model != "*") {
continue
}
vsdesc.Versions = append(vsdesc.Versions, value)
}
if vsdesc.Versions == nil {
vsdesc.Versions = _emptyVersionSo
}
return
}
// VersionRn return version_rn
func (s *Service) VersionRn(version, deploymentKey, bundleID string) (vrn *version.Rn, err error) {
if v, ok := s.rnCache[deploymentKey]; ok {
if vrn, ok = v[version]; !ok {
err = ecode.NotModified
} else if vrn.BundleID == bundleID {
err = ecode.NotModified
}
} else {
err = ecode.NotModified
}
return
}
// load cache data
func (s *Service) load() {
ver, err := s.dao.All(context.TODO())
if err != nil {
log.Error("version s.dao.All() error(%v)", err)
return
}
s.cache = ver
upver, err := s.dao.Updates(context.TODO())
if err != nil {
log.Error("version s.dao.GetUpdate() error(%v)", err)
return
}
s.upCache = upver
log.Info("version cacheproc success")
sover, err := s.dao.Sos(context.TODO())
if err != nil {
log.Error("version s.dao.Sos() error(%v)", err)
return
}
uplimit, err := s.dao.Limits(context.TODO())
if err != nil {
log.Error("version s.dao.Limits() error(%v)", err)
return
}
s.uplimitCache = uplimit
s.soCache = sover
log.Info("versionso cacheproc success")
increver, err := s.dao.Incrementals(context.TODO())
if err != nil {
log.Error("version s.dao.Incrementals error(%v)", err)
return
}
s.increCache = increver
log.Info("versionIncre cacheproc success")
rn, err := s.dao.Rn(context.TODO())
if err != nil {
log.Error("version s.dao.Rn error(%v)", err)
return
}
s.rnCache = rn
log.Info("versionRn cacheproc success")
}
// cacheproc load cache data
func (s *Service) loadproc() {
for {
time.Sleep(s.tick)
s.load()
}
}
// Close dao
func (s *Service) Close() {
s.dao.Close()
}

View File

@@ -0,0 +1,62 @@
package version
import (
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/app-resource/conf"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-resource-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestVersion(t *testing.T) {
Convey("get Version data", t, WithService(func(s *Service) {
res, err := s.Version(1)
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}
func TestVersionUpdate(t *testing.T) {
Convey("get VersionUpdate data", t, WithService(func(s *Service) {
res, err := s.VersionUpdate(1, 1, "", "", "", "", "")
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}
func TestVersionSo(t *testing.T) {
Convey("get VersionSo data", t, WithService(func(s *Service) {
res, err := s.VersionSo(1, 1, 1, "", "")
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}
func TestVersionRn(t *testing.T) {
Convey("get VersionRn data", t, WithService(func(s *Service) {
res, err := s.VersionRn("", "", "")
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,42 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = ["white.go"],
importpath = "go-common/app/interface/main/app-resource/service/white",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = ["//app/interface/main/app-resource/conf: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 = ["white_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/app-resource/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,26 @@
package white
import (
"go-common/app/interface/main/app-resource/conf"
)
// Service white service.
type Service struct {
c *conf.Config
listCache map[string][]string
}
// New new a interest service.
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
listCache: c.White.List,
}
return
}
// List white list
func (s *Service) List() (res map[string][]string) {
res = s.listCache
return
}

View File

@@ -0,0 +1,37 @@
package white
import (
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/interface/main/app-resource/conf"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-resource-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestList(t *testing.T) {
Convey("get List data", t, WithService(func(s *Service) {
res := s.List()
So(res, ShouldNotBeEmpty)
}))
}