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,21 @@
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/service/main/msm/cmd:all-srcs",
"//app/service/main/msm/conf:all-srcs",
"//app/service/main/msm/dao:all-srcs",
"//app/service/main/msm/http:all-srcs",
"//app/service/main/msm/model:all-srcs",
"//app/service/main/msm/service:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,45 @@
### msm-service
#### Version 1.7.5
1. ecode添加繁体信息接口
#### Version 1.7.4
1. ut补全
#### Version 1.7.3
1. 替换为verify.Verify
#### Version 1.7.1
>1. msm服务使用独立鉴权代码防止鉴权回路.
#### Version 1.7.0
>1. 增加RPC鉴权接口
>2. 删除无用接口和代码
>3. 使用BM框架
>4. 迁移至business/service/main目录
#### Version 1.6.0
>1. ecode读取db2数据库
#### Version 1.5.0
>1. 修改了ecode的逻辑分为2个接口codes兼容老的codes/2支持新的
#### Version 1.4.0
>1. 增加limit接口提供限流规则
#### Version 1.3.0
>1. 增加rules接口databus配置规则全量获取
#### Version 1.2.0
>1. 优化ecode接口增量拉取用更新时间作为版本号
#### Version 1.1.0
>1. 增加获取codes接口
#### Version 1.0.0
>1. rpc服务修改节点 权重,分组信息
>2. rpc服务所有节点信息查询节点删除
>3. 对配置中心进行broadCast调用所有节点目前有push和setToken方法。

View File

@@ -0,0 +1,10 @@
# Owner
maojian
# Author
zhoujixiang
chenshangqiang
# Reviewer
maojian
haoguanwei

View File

@@ -0,0 +1,17 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- chenshangqiang
- maojian
- zhoujixiang
labels:
- main
- service
- service/main/msm
options:
no_parent_owners: true
reviewers:
- chenshangqiang
- haoguanwei
- maojian
- zhoujixiang

View File

@@ -0,0 +1,21 @@
# go-common/app/service/msm
##### 项目简介
> 1. 提供code,限流等接口
> 2. 微服务节点管理接口
##### 编译环境
> 1. 请只用golang v1.7.x以上版本编译执行。
##### 依赖包
> 1. 公共依赖
##### 编译执行
> 1. 启动执行
> 2. 项目文档http://info.bilibili.co/pages/viewpage.action?pageId=1742325
##### 测试
> 1. 执行当前目录下所有测试文件,测试所有功能
##### 特别说明
> 2. 管理平台地址 http://apm-monitor.bilibili.co

View File

@@ -0,0 +1,41 @@
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_binary",
)
package(default_visibility = ["//visibility:public"])
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_library(
name = "go_default_library",
srcs = ["main.go"],
data = ["msm-service-example.toml"],
importpath = "go-common/app/service/main/msm/cmd",
tags = ["automanaged"],
deps = [
"//app/service/main/msm/conf:go_default_library",
"//app/service/main/msm/http:go_default_library",
"//app/service/main/msm/service:go_default_library",
"//library/log:go_default_library",
],
)
go_binary(
name = "cmd",
embed = [":go_default_library"],
tags = ["automanaged"],
)

View File

@@ -0,0 +1,43 @@
package main
import (
"flag"
"os"
"os/signal"
"syscall"
"go-common/app/service/main/msm/conf"
"go-common/app/service/main/msm/http"
"go-common/app/service/main/msm/service"
"go-common/library/log"
)
func main() {
flag.Parse()
if err := conf.Init(); err != nil {
log.Error("conf.Init() error(%v)", err)
panic(err)
}
// init log
log.Init(conf.Conf.Log)
defer log.Close()
log.Info("msm-service start")
svr := service.New(conf.Conf)
http.Init(conf.Conf, svr)
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
s := <-c
log.Info("msm-service get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
svr.Close()
log.Info("msm-service exit")
return
case syscall.SIGHUP:
// TODO reload
default:
return
}
}
}

View File

@@ -0,0 +1,27 @@
[httpClient]
key = "654af11b5df0c9d3"
secret = "a7512b8b243b82f4bdb72cf2824b3f8e"
dial = "1s"
timeout = "1s"
keepAlive = "60s"
[mysql]
addr = "172.16.33.205:3308"
dsn = "test:test@tcp(172.16.33.205:3308)/bilibili_apm_v2?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 5
idle = 5
queryTimeout = "500ms"
execTimeout = "500ms"
tranTimeout = "500ms"
idleTimeout = "7h"
[mysql.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[tree]
host = "http://easyst.bilibili.co"
platformID = "bilibili"

View File

@@ -0,0 +1,35 @@
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
package(default_visibility = ["//visibility:public"])
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_library(
name = "go_default_library",
srcs = ["conf.go"],
importpath = "go-common/app/service/main/msm/conf",
tags = ["automanaged"],
deps = [
"//library/conf:go_default_library",
"//library/database/sql:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/rpc:go_default_library",
"//vendor/github.com/BurntSushi/toml:go_default_library",
],
)

View File

@@ -0,0 +1,90 @@
package conf
import (
"errors"
"flag"
"go-common/library/conf"
"go-common/library/database/sql"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/rpc"
"github.com/BurntSushi/toml"
)
var (
confPath string
// Conf conf
Conf = &Config{}
configKey = "msm-service.toml"
client *conf.Client
)
// Config config
type Config struct {
// Environment string
Log *log.Config
BM *bm.ServerConfig
HTTPClient *bm.ClientConfig
ConfSvr *rpc.ClientConfig
Mysql *sql.Config
Tree *ServiceTree
}
// ServiceTree ServiceTree.
type ServiceTree struct {
Host string
PlatformID string
}
func init() {
flag.StringVar(&confPath, "conf", "", "config file")
}
// Init init.
func Init() (err error) {
if confPath != "" {
return local()
}
return remote()
}
func local() (err error) {
_, err = toml.DecodeFile(confPath, &Conf)
return
}
func remote() (err error) {
if client, err = conf.New(); err != nil {
return
}
if err = load(); err != nil {
return
}
go func() {
for range client.Event() {
log.Info("config reload")
if err := load(); err != nil {
log.Error("config reload error (%v)", err)
}
}
}()
return
}
func load() (err error) {
var (
s string
ok bool
tmpConf *Config
)
if s, ok = client.Value(configKey); !ok {
return errors.New("load config center error")
}
if _, err = toml.Decode(s, &tmpConf); err != nil {
return errors.New("could not decode config")
}
*Conf = *tmpConf
return
}

View File

@@ -0,0 +1,59 @@
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
package(default_visibility = ["//visibility:public"])
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 = [
"app_auth_test.go",
"dao_test.go",
"mysql_test.go",
"tree_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/msm/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"app_auth.go",
"dao.go",
"mysql.go",
"tree.go",
],
importpath = "go-common/app/service/main/msm/dao",
tags = ["automanaged"],
deps = [
"//app/service/main/msm/conf:go_default_library",
"//app/service/main/msm/model:go_default_library",
"//library/conf/env:go_default_library",
"//library/database/sql:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/time:go_default_library",
],
)

View File

@@ -0,0 +1,59 @@
package dao
import (
"context"
"go-common/app/service/main/msm/model"
"go-common/library/log"
)
const (
_allAppInfoSQL = "SELECT app_tree_id,app_id,`limit` FROM app"
_allAppAuthSQL = "SELECT service_tree_id,app_tree_id,rpc_method,http_method,quota,mtime FROM app_auth"
)
// AllAppsInfo AllAppsInfo.
func (d *Dao) AllAppsInfo(c context.Context) (res map[int64]*model.AppInfo, err error) {
rows, err := d.db.Query(c, _allAppInfoSQL)
if err != nil {
log.Error("d.apmDB.Query(app) error(%v)", err)
return
}
defer rows.Close()
res = make(map[int64]*model.AppInfo)
for rows.Next() {
app := &model.AppInfo{}
if err = rows.Scan(&app.AppTreeID, &app.AppID, &app.Limit); err != nil {
log.Error("rows.Scan(app) error(%v)", err)
return
}
res[app.AppTreeID] = app
}
return
}
// AllAppsAuth get all app auth info.
func (d *Dao) AllAppsAuth(c context.Context) (res map[int64]map[int64]*model.AppAuth, err error) {
rows, err := d.db.Query(c, _allAppAuthSQL)
if err != nil {
log.Error("d.apmDB.Query(app_auth) error(%v)", err)
return
}
defer rows.Close()
res = make(map[int64]map[int64]*model.AppAuth)
for rows.Next() {
appAuth := &model.AppAuth{}
if err = rows.Scan(&appAuth.ServiceTreeID, &appAuth.AppTreeID, &appAuth.RPCMethod, &appAuth.HTTPMethod, &appAuth.Quota, &appAuth.MTime); err != nil {
log.Error("rows.Scan(appAuth) error(%v)", err)
return
}
if _, b := res[appAuth.ServiceTreeID]; b {
res[appAuth.ServiceTreeID][appAuth.AppTreeID] = appAuth
} else {
authMap := make(map[int64]*model.AppAuth)
authMap[appAuth.AppTreeID] = appAuth
res[appAuth.ServiceTreeID] = authMap
}
}
return
}

View File

@@ -0,0 +1,34 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoAllAppsInfo(t *testing.T) {
var (
c = context.Background()
)
convey.Convey("AllAppsInfo", t, func(ctx convey.C) {
res, err := d.AllAppsInfo(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)
})
})
}
func TestDaoAllAppsAuth(t *testing.T) {
var (
c = context.Background()
)
convey.Convey("AllAppsAuth", t, func(ctx convey.C) {
res, err := d.AllAppsAuth(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)
})
})
}

View File

@@ -0,0 +1,33 @@
package dao
import (
"go-common/app/service/main/msm/conf"
"go-common/library/database/sql"
bm "go-common/library/net/http/blademaster"
)
// Dao dao.
type Dao struct {
client *bm.Client
db *sql.DB
treeHost string
platformID string
}
// New new dao.
func New(c *conf.Config) *Dao {
d := &Dao{
db: sql.NewMySQL(c.Mysql),
client: bm.NewClient(c.HTTPClient),
treeHost: c.Tree.Host,
platformID: c.Tree.PlatformID,
}
return d
}
// Close close mysql resource.
func (d *Dao) Close() {
if d.db != nil {
d.db.Close()
}
}

View File

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

View File

@@ -0,0 +1,114 @@
package dao
import (
"container/list"
"context"
"go-common/app/service/main/msm/model"
"go-common/library/log"
xtime "go-common/library/time"
)
const (
_codesSQL = "SELECT code, message, mtime FROM codes"
_diffCodesSQL = "SELECT code, message, mtime FROM codes WHERE mtime > ? ORDER BY mtime LIMIT 100"
_codesLangsSQL = "select a.code,a.message,a.mtime,IFNULL(b.locale,''),IFNULL(b.msg,''),IFNULL(b.mtime,'') as bmtime from codes as a left join code_msg as b on a.id=b.code_id"
)
// Codes get all codes.
func (d *Dao) Codes(c context.Context) (codes map[int]string, lcode *model.Code, err error) {
var (
code int
msg string
tmp int64
mtime xtime.Time
)
rows, err := d.db.Query(c, _codesSQL)
if err != nil {
log.Error("d.db.Query(%v) error(%v)", _codesSQL, err)
return
}
defer rows.Close()
lcode = &model.Code{}
codes = make(map[int]string)
for rows.Next() {
if err = rows.Scan(&code, &msg, &mtime); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
codes[code] = msg
if int64(mtime) > tmp {
lcode.Code = code
lcode.Ver = int64(mtime)
lcode.Msg = msg
tmp = int64(mtime)
}
}
return
}
// Diff get change codes.
func (d *Dao) Diff(c context.Context, ver int64) (vers *list.List, err error) {
var (
code int
msg string
mtime xtime.Time
)
rows, err := d.db.Query(c, _diffCodesSQL, xtime.Time(ver))
if err != nil {
log.Error("d.db.Query(%v) error(%v)", _diffCodesSQL, err)
return
}
defer rows.Close()
vers = list.New()
for rows.Next() {
if err = rows.Scan(&code, &msg, &mtime); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
vers.PushBack(&model.Code{Ver: int64(mtime), Code: code, Msg: msg})
}
return
}
// CodesLang get all codes.
func (d *Dao) CodesLang(c context.Context) (codes map[int]map[string]string, lcode *model.CodeLangs, err error) {
var (
code int
tmp int64
mtime xtime.Time
message string
bl string
bmsg string
bmtime xtime.Time
)
rows, err := d.db.Query(c, _codesLangsSQL)
if err != nil {
log.Error("d.db.Query(%v) error(%v)", _codesLangsSQL, err)
return
}
defer rows.Close()
lcode = &model.CodeLangs{}
codes = make(map[int]map[string]string)
for rows.Next() {
t := make(map[string]string)
bl = ""
if err = rows.Scan(&code, &message, &mtime, &bl, &bmsg, &bmtime); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
t["default"] = message
if len(bl) > 0 {
t[bl] = bmsg
}
codes[code] = t
if int64(mtime) > tmp {
lcode.Code = code
lcode.Ver = int64(mtime)
lcode.Msg = t
tmp = int64(mtime)
}
}
err = rows.Err()
return
}

View File

@@ -0,0 +1,36 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoCodes(t *testing.T) {
var (
c = context.Background()
)
convey.Convey("Codes", t, func(ctx convey.C) {
codes, lcode, err := d.Codes(c)
ctx.Convey("Then err should be nil.codes,lcode should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(lcode, convey.ShouldNotBeNil)
ctx.So(codes, convey.ShouldNotBeNil)
})
})
}
func TestDaoDiff(t *testing.T) {
var (
c = context.Background()
ver = int64(0)
)
convey.Convey("Diff", t, func(ctx convey.C) {
vers, err := d.Diff(c, ver)
ctx.Convey("Then err should be nil.vers should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(vers, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,101 @@
package dao
import (
"context"
"encoding/json"
"fmt"
"net/http"
"strings"
"go-common/app/service/main/msm/model"
"go-common/library/conf/env"
"go-common/library/log"
)
const (
treeUsername = "msm"
treeAuthURL = "/v1/token"
allAppAuthURL = "%s/v1/node/app/secretinfo/%s"
)
func (d *Dao) treeToken(c context.Context) (token string, err error) {
var (
jsonBytes []byte
url = d.treeHost + treeAuthURL
)
body := &struct {
Username string `json:"user_name"`
PlatformID string `json:"platform_id"`
}{
Username: treeUsername,
PlatformID: d.platformID,
}
if jsonBytes, err = json.Marshal(body); err != nil {
log.Error("json.Marshal(body) error(%v)", err)
return
}
req, err := http.NewRequest("POST", url, strings.NewReader(string(jsonBytes)))
if err != nil {
log.Error("http.NewRequest failed", err)
return
}
req.Header.Set("Content-Type", "application/json")
res := &struct {
Code int64 `json:"code"`
Data struct {
Token string `json:"token"`
Username string `json:"user_name"`
Secret string `json:"secret"`
Expired int64 `json:"expired"`
} `json:"data"`
Message string `json:"message"`
Status int `json:"status"`
}{}
if err = d.client.Do(c, req, res); err != nil {
log.Error("service-tree client Do failed", err)
return
}
if res.Code != 90000 {
log.Error("service-tree client Do failed", err)
return
}
token = res.Data.Token
return
}
// TreeAppInfo TreeAppInfo.
func (d *Dao) TreeAppInfo(c context.Context) (appInfo map[int64]*model.AppToken, err error) {
var (
token string
url = fmt.Sprintf(allAppAuthURL, d.treeHost, env.DeployEnv)
)
appInfo = make(map[int64]*model.AppToken)
if token, err = d.treeToken(c); err != nil {
return
}
req, err := http.NewRequest("GET", url, nil)
if err != nil {
log.Error("http.NewRequest failed", err)
return
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Authorization-Token", token)
res := &struct {
Code int `json:"code"`
Data []*model.AppToken `json:"data"`
Message string `json:"message"`
Status int `json:"status"`
}{}
if err = d.client.Do(c, req, res); err != nil {
log.Error("service-tree client Do failed", err)
return
}
if res.Code != 90000 {
log.Error("service-tree client Do failed", err)
return
}
for _, auth := range res.Data {
appInfo[auth.AppTreeID] = auth
}
return
}

View File

@@ -0,0 +1,34 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaotreeToken(t *testing.T) {
var (
c = context.Background()
)
convey.Convey("treeToken", t, func(ctx convey.C) {
token, err := d.treeToken(c)
ctx.Convey("Then err should be nil.token should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(token, convey.ShouldNotBeNil)
})
})
}
func TestDaoTreeAppInfo(t *testing.T) {
var (
c = context.Background()
)
convey.Convey("TreeAppInfo", t, func(ctx convey.C) {
appInfo, err := d.TreeAppInfo(c)
ctx.Convey("Then err should be nil.appInfo should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(appInfo, convey.ShouldNotBeNil)
})
})
}

View File

@@ -0,0 +1,42 @@
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
package(default_visibility = ["//visibility:public"])
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_library(
name = "go_default_library",
srcs = [
"app_auth.go",
"config.go",
"credential.go",
"ecode.go",
"http.go",
],
importpath = "go-common/app/service/main/msm/http",
tags = ["automanaged"],
deps = [
"//app/service/main/msm/conf:go_default_library",
"//app/service/main/msm/model:go_default_library",
"//app/service/main/msm/service:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/middleware/verify:go_default_library",
],
)

View File

@@ -0,0 +1,27 @@
package http
import (
"go-common/app/service/main/msm/model"
bm "go-common/library/net/http/blademaster"
)
func scope(c *bm.Context) {
var (
err error
scopeMap map[int64]*model.Scope
param = new(struct {
AppTreeID int64 `form:"app_tree_id" validate:"gt=0"`
})
)
if err = c.Bind(param); err != nil {
return
}
if scopeMap, err = svr.ServiceScopes(c, param.AppTreeID); err != nil {
c.JSON(nil, err)
return
}
data := make(map[string]interface{}, 2)
data["service_tree_id"] = param.AppTreeID
data["scopes"] = scopeMap
c.JSON(data, nil)
}

View File

@@ -0,0 +1,37 @@
package http
import (
bm "go-common/library/net/http/blademaster"
)
// push config update
func push(c *bm.Context) {
var (
err error
param = new(struct {
Ver int64 `form:"version" validate:"gte=0"`
App string `form:"service" validate:"required"`
BVer string `form:"build_ver" validate:"required"`
Env string `form:"environment" validate:"required"`
})
)
if err = c.Bind(param); err != nil {
return
}
c.JSON(nil, svr.Push(c, param.App, param.BVer, param.Env, param.Ver))
}
func setToken(c *bm.Context) {
var (
err error
param = new(struct {
App string `form:"service" validate:"required"`
Token string `form:"token" validate:"required"`
Env string `form:"environment" validate:"required"`
})
)
if err = c.Bind(param); err != nil {
return
}
c.JSON(nil, svr.SetToken(c, param.App, param.Env, param.Token))
}

View File

@@ -0,0 +1,43 @@
package http
import (
"strconv"
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
)
const (
_contentType = "Content-Type"
_urlJSON = "application/json"
)
// credential verify.
func credential(ctx *bm.Context) {
var (
appIDStr string
signature string
)
req := ctx.Request
params := req.Form
header := req.Header
if header.Get(_contentType) == _urlJSON {
appIDStr = header.Get("App-Tree-ID")
signature = header.Get("Signature")
header.Del("Signature")
} else {
appIDStr = params.Get("app_tree_id")
signature = params.Get("signature")
params.Del("signature")
}
appID, _ := strconv.ParseInt(appIDStr, 10, 64)
if appID == 0 || signature == "" {
ctx.JSON(nil, ecode.RequestErr)
ctx.Abort()
return
}
if ok := svr.CheckSign(appID, signature); !ok {
ctx.JSON(nil, ecode.SignCheckErr)
ctx.Abort()
}
}

View File

@@ -0,0 +1,42 @@
package http
import (
"go-common/app/service/main/msm/model"
bm "go-common/library/net/http/blademaster"
)
func codes(c *bm.Context) {
var (
err error
code *model.Codes
param = new(struct {
Ver int64 `form:"ver"`
})
)
if err = c.Bind(param); err != nil {
return
}
if code, err = svr.Codes(c, param.Ver); err != nil {
c.JSON(nil, err)
return
}
c.JSON(code, nil)
}
func codesLangs(c *bm.Context) {
var (
err error
code *model.CodesLangs
param = new(struct {
Ver int64 `form:"ver"`
})
)
if err = c.Bind(param); err != nil {
return
}
if code, err = svr.CodesLangs(c, param.Ver); err != nil {
c.JSON(nil, err)
return
}
c.JSON(code, nil)
}

View File

@@ -0,0 +1,56 @@
package http
import (
"net/http"
"go-common/app/service/main/msm/conf"
"go-common/app/service/main/msm/service"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/verify"
)
var (
vfySvr *verify.Verify
svr *service.Service
)
// Init init config.
func Init(c *conf.Config, s *service.Service) {
svr = s
vfySvr = verify.New(nil)
engine := bm.DefaultServer(c.BM)
oldRouter(engine)
innerRouter(engine)
if err := engine.Start(); err != nil {
log.Error("engine.Start error(%v)", err)
panic(err)
}
}
func oldRouter(e *bm.Engine) {
e.Ping(ping)
group := e.Group("/x/v1/msm", vfySvr.Verify)
{
group.GET("/codes/2", codes)
group.POST("/conf/push", push)
group.POST("/conf/setToken", setToken)
group.GET("/codes/langs", codesLangs)
}
}
func innerRouter(e *bm.Engine) {
group := e.Group("/x/internal/msm/v1")
{
group.GET("/codes/2", vfySvr.Verify, codes)
group.GET("/auth/scope", credential, scope)
}
}
// ping check server ok.
func ping(c *bm.Context) {
if svr.Ping() != nil {
log.Error("service ping error")
c.AbortWithStatus(http.StatusServiceUnavailable)
}
}

View File

@@ -0,0 +1,31 @@
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
package(default_visibility = ["//visibility:public"])
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_library(
name = "go_default_library",
srcs = [
"app_auth.go",
"model.go",
],
importpath = "go-common/app/service/main/msm/model",
tags = ["automanaged"],
deps = ["//library/time:go_default_library"],
)

View File

@@ -0,0 +1,39 @@
package model
import (
xtime "go-common/library/time"
)
// AppInfo App info.
type AppInfo struct {
AppTreeID int64 `json:"app_tree_id"`
AppID string `json:"app_id"`
Limit int32 `json:"limit"`
MTime xtime.Time `json:"mtime"`
}
// AppAuth AppAuth.
type AppAuth struct {
ServiceTreeID int64 `json:"service_tree_id"`
AppTreeID int64 `json:"app_tree_id"`
RPCMethod string `json:"rpc_method"`
HTTPMethod string `json:"http_method"`
Quota int32 `json:"quota"`
MTime xtime.Time `json:"mtime"`
}
// Scope Scope.
type Scope struct {
AppTreeID int64 `json:"app_tree_id"`
RPCMethods []string `json:"rpc_methods"`
HTTPMethods []string `json:"http_methods"`
Quota int32 `json:"quota"`
Sign string `json:"sign"`
}
// AppToken AppToken.
type AppToken struct {
AppTreeID int64 `json:"app_tree_id"`
AppID string `json:"app_id"`
AppAuth string `json:"app_auth"`
}

View File

@@ -0,0 +1,109 @@
package model
import (
"container/list"
)
const (
// CodePlatDefaut db common plat code.
CodePlatDefaut = 1
// CodePlatDefautMsg db common plat msg.
CodePlatDefautMsg = "common"
// CodeDelStatus db delete status.
CodeDelStatus = 2
// HostOffline host offline state.
HostOffline = 0
)
// RPC rpc node value.
type RPC struct {
Proto string `json:"Proto"`
Addr string `json:"Addr"`
Group string `json:"Group"`
Weight int `json:"Weight"`
}
// Code ver and message.
type Code struct {
Ver int64
Code int
Msg string
}
// Codes all codes local map cache.
type Codes struct {
Ver int64
MD5 string
Code map[int]string
}
// Version list and map.
type Version struct {
List *list.List
Map map[int64]*list.Element
}
// Databus databus rule.
type Databus struct {
Topic string `json:"topic"`
Group string `json:"group"`
Cluster string `json:"cluster"`
Business string `json:"business"`
Operation int8 `json:"operation"`
Leader string `json:"leader"`
Phone string `json:"phone"`
Email string `json:"email"`
AlarmSwitch int8 `json:"alarmSwitch"`
Users string `json:"users"`
AlarmRule string `json:"alarmRule"`
}
// Databuss databuss rules.
type Databuss struct {
Rules []*Databus `json:"rules"`
MD5 string `json:"md5"`
}
// Limit limit.
type Limit struct {
Burst int `json:"burst"`
Rate float64 `json:"rate"`
}
// Limits limits.
type Limits struct {
Apps map[string]*Limit `json:"apps"`
MD5 string `json:"md5"`
}
// Host host.
type Host struct {
Name string `json:"hostname"`
State int `json:"state"`
}
//CodesLangs ...
type CodesLangs struct {
Ver int64
MD5 string
Code map[int]map[string]string
}
// //Langs ...
// type Langs struct {
// Default string `json:"default"`
// Localeds []*Locale
// }
//Locale ...
// type Locale struct {
// Locale string
// Message string
// }
//CodeLangs ...
type CodeLangs struct {
Ver int64
Code int
Msg map[string]string
}

View File

@@ -0,0 +1,64 @@
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
package(default_visibility = ["//visibility:public"])
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 = [
"app_auth_test.go",
"config_test.go",
"ecode_test.go",
"router_test.go",
"service_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/infra/config/model:go_default_library",
"//app/service/main/msm/conf:go_default_library",
"//app/service/main/msm/model:go_default_library",
"//library/log:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"app_auth.go",
"config.go",
"ecode.go",
"router.go",
"service.go",
],
importpath = "go-common/app/service/main/msm/service",
tags = ["automanaged"],
deps = [
"//app/infra/config/model:go_default_library",
"//app/infra/config/rpc/client:go_default_library",
"//app/service/main/msm/conf:go_default_library",
"//app/service/main/msm/dao:go_default_library",
"//app/service/main/msm/model:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
],
)

View File

@@ -0,0 +1,125 @@
package service
import (
"context"
"crypto/hmac"
"crypto/sha1"
"encoding/hex"
"fmt"
"strings"
"time"
"go-common/app/service/main/msm/model"
"go-common/library/log"
)
const (
_hmacTreeID = "%d%d"
_msmTreeID = int64(2888)
)
func signature(appID, serviceID int64, appAuth string) string {
hmacTreeIDStr := fmt.Sprintf(_hmacTreeID, appID, serviceID)
mac := hmac.New(sha1.New, []byte(appAuth))
mac.Write([]byte(hmacTreeIDStr))
return hex.EncodeToString(mac.Sum(nil))
}
// ServiceScopes ServiceScopes.
func (s *Service) ServiceScopes(c context.Context, appTreeID int64) (res map[int64]*model.Scope, err error) {
res, ok := s.scopeMap[appTreeID]
if !ok {
res = make(map[int64]*model.Scope)
}
return
}
func (s *Service) updateScope() (err error) {
var (
c = context.TODO()
appAuthMap map[int64]map[int64]*model.AppAuth
appTokenMap map[int64]*model.AppToken
)
scopeMap := make(map[int64]map[int64]*model.Scope)
if appAuthMap, err = s.dao.AllAppsAuth(c); err != nil {
log.Error("The update scope process was abnormal, was blocked in DB!")
return
}
if appTokenMap, err = s.dao.TreeAppInfo(c); err != nil {
log.Error("The update scope process was abnormal, was blocked in service-tree service!")
return
}
for sTreeID, sAuthMap := range appAuthMap {
_, ok := appTokenMap[sTreeID]
if !ok {
log.Warn("This app(%d) has no app_auth records in the service-tree service.", sTreeID)
continue
}
si := make(map[int64]*model.Scope)
for appID, appAuth := range sAuthMap {
appToken, b := appTokenMap[appID]
if !b {
log.Warn("This app(%d) has no app_auth records in the service-tree service.", appID)
continue
}
scope := &model.Scope{
AppTreeID: appID,
RPCMethods: strings.Split(appAuth.RPCMethod, ","),
HTTPMethods: strings.Split(appAuth.HTTPMethod, ","),
Quota: appAuth.Quota,
Sign: signature(appID, sTreeID, appToken.AppAuth),
}
si[appID] = scope
}
scopeMap[sTreeID] = si
}
s.scopeMap = scopeMap
return
}
// updateScopeproc update scope info proc.
func (s *Service) updateScopeproc() {
for {
time.Sleep(time.Minute)
s.updateScope()
}
}
// updateMsmScopeproc update scope info proc.
func (s *Service) updateMsmScopeproc() {
for {
time.Sleep(time.Minute)
s.updateMsmScope()
}
}
func (s *Service) updateMsmScope() (err error) {
var (
c = context.TODO()
appTokenMap map[int64]*model.AppToken
)
scopes := make(map[int64]*model.Scope)
if appTokenMap, err = s.dao.TreeAppInfo(c); err != nil {
log.Error("The update scope process was abnormal, was blocked in service-tree service!")
return
}
for treeID, appToken := range appTokenMap {
scope := &model.Scope{
AppTreeID: treeID,
Sign: signature(treeID, _msmTreeID, appToken.AppAuth),
}
scopes[treeID] = scope
}
s.msmScope = scopes
return
}
// CheckSign CheckSign.
func (s *Service) CheckSign(appID int64, sign string) bool {
scope, ok := s.msmScope[appID]
if !ok || scope == nil {
log.Error("CheckSign(%d) error(no msmTree info.)", appID)
return false
}
return sign == scope.Sign
}

View File

@@ -0,0 +1,38 @@
package service
import (
"context"
"testing"
"go-common/app/service/main/msm/model"
. "github.com/smartystreets/goconvey/convey"
)
func TestScope(t *testing.T) {
var (
serviceTreeID = int64(22)
appTreeID = int64(33)
appAuth = "qwertyuiop"
sign = "123455667"
c = context.TODO()
)
scope := &model.Scope{
AppTreeID: appTreeID,
RPCMethods: append([]string{"RPC.Info", "RPC.Scope"}),
HTTPMethods: append([]string{"/test/info", "/test/add"}),
Quota: 5000,
Sign: signature(appTreeID, serviceTreeID, appAuth),
}
real := make(map[int64]*model.Scope)
real[serviceTreeID] = scope
Convey("err should return nil and id greater than zero", t, func() {
res, err := svr.ServiceScopes(c, serviceTreeID)
So(err, ShouldBeNil)
So(res, ShouldEqual, real)
})
Convey("compare sign is equal", t, func() {
b := svr.CheckSign(14212, sign)
So(b, ShouldBeFalse)
})
}

View File

@@ -0,0 +1,35 @@
package service
import (
"context"
"go-common/app/infra/config/model"
"go-common/library/log"
)
// Push push new ver to config-service.
func (s *Service) Push(c context.Context, app, bver, env string, ver int64) (err error) {
arg := &model.ArgConf{
App: app,
BuildVer: bver,
Ver: ver,
Env: env,
}
if err = s.confSvr.Push(c, arg); err != nil {
log.Error("push(%v) error(%v)", arg, err)
}
return
}
// SetToken set token to config-service.
func (s *Service) SetToken(c context.Context, app, env, token string) (err error) {
arg := &model.ArgToken{
App: app,
Token: token,
Env: env,
}
if err = s.confSvr.SetToken(c, arg); err != nil {
log.Error("SetToken(%v) error(%v)", arg, err)
}
return
}

View File

@@ -0,0 +1,32 @@
package service
import (
"context"
"testing"
"go-common/app/infra/config/model"
"go-common/library/log"
)
func TestConfig(t *testing.T) {
arg := &model.ArgConf{
App: "zjx_test",
BuildVer: "1_0_0_0",
Ver: 62,
Env: "3",
}
if err := svr.confSvr.Push(context.TODO(), arg); err != nil {
log.Error("push(%v) error(%v)", arg, err)
t.FailNow()
}
argT := &model.ArgToken{
App: "zjx_test",
Env: "3",
Token: "123",
}
if err := svr.confSvr.SetToken(context.TODO(), argT); err != nil {
log.Error("push(%v) error(%v)", argT, err)
t.FailNow()
}
}

View File

@@ -0,0 +1,230 @@
package service
import (
"container/list"
"context"
"crypto/md5"
"encoding/hex"
"encoding/json"
"time"
"go-common/app/service/main/msm/model"
"go-common/library/ecode"
"go-common/library/log"
)
// Codes get codes.
func (s *Service) Codes(c context.Context, rver int64) (*model.Codes, error) {
var (
e *list.Element
ok bool
)
codes := s.codes.Load().(*model.Codes)
if rver == 0 {
return codes, nil
}
if rver == codes.Ver {
return nil, ecode.NotModified
}
code := make(map[int]string)
s.lock.RLock()
if e, ok = s.version.Map[rver]; !ok {
s.lock.RUnlock()
return codes, nil
}
for ; e != nil; e = e.Next() {
ver := e.Value.(*model.Code)
if ver.Ver <= rver {
continue
}
code[ver.Code] = ver.Msg
}
s.lock.RUnlock()
return s.newCodes(code, codes.Ver)
}
// updateproc update proc.每2分钟拉一次增量每小时拉一次全量
func (s *Service) updateproc() {
var last = time.Now()
for {
cur := time.Now()
if cur.Sub(last) > time.Hour {
if err := s.all(); err != nil {
time.Sleep(2 * time.Second)
continue
}
last = cur
} else {
if err := s.diff(); err != nil {
time.Sleep(2 * time.Second)
continue
}
}
time.Sleep(120 * time.Second)
}
}
func (s *Service) newCodes(code map[int]string, ver int64) (*model.Codes, error) {
bytes, err := json.Marshal(code)
if err != nil {
log.Error("json.Marshal(%v) error(%v)", code, err)
return nil, err
}
mb := md5.Sum(bytes)
return &model.Codes{Ver: ver, Code: code, MD5: hex.EncodeToString(mb[:])}, nil
}
// all get all codes.//全量获取
func (s *Service) all() (err error) {
var (
lcode *model.Code
ncodes *model.Codes
code map[int]string
)
if code, lcode, err = s.dao.Codes(context.Background()); err != nil {
return
}
if ncodes, err = s.newCodes(code, lcode.Ver); err != nil {
return
}
s.codes.Store(ncodes)
// save last ver into list.
s.lock.Lock()
l := s.version.List
m := s.version.Map
if _, ok := m[lcode.Ver]; ok {
s.lock.Unlock()
return
}
l.PushBack(lcode)
m[lcode.Ver] = l.Back()
s.lock.Unlock()
return
}
// diff get change code.增量获取
func (s *Service) diff() (err error) {
var (
vers *list.List
ncodes *model.Codes
ocodes = s.codes.Load().(*model.Codes)
code = copy(ocodes.Code)
)
if vers, err = s.dao.Diff(context.Background(), ocodes.Ver); err != nil {
return
} else if vers.Len() == 0 {
return
}
// merge diff ecode
for e := vers.Front(); e != nil; e = e.Next() {
ver := e.Value.(*model.Code)
if ver.Ver < ocodes.Ver {
continue
}
code[ver.Code] = ver.Msg
}
// save global ecode
if ncodes, err = s.newCodes(code, vers.Back().Value.(*model.Code).Ver); err != nil {
return
}
s.codes.Store(ncodes)
// push diff to vers list and trim
s.lock.Lock()
m := s.version.Map
l := s.version.List
for e := vers.Front(); e != nil; e = e.Next() {
l.PushBack(e.Value)
ver := e.Value.(*model.Code).Ver
m[ver] = l.Back()
}
for i := 0; i < l.Len()-_maxVerNum; i++ {
e := l.Front()
l.Remove(e)
delete(m, e.Value.(*model.Code).Ver)
}
s.lock.Unlock()
return
}
func copy(src map[int]string) (dst map[int]string) {
dst = make(map[int]string)
for k, v := range src {
dst[k] = v
}
return
}
// CodesLangs get codes.
func (s *Service) CodesLangs(c context.Context, rver int64) (*model.CodesLangs, error) {
var (
e *list.Element
ok bool
)
codes := s.langsCodes.Load().(*model.CodesLangs)
if rver == 0 {
return codes, nil
}
if rver == codes.Ver {
return nil, ecode.NotModified
}
code := make(map[int]map[string]string)
s.langsLock.RLock()
if e, ok = s.langsVersion.Map[rver]; !ok {
s.langsLock.RUnlock()
return codes, nil
}
for ; e != nil; e = e.Next() {
ver := e.Value.(*model.CodeLangs)
if ver.Ver <= rver {
continue
}
code[ver.Code] = ver.Msg
}
s.langsLock.RUnlock()
return s.newCodesLang(code, codes.Ver)
}
// all get all codes.//全量获取
func (s *Service) allLang() (err error) {
var (
lcode *model.CodeLangs
ncodes *model.CodesLangs
code map[int]map[string]string
)
if code, lcode, err = s.dao.CodesLang(context.Background()); err != nil {
return
}
if ncodes, err = s.newCodesLang(code, lcode.Ver); err != nil {
return
}
s.langsCodes.Store(ncodes)
// save last ver into list.
s.langsLock.Lock()
l := s.langsVersion.List
m := s.langsVersion.Map
if _, ok := m[lcode.Ver]; ok {
s.langsLock.Unlock()
return
}
l.PushBack(lcode)
m[lcode.Ver] = l.Back()
s.langsLock.Unlock()
return
}
func (s *Service) newCodesLang(code map[int]map[string]string, ver int64) (*model.CodesLangs, error) {
bytes, err := json.Marshal(code)
if err != nil {
log.Error("json.Marshal(%v) error(%v)", code, err)
return nil, err
}
mb := md5.Sum(bytes)
return &model.CodesLangs{Ver: ver, Code: code, MD5: hex.EncodeToString(mb[:])}, nil
}
func (s *Service) updateLangproc() {
for {
time.Sleep(300 * time.Second)
s.allLang()
}
}

View File

@@ -0,0 +1,72 @@
package service
import (
"context"
"testing"
"go-common/app/service/main/msm/model"
)
func TestService(t *testing.T) {
testIncUpdate(t, svr)
testCodes(t, svr)
testUpdate(t, svr)
testAllCodes(t, svr)
}
func testIncUpdate(t *testing.T, svr *Service) {
codes := svr.codes.Load().(*model.Codes)
codes.Ver = 1499742647
if err := svr.diff(); err != nil {
t.Logf("update(%v)", err)
t.FailNow()
}
}
func testCodes(t *testing.T, svr *Service) {
if code, err := svr.Codes(context.TODO(), 1499742647); err != nil {
t.Logf("codes() error(%v)", err)
t.FailNow()
} else {
t.Logf("update() data(%v) ", code)
}
}
func testUpdate(t *testing.T, svr *Service) {
if err := svr.all(); err != nil {
t.Logf("update(%v)", err)
t.FailNow()
}
}
func testAllCodes(t *testing.T, svr *Service) {
if code, err := svr.Codes(context.TODO(), 0); err != nil {
t.Logf("codes() error(%v)", err)
t.FailNow()
} else {
t.Logf("update() data(%v)", code)
}
}
func BenchmarkAllCodes(b *testing.B) {
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if _, err := svr.Codes(context.TODO(), 0); err != nil {
b.Logf("codes() error(%v)", err)
b.FailNow()
}
}
})
}
func BenchmarkCodes(b *testing.B) {
//svr.all()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
//svr.diff()
if _, err := svr.Codes(context.TODO(), svr.codes.Load().(*model.Codes).Ver); err != nil {
b.Logf("codes() error(%v)", err)
b.FailNow()
}
}
})
}

View File

@@ -0,0 +1,40 @@
package service
import (
"context"
"go-common/app/service/main/msm/model"
"go-common/library/ecode"
)
// Limits get limits.
func (s *Service) Limits(c context.Context, family, hmd5 string) (*model.Limits, error) {
// var (
// id int64
// bytes []byte
// num int
// err error
// limits map[string]*model.Limit
// )
// if num, err = s.dao.HostAmount(c, family); err != nil {
// log.Error("HostAmount() error(%v)", err)
// return nil, err
// }
// if id, err = s.dao.LimitID(c, family); err != nil {
// log.Error("LimitID() error(%v)", err)
// return nil, err
// }
// if limits, err = s.dao.LimitBusiness(c, id, num); err != nil {
// log.Error("LimitBusiness() error(%v)", err)
// return nil, err
// }
// if bytes, err = json.Marshal(limits); err != nil {
// log.Error("json.Marshal(%v) error(%v)", limits, err)
// return nil, err
// }
// mb := md5.Sum(bytes)
// if md5 := hex.EncodeToString(mb[:]); md5 != hmd5 {
// return &model.Limits{Apps: limits, MD5: md5}, nil
// }
return nil, ecode.NotModified
}

View File

@@ -0,0 +1,16 @@
package service
import (
"context"
"fmt"
"testing"
)
func TestService_Limits(t *testing.T) {
if res, err := svr.Limits(context.TODO(), "msm-service", ""); err != nil {
t.Logf("svr.Limits() error(%v)", err)
t.FailNow()
} else {
fmt.Println(res)
}
}

View File

@@ -0,0 +1,77 @@
package service
import (
"container/list"
"sync"
"sync/atomic"
confrpc "go-common/app/infra/config/rpc/client"
"go-common/app/service/main/msm/conf"
"go-common/app/service/main/msm/dao"
"go-common/app/service/main/msm/model"
)
const (
_maxVerNum = 100
)
// Service service
type Service struct {
c *conf.Config
// rpcconf config service Rpc
confSvr *confrpc.Service2
dao *dao.Dao
// ecode
lock sync.RWMutex
version *model.Version
codes atomic.Value
scopeMap map[int64]map[int64]*model.Scope
msmScope map[int64]*model.Scope
// langs
langsLock sync.RWMutex
langsVersion *model.Version
langsCodes atomic.Value
}
// New new a service
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
confSvr: confrpc.New2(c.ConfSvr),
dao: dao.New(c),
version: &model.Version{List: list.New(), Map: make(map[int64]*list.Element)},
scopeMap: make(map[int64]map[int64]*model.Scope),
msmScope: make(map[int64]*model.Scope),
langsVersion: &model.Version{List: list.New(), Map: make(map[int64]*list.Element)},
}
if err := s.all(); err != nil {
panic(err)
}
if err := s.allLang(); err != nil {
panic(err)
}
if err := s.updateScope(); err != nil {
panic(err)
}
if err := s.updateMsmScope(); err != nil {
panic(err)
}
go s.updateLangproc()
go s.updateproc()
go s.updateScopeproc()
go s.updateMsmScopeproc()
return
}
// Ping check server ok.
func (s *Service) Ping() (err error) {
return
}
// Close close resource
func (s *Service) Close() {
s.dao.Close()
}

View File

@@ -0,0 +1,23 @@
package service
import (
"flag"
"fmt"
"path/filepath"
"testing"
"go-common/app/service/main/msm/conf"
)
var (
svr *Service
)
func TestMain(m *testing.M) {
flag.Parse()
dir, _ := filepath.Abs("../cmd/msm-service-example.toml")
fmt.Println(dir)
flag.Set("conf", dir)
conf.Init()
svr = New(conf.Conf)
}