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/job/main/passport-game-cloud/cmd:all-srcs",
"//app/job/main/passport-game-cloud/conf:all-srcs",
"//app/job/main/passport-game-cloud/dao:all-srcs",
"//app/job/main/passport-game-cloud/http:all-srcs",
"//app/job/main/passport-game-cloud/model:all-srcs",
"//app/job/main/passport-game-cloud/service:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,23 @@
## passport-game-cloud-job
#### Version 1.5.0
> 1.增加清除用户手机邮箱缓存逻辑
#### Version 1.4.0
> 1.change to bm router
#### Version 1.3.0
> 1.ignore duplicate entry error when add or update aso account fails
> 2.change time location when parsing mtime for prom
#### Version 1.2.0
> 1.remove account table usage
> 2.change perm model to pb
> 3.set token cache instead of dropping
> 4.add interval prom for token, member, aso_account, encrypt_trans
#### Version 1.1.0
> 1.move to krotos
#### Version 1.0.0
> 1.版本初始化

View File

@@ -0,0 +1,10 @@
# Owner
wanghuan01
# Author
wanghuan01
wutao
wucongyou
# Reviewer
wanghuan01

View File

@@ -0,0 +1,16 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- wanghuan01
- wucongyou
- wutao
labels:
- job
- job/main/passport-game-cloud
- main
options:
no_parent_owners: true
reviewers:
- wanghuan01
- wucongyou
- wutao

View File

@@ -0,0 +1,12 @@
## passport-game-cloud-job
#### 项目简介
> 1.游戏云账号云job主要用于消费源站数据变更和通知游戏删除缓存
#### 编译环境
> 请只用golang v1.8.x以上版本编译执行。
#### 依赖包
> 1.公共包go-common
#### 特别说明

View File

@@ -0,0 +1,41 @@
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_binary",
)
go_library(
name = "go_default_library",
srcs = ["main.go"],
data = ["passport-game-cloud-job.toml"],
importpath = "go-common/app/job/main/passport-game-cloud/cmd",
tags = ["automanaged"],
visibility = ["//visibility:private"],
deps = [
"//app/job/main/passport-game-cloud/conf:go_default_library",
"//app/job/main/passport-game-cloud/http:go_default_library",
"//app/job/main/passport-game-cloud/service:go_default_library",
"//library/log:go_default_library",
"//library/net/trace:go_default_library",
],
)
go_binary(
name = "cmd",
embed = [":go_default_library"],
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"],
)

View File

@@ -0,0 +1,48 @@
package main
import (
"flag"
"os"
"os/signal"
"syscall"
"time"
"go-common/app/job/main/passport-game-cloud/conf"
"go-common/app/job/main/passport-game-cloud/http"
"go-common/app/job/main/passport-game-cloud/service"
"go-common/library/log"
"go-common/library/net/trace"
)
func main() {
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
log.Init(conf.Conf.Xlog)
defer log.Close()
trace.Init(conf.Conf.Tracer)
defer trace.Close()
// service init
srv := service.New(conf.Conf)
http.Init(conf.Conf, srv)
// signal handler
log.Info("passport-game-cloud-job start")
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
s := <-c
log.Info("passport-game-cloud-job get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
srv.Close()
time.Sleep(time.Second * 2)
log.Info("passport-game-cloud-job exit")
return
case syscall.SIGHUP:
// TODO reload
default:
return
}
}
}

View File

@@ -0,0 +1,118 @@
# This is a TOML document. Boom.
version = "1.0.0"
#user = "noboby"
#dir = "./"
#perf = "0.0.0.0:7400"
family = "passport-game-cloud-job"
env = "qa"
#[xlog]
#dir = "/data/log/passport-game-cloud-job"
#
#[tracer]
#family = "passport-game-cloud-job"
#proto = "unixgram"
#addr = "/var/run/dapper-collect/dapper-collect.sock"
#[multiHTTP]
#[multiHTTP.inner]
#addrs = ["0.0.0.0:7401"]
#maxListen = 1000
[game]
# NOTE: the conf item appIDs represents the game app id list,
# the app id 876 will always be the first item of the the final game app id list,
# even if it's not configured in this file or configured in other order.
appIDs = [876,900]
delCacheURI = "http://p.biligame.com/api/notify/purge.cache"
[game.client]
key = "ebbec09cd271049e"
secret = "test"
dial = "500ms"
timeout = "1s"
keepAlive = "60s"
timer = 10
[game.client.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[db.cloud]
addr = "172.16.33.205:3306"
dsn = "account:wx2U1MwXRyWEuURw@tcp(172.16.33.205:3306)/member_app1?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 5
idle = 2
queryTimeout = "1s"
execTimeout = "2s"
tranTimeout = "2s"
[db.cloud.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[memcache]
name = "passport-game-cloud-job"
proto = "tcp"
addr = "172.16.33.54:21211"
idle = 5
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "10h"
[group]
[group.binLog]
size = 200
num = 32
ticker = "1s"
chan = 1024
[group.encryptTrans]
size = 200
num = 32
ticker = "1s"
chan = 1024
[databus]
[databus.binLogSub]
key = "0QEO9F8JuuIxZzNDvklH"
secret = "0QEO9F8JuuIxZzNDvklI"
group = "PassportGame-UGC-S"
topic = "PassportGame-T"
action = "sub"
offset = "old"
buffer = 2048
name = "passport-game-cloud-job/databus"
proto = "tcp"
addr = "172.16.33.158:6205"
idle = 1
active = 1
dialTimeout = "1s"
readTimeout = "60s"
writeTimeout = "1s"
idleTimeout = "10s"
[databus.encryptTransSub]
key = "0QEO9F8JuuIxZzNDvklH"
secret = "0QEO9F8JuuIxZzNDvklI"
group = "PassportGameTrans-ENCRYPT-S"
topic = "PassportGameTrans-T"
action = "sub"
offset = "old"
buffer = 2048
name = "passport-game-cloud-job/databus"
proto = "tcp"
addr = "172.16.33.158:6205"
idle = 1
active = 1
dialTimeout = "1s"
readTimeout = "60s"
writeTimeout = "1s"
idleTimeout = "10s"

View File

@@ -0,0 +1,37 @@
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["conf.go"],
importpath = "go-common/app/job/main/passport-game-cloud/conf",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/cache/memcache:go_default_library",
"//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/trace:go_default_library",
"//library/queue/databus:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/BurntSushi/toml: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,138 @@
package conf
import (
"errors"
"flag"
"go-common/library/cache/memcache"
"go-common/library/conf"
"go-common/library/database/sql"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/trace"
"go-common/library/queue/databus"
"go-common/library/time"
"github.com/BurntSushi/toml"
)
var (
confPath string
// Conf conf.
Conf = &Config{}
client *conf.Client
)
// Config config.
type Config struct {
// Xlog log
Xlog *log.Config
// Tracer tracer
Tracer *trace.Config
// DB db
DB *DB
// Memcache memcache
Memcache *Memcache
// Game
Game *Game
// HTTP
BM *bm.ServerConfig
// Group
Group *Group
// DataBus databus
DataBus *DataBus
}
// Game game notify conf.
type Game struct {
AppIDs []int32
DelCacheURI string
Client *bm.ClientConfig
}
// Group multi group config collection.
type Group struct {
BinLog *GroupConfig
EncryptTrans *GroupConfig
}
// GroupConfig group config.
type GroupConfig struct {
// Size merge size
Size int
// Num merge goroutine num
Num int
// Ticker duration of submit merges when no new message
Ticker time.Duration
// Chan size of merge chan and done chan
Chan int
}
// DataBus databus infomation
type DataBus struct {
BinLogSub *databus.Config
EncryptTransSub *databus.Config
}
// DB db config.
type DB struct {
Cloud *sql.Config
}
// Memcache general memcache config.
type Memcache struct {
*memcache.Config
Expire time.Duration
}
func init() {
flag.StringVar(&confPath, "conf", "", "default config path")
}
// Init init config.
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 load() != nil {
log.Error("config reload error (%v)", err)
}
}
}()
return
}
func load() (err error) {
var (
s string
ok bool
tmpConf *Config
)
if s, ok = client.Toml2(); !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,60 @@
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"mc.go",
"mysql.go",
"notify.go",
],
importpath = "go-common/app/job/main/passport-game-cloud/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/passport-game-cloud/conf:go_default_library",
"//app/job/main/passport-game-cloud/model:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/database/sql:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = [
"dao_test.go",
"mysql_test.go",
"notify_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/passport-game-cloud/conf:go_default_library",
"//app/job/main/passport-game-cloud/model:go_default_library",
"//vendor/github.com/go-sql-driver/mysql:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,63 @@
package dao
import (
"context"
"fmt"
"time"
"go-common/app/job/main/passport-game-cloud/conf"
"go-common/library/cache/memcache"
"go-common/library/database/sql"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
)
// Dao dao
type Dao struct {
c *conf.Config
getMemberStmt []*sql.Stmt
cloudDB *sql.DB
mc *memcache.Pool
mcExpire int32
gameClient *bm.Client
delGameCacheURI string
}
// New new dao.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
cloudDB: sql.NewMySQL(c.DB.Cloud),
mc: memcache.NewPool(c.Memcache.Config),
mcExpire: int32(time.Duration(c.Memcache.Expire) / time.Second),
gameClient: bm.NewClient(c.Game.Client),
delGameCacheURI: c.Game.DelCacheURI,
}
d.getMemberStmt = make([]*sql.Stmt, _memberShard)
for i := 0; i < _memberShard; i++ {
d.getMemberStmt[i] = d.cloudDB.Prepared(fmt.Sprintf(_getMemberInfoSQL, i))
}
return
}
// Ping check dao ok.
func (d *Dao) Ping(c context.Context) (err error) {
if err = d.cloudDB.Ping(c); err != nil {
log.Info("dao.cloudDB.Ping() error(%v)", err)
}
if err = d.pingMC(c); err != nil {
log.Info("dao.pingMC() error(%v)", err)
}
return
}
// Close close connections of mc, cloudDB.
func (d *Dao) Close() (err error) {
if d.cloudDB != nil {
d.cloudDB.Close()
}
if d.mc != nil {
d.mc.Close()
}
return
}

View File

@@ -0,0 +1,20 @@
package dao
import (
"fmt"
"sync"
"go-common/app/job/main/passport-game-cloud/conf"
)
var (
once sync.Once
d *Dao
)
func startDao() {
if err := conf.Init(); err != nil {
panic(fmt.Sprintf("conf.Init() error(%v)", err))
}
d = New(conf.Conf)
}

View File

@@ -0,0 +1,84 @@
package dao
import (
"context"
"strconv"
"go-common/app/job/main/passport-game-cloud/model"
"go-common/library/cache/memcache"
"go-common/library/log"
)
const (
_keyPrefixInfoPB = "pa2_"
_keyPrefixTokenPB = "pt_"
)
func keyInfoPB(mid int64) string {
return _keyPrefixInfoPB + strconv.FormatInt(mid, 10)
}
func keyTokenPB(accessToken string) string {
return _keyPrefixTokenPB + accessToken
}
// pingMC check connection success.
func (d *Dao) pingMC(c context.Context) (err error) {
item := &memcache.Item{
Key: "ping",
Value: []byte{1},
Expiration: d.mcExpire,
}
conn := d.mc.Get(c)
defer conn.Close()
if err = conn.Set(item); err != nil {
log.Error("conn.Set(%v) error(%v)", item, err)
}
return
}
// DelInfoCache delete info cache.
func (d *Dao) DelInfoCache(c context.Context, mid int64) (err error) {
key := keyInfoPB(mid)
conn := d.mc.Get(c)
defer conn.Close()
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
log.Error("conn.Delete(%s) error(%v)", key, err)
}
return
}
// SetTokenCache set token into cache.
func (d *Dao) SetTokenCache(c context.Context, token *model.Perm) (err error) {
item := &memcache.Item{
Key: keyTokenPB(token.AccessToken),
Object: token,
Flags: memcache.FlagProtobuf,
Expiration: d.mcExpire,
}
conn := d.mc.Get(c)
defer conn.Close()
if err = conn.Set(item); err != nil {
log.Error("conn.Set(%s) error(%v)", item.Key, err)
}
return
}
// DelTokenCache delete token cache.
func (d *Dao) DelTokenCache(c context.Context, accessToken string) (err error) {
key := keyTokenPB(accessToken)
conn := d.mc.Get(c)
defer conn.Close()
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
log.Error("conn.Delete(%s) error(%v)", key, err)
}
return
}

View File

@@ -0,0 +1,143 @@
package dao
import (
"context"
"database/sql"
"fmt"
"go-common/app/job/main/passport-game-cloud/model"
xsql "go-common/library/database/sql"
"go-common/library/log"
)
const (
_memberShard = 30
_addMemberInfoSQL = "INSERT INTO member_%02d (mid,face) VALUES(?,?) ON DUPLICATE KEY UPDATE face=?"
_deleteMemberInfoSQL = "DELETE FROM member_%02d WHERE mid=?"
_getMemberInfoSQL = "SELECT mid,face FROM member_%02d WHERE mid=?"
_addTokenSQL = "INSERT INTO app_perm (mid,appid,app_subid,access_token,create_at,expires) VALUES (?,?,?,?,?,?)"
_updateTokenSQL = "UPDATE app_perm SET expires=? WHERE access_token=? AND expires<?"
_deleteTokenSQL = "DELETE FROM app_perm WHERE access_token=?"
_getTokensSQL = "SELECT access_token FROM app_perm WHERE mid=?"
_addAsoAccountSQL = "INSERT INTO aso_account (mid,userid,uname,pwd,salt,email,tel,country_id,mobile_verified,isleak) VALUES(?,?,?,?,?,?,?,?,?,?)"
_updateAsoAccountSQL = "UPDATE aso_account SET userid=?,uname=?,pwd=?,salt=?,email=?,tel=?,country_id=?,mobile_verified=?,isleak=? WHERE mid=?"
_deleteAsoAccountSQL = "DELETE FROM aso_account WHERE mid=?"
)
func hit(mid int64) int64 {
return mid % _memberShard
}
// AddMemberInfo add member info.
func (d *Dao) AddMemberInfo(c context.Context, info *model.Info) (affected int64, err error) {
var res sql.Result
if res, err = d.cloudDB.Exec(c, fmt.Sprintf(_addMemberInfoSQL, hit(info.Mid)), info.Mid, info.Face, info.Face); err != nil {
log.Error("failed to add member info, dao.cloudDB.Exec(%d, %s, %s) error(%v)", info.Mid, info.Face, info.Face, err)
return
}
return res.RowsAffected()
}
// DelMemberInfo delete member info.
func (d *Dao) DelMemberInfo(c context.Context, mid int64) (affected int64, err error) {
var res sql.Result
if res, err = d.cloudDB.Exec(c, fmt.Sprintf(_deleteMemberInfoSQL, hit(mid)), mid); err != nil {
log.Error("failed to delete member info, dao.cloudDB.Exec(%d) error(%v)", mid, err)
return
}
return res.RowsAffected()
}
// AddToken add token.
func (d *Dao) AddToken(c context.Context, t *model.Perm) (affected int64, err error) {
var res sql.Result
if res, err = d.cloudDB.Exec(c, _addTokenSQL, t.Mid, t.AppID, t.AppSubID, t.AccessToken, t.CreateAt, t.Expires); err != nil {
log.Error("failed to add token, dao.cloudDB.Exec(%d, %d, %d, %s, %d, %d) error(%v)", t.Mid, t.AppID, t.AppSubID, t.AccessToken, t.CreateAt, t.Expires, err)
return
}
return res.RowsAffected()
}
// UpdateToken update token.
func (d *Dao) UpdateToken(c context.Context, t *model.Perm) (affected int64, err error) {
var res sql.Result
if res, err = d.cloudDB.Exec(c, _updateTokenSQL, t.Expires, t.AccessToken, t.Expires); err != nil {
log.Error("failed to update token, dao.cloudDB.Exec(%d, %s, %d) error(%v)", t.Expires, t.AccessToken, t.Expires, err)
return
}
return res.RowsAffected()
}
// DelToken delete token.
func (d *Dao) DelToken(c context.Context, accessToken string) (affected int64, err error) {
var res sql.Result
if res, err = d.cloudDB.Exec(c, _deleteTokenSQL, accessToken); err != nil {
log.Error("failed to delete token, dao.cloudDB.Exec(%s) error(%v)", accessToken, err)
return
}
return res.RowsAffected()
}
// Tokens get tokens by mid.
func (d *Dao) Tokens(c context.Context, mid int64) (res []string, err error) {
var rows *xsql.Rows
if rows, err = d.cloudDB.Query(c, _getTokensSQL, mid); err != nil {
log.Error("failed to get tokens, dao.cloudDB.Tokens(%s) error(%v)", _getTokensSQL, err)
return
}
defer rows.Close()
for rows.Next() {
var at string
if err = rows.Scan(&at); err != nil {
log.Error("row.Scan() error(%v)", err)
res = nil
return
}
res = append(res, at)
}
return
}
// AddAsoAccount add aso account.
func (d *Dao) AddAsoAccount(c context.Context, a *model.AsoAccount) (affected int64, err error) {
var res sql.Result
var telPtr, emailPtr *string
if a.Tel != "" {
telPtr = &a.Tel
}
if a.Email != "" {
emailPtr = &a.Email
}
if res, err = d.cloudDB.Exec(c, _addAsoAccountSQL, a.Mid, a.UserID, a.Uname, a.Pwd, a.Salt, emailPtr, telPtr, a.CountryID, a.MobileVerified, a.Isleak); err != nil {
log.Error("failed to add aso account, dao.cloudDB.Exec() error(%v)", err)
return
}
return res.RowsAffected()
}
// UpdateAsoAccount update aso account.
func (d *Dao) UpdateAsoAccount(c context.Context, a *model.AsoAccount) (affected int64, err error) {
var res sql.Result
var telPtr, emailPtr *string
if a.Tel != "" {
telPtr = &a.Tel
}
if a.Email != "" {
emailPtr = &a.Email
}
if res, err = d.cloudDB.Exec(c, _updateAsoAccountSQL, a.UserID, a.Uname, a.Pwd, a.Salt, emailPtr, telPtr, a.CountryID, a.MobileVerified, a.Isleak, a.Mid); err != nil {
log.Error("failed to add aso account, dao.cloudDB.Exec() error(%v)", err)
return
}
return res.RowsAffected()
}
// DelAsoAccount delete aso account.
func (d *Dao) DelAsoAccount(c context.Context, mid int64) (affected int64, err error) {
var res sql.Result
if res, err = d.cloudDB.Exec(c, _deleteAsoAccountSQL, mid); err != nil {
log.Error("failed to delete aso account, dao.cloudDB.Exec(%s) error(%v)", mid, err)
return
}
return res.RowsAffected()
}

View File

@@ -0,0 +1,82 @@
package dao
import (
"context"
"testing"
"go-common/app/job/main/passport-game-cloud/model"
"github.com/go-sql-driver/mysql"
"github.com/pkg/errors"
. "github.com/smartystreets/goconvey/convey"
)
func TestDao_PingMySQL(t *testing.T) {
once.Do(startDao)
if err := d.cloudDB.Ping(context.TODO()); err != nil {
t.Errorf("dao.cloudDB.Ping() error(%v)", err)
t.FailNow()
}
}
func TestDao_AddMemberInfo(t *testing.T) {
once.Do(startDao)
info := &model.Info{
Mid: 110000130,
Face: "/bfs/face/bbc031c4b7bdabb6635a246ce7386ccb587c5214811111.jpg",
}
if a, err := d.AddMemberInfo(context.TODO(), info); err != nil {
t.FailNow()
} else {
t.Logf("a: %d", a)
}
}
func TestDao_UpdateAsoAccount(t *testing.T) {
once.Do(startDao)
Convey("update a aso account", t, func() {
account := &model.AsoAccount{
Mid: 12047569,
UserID: "bili_1710676855",
Uname: "Bili_12047569",
Pwd: "3686c9d96ae6896fe117319ba6c07087",
Salt: "pdMXF856",
Email: "62fe0d616162f56ecab3e12a2de83ea6",
Tel: "bdb27b0300e3984e48e7aea5c672a243",
CountryID: 1,
MobileVerified: 1,
Isleak: 0,
}
affected, err := d.UpdateAsoAccount(context.TODO(), account)
So(err, ShouldBeNil)
So(affected, ShouldEqual, 1)
})
}
func TestDao_AddAsoAccount(t *testing.T) {
once.Do(startDao)
account := &model.AsoAccount{
Mid: 12047569,
UserID: "bili_1710676855",
Uname: "Bili_12047569",
Pwd: "3686c9d96ae6896fe117319ba6c07087",
Salt: "pdMXF856",
Email: "62fe0d616162f56ecab3e12a2de83ea6",
Tel: "bdb27b0300e3984e48e7aea5c672a243",
CountryID: 1,
MobileVerified: 1,
Isleak: 0,
}
if _, err := d.AddAsoAccount(context.TODO(), account); err != nil {
switch nErr := errors.Cause(err).(type) {
case *mysql.MySQLError:
if nErr.Number != 1062 {
t.Errorf("expected MySQL error 1062 but got error(%v)", err)
t.FailNow()
}
}
} else {
t.FailNow()
}
}

View File

@@ -0,0 +1,33 @@
package dao
import (
"context"
"net/url"
"strconv"
"go-common/library/ecode"
"go-common/library/log"
)
// NotifyGame to notify game.
func (d *Dao) NotifyGame(c context.Context, mid int64, accessToken, action string) (err error) {
params := url.Values{}
params.Set("modifiedAttr", action)
params.Set("mid", strconv.FormatInt(mid, 10))
if accessToken != "" {
params.Set("access_token", accessToken)
}
params.Set("from", "passport-game-cloud-job")
var res struct {
Code int `json:"code"`
}
if err = d.gameClient.Get(c, d.delGameCacheURI, "127.0.0.1", params, &res); err != nil {
log.Error("failed to notify game, d.gameClient.Get(%s) error(%v)", d.delGameCacheURI+"?"+params.Encode(), err)
return
}
if res.Code != 0 {
err = ecode.Int(res.Code)
log.Error("failed to notify game, url(%s) err(%v)", d.delGameCacheURI+"?"+params.Encode(), err)
}
return
}

View File

@@ -0,0 +1,17 @@
package dao
import (
"context"
"testing"
)
func TestDao_NotifyGame(t *testing.T) {
once.Do(startDao)
mid := int64(4780461)
ak := "3cf80530cccafaa9ed675d8a493c1a89#tx"
action := "changePwd"
if err := d.NotifyGame(context.TODO(), mid, ak, action); err != nil {
t.Errorf("dao.NotifyGame(%d, %s, %s) error(%v)", mid, ak, action, err)
t.FailNow()
}
}

View File

@@ -0,0 +1,32 @@
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["http.go"],
importpath = "go-common/app/job/main/passport-game-cloud/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/passport-game-cloud/conf:go_default_library",
"//app/job/main/passport-game-cloud/service:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,36 @@
package http
import (
"go-common/app/job/main/passport-game-cloud/conf"
"go-common/app/job/main/passport-game-cloud/service"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
)
var (
srv *service.Service
)
// Init init http sever instance.
func Init(c *conf.Config, s *service.Service) {
srv = s
// init inner router
eng := bm.DefaultServer(c.BM)
initRouter(eng)
// init inner server
if err := eng.Start(); err != nil {
log.Error("bm.DefaultServer error(%v)", err)
panic(err)
}
}
// initRouter init inner router.
func initRouter(e *bm.Engine) {
// health check
e.Ping(ping)
}
// ping check server ok.
func ping(c *bm.Context) {
c.JSON(nil, srv.Ping(c))
}

View File

@@ -0,0 +1,56 @@
load(
"@io_bazel_rules_go//proto:def.bzl",
"go_proto_library",
)
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"message.go",
"model.go",
],
embed = [":model_go_proto"],
importpath = "go-common/app/job/main/passport-game-cloud/model",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"@com_github_gogo_protobuf//gogoproto:go_default_library",
"@com_github_golang_protobuf//proto: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"],
)
proto_library(
name = "model_proto",
srcs = ["model.proto"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = ["@gogo_special_proto//github.com/gogo/protobuf/gogoproto"],
)
go_proto_library(
name = "model_go_proto",
compilers = ["@io_bazel_rules_go//proto:gogofast_proto"],
importpath = "go-common/app/job/main/passport-game-cloud/model",
proto = ":model_proto",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = ["@com_github_gogo_protobuf//gogoproto:go_default_library"],
)

View File

@@ -0,0 +1,23 @@
package model
import (
"encoding/json"
)
// BMsg databus binlog message.
type BMsg struct {
Action string `json:"action"`
Table string `json:"table"`
New json.RawMessage `json:"new"`
Old json.RawMessage `json:"old"`
MTS int64
}
// PMsg Push msg
type PMsg struct {
Action string `json:"action"`
Table string `json:"table"`
Data *AsoAccount `json:"data"`
Flag int `json:"flag"`
MTS int64
}

View File

@@ -0,0 +1,62 @@
package model
// OriginPerm origin token.
type OriginPerm struct {
Mid int64 `json:"mid"`
AppID int32 `json:"appid"`
AppSubID int32 `json:"app_subid"`
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
CreateAt int64 `json:"create_at"`
Expires int64 `json:"expires"`
Ctime string `json:"ctime"`
Mtime string `json:"mtime"`
}
// OriginAsoAccount origin aso account.
type OriginAsoAccount struct {
Mid int64 `json:"mid"`
Uname string `json:"uname"`
Mtime string `json:"modify_time"`
}
// OriginMember origin member.
type OriginMember struct {
Mid int64 `json:"mid"`
Face string `json:"face"`
Mtime string `json:"modify_time"`
}
// Info account info.
type Info struct {
Mid int64 `json:"mid"`
Uname string `json:"uname"`
Face string `json:"face"`
Email string `json:"email"`
Tel string `json:"tel"`
}
// Equals check info equals.
func (m *Info) Equals(other *Info) bool {
return m.Mid == other.Mid && m.Uname == other.Uname && m.Face == other.Face
}
// AsoAccount aso account.
type AsoAccount struct {
Mid int64 `json:"mid"`
UserID string `json:"userid"`
Uname string `json:"uname"`
Pwd string `json:"pwd"`
Salt string `json:"salt"`
Email string `json:"email"`
Tel string `json:"tel"`
CountryID int64 `json:"country_id"`
MobileVerified int8 `json:"mobile_verified"`
Isleak int8 `json:"isleak"`
Mtime string `json:"mtime"`
}
// Equals check perm equals, check all non primary key fields exclude create_at.
func (m *Perm) Equals(other *Perm) bool {
return m.Mid == other.Mid && m.AppID == other.AppID && m.AccessToken == other.AccessToken && m.RefreshToken == other.RefreshToken && m.AppSubID == other.AppSubID && m.Expires == other.Expires
}

View File

@@ -0,0 +1,556 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: model.proto
/*
Package model is a generated protocol buffer package.
It is generated from these files:
model.proto
It has these top-level messages:
Perm
*/
package model
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import _ "github.com/gogo/protobuf/gogoproto"
import io "io"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
// Perm token.
type Perm struct {
Mid int64 `protobuf:"varint,1,opt,name=Mid,proto3" json:"mid"`
AppID int32 `protobuf:"varint,2,opt,name=AppID,proto3" json:"appid"`
AppSubID int32 `protobuf:"varint,3,opt,name=AppSubID,proto3" json:"app_subid"`
AccessToken string `protobuf:"bytes,4,opt,name=AccessToken,proto3" json:"access_token"`
RefreshToken string `protobuf:"bytes,5,opt,name=RefreshToken,proto3" json:"refresh_token"`
CreateAt int64 `protobuf:"varint,6,opt,name=CreateAt,proto3" json:"create_at"`
Expires int64 `protobuf:"varint,7,opt,name=Expires,proto3" json:"expires"`
}
func (m *Perm) Reset() { *m = Perm{} }
func (m *Perm) String() string { return proto.CompactTextString(m) }
func (*Perm) ProtoMessage() {}
func (*Perm) Descriptor() ([]byte, []int) { return fileDescriptorModel, []int{0} }
func (m *Perm) GetMid() int64 {
if m != nil {
return m.Mid
}
return 0
}
func (m *Perm) GetAppID() int32 {
if m != nil {
return m.AppID
}
return 0
}
func (m *Perm) GetAppSubID() int32 {
if m != nil {
return m.AppSubID
}
return 0
}
func (m *Perm) GetAccessToken() string {
if m != nil {
return m.AccessToken
}
return ""
}
func (m *Perm) GetRefreshToken() string {
if m != nil {
return m.RefreshToken
}
return ""
}
func (m *Perm) GetCreateAt() int64 {
if m != nil {
return m.CreateAt
}
return 0
}
func (m *Perm) GetExpires() int64 {
if m != nil {
return m.Expires
}
return 0
}
func init() {
proto.RegisterType((*Perm)(nil), "model.Perm")
}
func (m *Perm) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalTo(dAtA)
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *Perm) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if m.Mid != 0 {
dAtA[i] = 0x8
i++
i = encodeVarintModel(dAtA, i, uint64(m.Mid))
}
if m.AppID != 0 {
dAtA[i] = 0x10
i++
i = encodeVarintModel(dAtA, i, uint64(m.AppID))
}
if m.AppSubID != 0 {
dAtA[i] = 0x18
i++
i = encodeVarintModel(dAtA, i, uint64(m.AppSubID))
}
if len(m.AccessToken) > 0 {
dAtA[i] = 0x22
i++
i = encodeVarintModel(dAtA, i, uint64(len(m.AccessToken)))
i += copy(dAtA[i:], m.AccessToken)
}
if len(m.RefreshToken) > 0 {
dAtA[i] = 0x2a
i++
i = encodeVarintModel(dAtA, i, uint64(len(m.RefreshToken)))
i += copy(dAtA[i:], m.RefreshToken)
}
if m.CreateAt != 0 {
dAtA[i] = 0x30
i++
i = encodeVarintModel(dAtA, i, uint64(m.CreateAt))
}
if m.Expires != 0 {
dAtA[i] = 0x38
i++
i = encodeVarintModel(dAtA, i, uint64(m.Expires))
}
return i, nil
}
func encodeFixed64Model(dAtA []byte, offset int, v uint64) int {
dAtA[offset] = uint8(v)
dAtA[offset+1] = uint8(v >> 8)
dAtA[offset+2] = uint8(v >> 16)
dAtA[offset+3] = uint8(v >> 24)
dAtA[offset+4] = uint8(v >> 32)
dAtA[offset+5] = uint8(v >> 40)
dAtA[offset+6] = uint8(v >> 48)
dAtA[offset+7] = uint8(v >> 56)
return offset + 8
}
func encodeFixed32Model(dAtA []byte, offset int, v uint32) int {
dAtA[offset] = uint8(v)
dAtA[offset+1] = uint8(v >> 8)
dAtA[offset+2] = uint8(v >> 16)
dAtA[offset+3] = uint8(v >> 24)
return offset + 4
}
func encodeVarintModel(dAtA []byte, offset int, v uint64) int {
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return offset + 1
}
func (m *Perm) Size() (n int) {
var l int
_ = l
if m.Mid != 0 {
n += 1 + sovModel(uint64(m.Mid))
}
if m.AppID != 0 {
n += 1 + sovModel(uint64(m.AppID))
}
if m.AppSubID != 0 {
n += 1 + sovModel(uint64(m.AppSubID))
}
l = len(m.AccessToken)
if l > 0 {
n += 1 + l + sovModel(uint64(l))
}
l = len(m.RefreshToken)
if l > 0 {
n += 1 + l + sovModel(uint64(l))
}
if m.CreateAt != 0 {
n += 1 + sovModel(uint64(m.CreateAt))
}
if m.Expires != 0 {
n += 1 + sovModel(uint64(m.Expires))
}
return n
}
func sovModel(x uint64) (n int) {
for {
n++
x >>= 7
if x == 0 {
break
}
}
return n
}
func sozModel(x uint64) (n int) {
return sovModel(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *Perm) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModel
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Perm: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Perm: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Mid", wireType)
}
m.Mid = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModel
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Mid |= (int64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 2:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field AppID", wireType)
}
m.AppID = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModel
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.AppID |= (int32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field AppSubID", wireType)
}
m.AppSubID = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModel
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.AppSubID |= (int32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field AccessToken", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModel
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthModel
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.AccessToken = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 5:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field RefreshToken", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModel
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthModel
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.RefreshToken = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 6:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field CreateAt", wireType)
}
m.CreateAt = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModel
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.CreateAt |= (int64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 7:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Expires", wireType)
}
m.Expires = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModel
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Expires |= (int64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skipModel(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthModel
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipModel(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowModel
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowModel
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
return iNdEx, nil
case 1:
iNdEx += 8
return iNdEx, nil
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowModel
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
iNdEx += length
if length < 0 {
return 0, ErrInvalidLengthModel
}
return iNdEx, nil
case 3:
for {
var innerWire uint64
var start int = iNdEx
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowModel
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
innerWire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
innerWireType := int(innerWire & 0x7)
if innerWireType == 4 {
break
}
next, err := skipModel(dAtA[start:])
if err != nil {
return 0, err
}
iNdEx = start + next
}
return iNdEx, nil
case 4:
return iNdEx, nil
case 5:
iNdEx += 4
return iNdEx, nil
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
}
panic("unreachable")
}
var (
ErrInvalidLengthModel = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowModel = fmt.Errorf("proto: integer overflow")
)
func init() { proto.RegisterFile("model.proto", fileDescriptorModel) }
var fileDescriptorModel = []byte{
// 304 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x90, 0x4f, 0x4a, 0x3b, 0x31,
0x1c, 0xc5, 0x7f, 0xe9, 0x74, 0x3a, 0xbf, 0xa6, 0x2d, 0xd4, 0xac, 0x46, 0x17, 0x93, 0x22, 0x08,
0x75, 0x61, 0x0b, 0x8a, 0x07, 0x98, 0xb1, 0x2e, 0xba, 0x10, 0x24, 0xba, 0x2f, 0xf3, 0x27, 0x6d,
0x83, 0x8e, 0x09, 0x99, 0x0c, 0x78, 0x14, 0xcf, 0xe0, 0x49, 0x5c, 0x7a, 0x82, 0x20, 0x75, 0x97,
0x53, 0xc8, 0x7c, 0x47, 0x8b, 0xee, 0xf2, 0x3e, 0xef, 0x3d, 0x78, 0xf9, 0xe2, 0x41, 0x29, 0x0b,
0xfe, 0x38, 0x53, 0x5a, 0x1a, 0x49, 0x7c, 0x10, 0x47, 0x67, 0x1b, 0x61, 0xb6, 0x75, 0x36, 0xcb,
0x65, 0x39, 0xdf, 0xc8, 0x8d, 0x9c, 0x83, 0x9b, 0xd5, 0x6b, 0x50, 0x20, 0xe0, 0xd5, 0xb6, 0x8e,
0x5f, 0x3b, 0xb8, 0x7b, 0xcb, 0x75, 0x49, 0x0e, 0xb1, 0x77, 0x23, 0x8a, 0x10, 0x4d, 0xd0, 0xd4,
0x4b, 0x02, 0x67, 0xa9, 0x57, 0x8a, 0x82, 0x35, 0x8c, 0x50, 0xec, 0xc7, 0x4a, 0x2d, 0x17, 0x61,
0x67, 0x82, 0xa6, 0x7e, 0xd2, 0x77, 0x96, 0xfa, 0xa9, 0x52, 0xa2, 0x60, 0x2d, 0x27, 0xa7, 0xf8,
0x7f, 0xac, 0xd4, 0x5d, 0x9d, 0x2d, 0x17, 0xa1, 0x07, 0x99, 0x91, 0xb3, 0xb4, 0x9f, 0x2a, 0xb5,
0xaa, 0xea, 0x4c, 0x14, 0x6c, 0x6f, 0x93, 0x73, 0x3c, 0x88, 0xf3, 0x9c, 0x57, 0xd5, 0xbd, 0x7c,
0xe0, 0x4f, 0x61, 0x77, 0x82, 0xa6, 0xfd, 0x64, 0xec, 0x2c, 0x1d, 0xa6, 0x80, 0x57, 0xa6, 0xe1,
0xec, 0x77, 0x88, 0x5c, 0xe2, 0x21, 0xe3, 0x6b, 0xcd, 0xab, 0x6d, 0x5b, 0xf2, 0xa1, 0x74, 0xe0,
0x2c, 0x1d, 0xe9, 0x96, 0x7f, 0xb7, 0xfe, 0xc4, 0x9a, 0x55, 0x57, 0x9a, 0xa7, 0x86, 0xc7, 0x26,
0xec, 0xc1, 0xb7, 0x60, 0x55, 0x0e, 0x6c, 0x95, 0x1a, 0xb6, 0xb7, 0xc9, 0x09, 0x0e, 0xae, 0x9f,
0x95, 0xd0, 0xbc, 0x0a, 0x03, 0x48, 0x0e, 0x9c, 0xa5, 0x01, 0x6f, 0x11, 0xfb, 0xf1, 0x92, 0xf1,
0xdb, 0x2e, 0x42, 0xef, 0xbb, 0x08, 0x7d, 0xec, 0x22, 0xf4, 0xf2, 0x19, 0xfd, 0xcb, 0x7a, 0x70,
0xc5, 0x8b, 0xaf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc3, 0xc7, 0xd0, 0xe6, 0x8a, 0x01, 0x00, 0x00,
}

View File

@@ -0,0 +1,16 @@
syntax = "proto3";
package model;
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
// Perm token.
message Perm {
int64 Mid = 1 [(gogoproto.jsontag) = "mid"];
int32 AppID = 2 [(gogoproto.jsontag) = "appid"];
int32 AppSubID = 3 [(gogoproto.jsontag) = "app_subid"];
string AccessToken = 4 [(gogoproto.jsontag) = "access_token"];
string RefreshToken = 5 [(gogoproto.jsontag) = "refresh_token"];
int64 CreateAt = 6 [(gogoproto.jsontag) = "create_at"];
int64 Expires = 7 [(gogoproto.jsontag) = "expires"];
}

View File

@@ -0,0 +1,5 @@
#! /bin/sh
# proto.sh
gopath=$GOPATH/src
gogopath=$GOPATH/src/go-common/vendor/github.com/gogo/protobuf
protoc --gofast_out=. --proto_path=$gopath:$gogopath:. *.proto

View File

@@ -0,0 +1,59 @@
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"account.go",
"bin_log.go",
"encrypt_trans.go",
"passport.go",
"prom.go",
"service.go",
],
importpath = "go-common/app/job/main/passport-game-cloud/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/passport-game-cloud/conf:go_default_library",
"//app/job/main/passport-game-cloud/dao:go_default_library",
"//app/job/main/passport-game-cloud/model:go_default_library",
"//library/log:go_default_library",
"//library/queue/databus:go_default_library",
"//library/stat/prom:go_default_library",
"//vendor/github.com/go-sql-driver/mysql:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = [
"prom_test.go",
"service_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/passport-game-cloud/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey: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,72 @@
package service
import (
"context"
"encoding/json"
"time"
"go-common/app/job/main/passport-game-cloud/model"
"go-common/library/log"
)
const (
_memberTableUpdateDuration = time.Second * 1
)
func (s *Service) processMemberInfo(bmsg *model.BMsg) {
n := new(model.Info)
if err := json.Unmarshal(bmsg.New, n); err != nil {
log.Error("failed to parse binlog new, json.Unmarshal(%s) error(%v)", string(bmsg.New), err)
return
}
s.memberInterval.Prom(context.TODO(), bmsg.MTS)
switch bmsg.Action {
case "insert":
s.addMemberInfo(context.TODO(), n)
s.delInfoCache(context.TODO(), n.Mid)
case "update":
old := new(model.Info)
if err := json.Unmarshal(bmsg.Old, old); err != nil {
log.Error("failed to parse binlog old, json.Unmarshal(%s) error(%v)", string(bmsg.Old), err)
return
}
if n.Equals(old) {
return
}
s.addMemberInfo(context.TODO(), n)
s.delInfoCache(context.TODO(), n.Mid)
case "delete":
s.delMemberInfo(context.TODO(), n.Mid)
s.delInfoCache(context.TODO(), n.Mid)
}
}
func (s *Service) addMemberInfo(c context.Context, info *model.Info) (err error) {
for {
if _, err = s.d.AddMemberInfo(c, info); err == nil {
break
}
time.Sleep(_memberTableUpdateDuration)
}
return
}
func (s *Service) delMemberInfo(c context.Context, mid int64) (err error) {
for {
if _, err = s.d.DelMemberInfo(c, mid); err == nil {
break
}
time.Sleep(_memberTableUpdateDuration)
}
return
}
func (s *Service) delInfoCache(c context.Context, mid int64) (err error) {
for i := 0; i < _accountCacheRetryCount; i++ {
if err = s.d.DelInfoCache(c, mid); err == nil {
break
}
time.Sleep(_accountCacheRetryDuration)
}
return
}

View File

@@ -0,0 +1,137 @@
package service
import (
"context"
"encoding/json"
"strings"
"time"
"go-common/app/job/main/passport-game-cloud/model"
"go-common/library/log"
"go-common/library/queue/databus"
)
func (s *Service) binlogconsumeproc() {
mergeRoutineNum := int64(s.c.Group.BinLog.Num)
for {
msg, ok := <-s.binLogDataBus.Messages()
if !ok {
log.Error("binlogconsumeproc closed")
return
}
// marked head to first commit
m := &message{data: msg}
s.mu.Lock()
if s.head == nil {
s.head = m
s.last = m
} else {
s.last.next = m
s.last = m
}
s.mu.Unlock()
bmsg := new(model.BMsg)
if err := json.Unmarshal(msg.Value, bmsg); err != nil {
log.Error("json.Unmarshal(%s) error(%v)", string(msg.Value), err)
continue
}
mid := int64(0)
if bmsg.Table == _asoAccountTable {
t := new(model.OriginAsoAccount)
if err := json.Unmarshal(bmsg.New, t); err != nil {
log.Error("json.Unmarshal(%s) error(%v)", string(bmsg.New), err)
continue
}
mid = t.Mid
bmsg.MTS = s.asoAccountInterval.MTS(context.TODO(), t.Mtime)
} else if strings.HasPrefix(bmsg.Table, _tokenTablePrefix) {
t := new(model.OriginPerm)
if err := json.Unmarshal(bmsg.New, t); err != nil {
log.Error("json.Unmarshal(%s) error(%v)", string(bmsg.New), err)
continue
}
mid = t.Mid
bmsg.MTS = s.tokenInterval.MTS(context.TODO(), t.Mtime)
} else if strings.HasPrefix(bmsg.Table, _memberTablePrefix) {
t := new(model.OriginMember)
if err := json.Unmarshal(bmsg.New, t); err != nil {
log.Error("json.Unmarshal(%s) error(%v)", string(bmsg.New), err)
continue
}
mid = t.Mid
bmsg.MTS = s.memberInterval.MTS(context.TODO(), t.Mtime)
}
m.object = bmsg
// use specify goroutine to merge messages
s.binLogMergeChans[mid%mergeRoutineNum] <- m
log.Info("binlogconsumeproc table:%s key:%s partition:%d offset:%d", bmsg.Table, msg.Key, msg.Partition, msg.Offset)
}
}
func (s *Service) binlogcommitproc() {
commits := make(map[int32]*databus.Message, s.c.Group.BinLog.Size)
for {
done := <-s.binLogDoneChan
// merge partitions to commit offset
for _, d := range done {
d.done = true
}
s.mu.Lock()
for ; s.head != nil && s.head.done; s.head = s.head.next {
commits[s.head.data.Partition] = s.head.data
}
s.mu.Unlock()
for k, m := range commits {
log.Info("binlogcommitproc committed, key:%s partition:%d offset:%d", m.Key, m.Partition, m.Offset)
m.Commit()
delete(commits, k)
}
}
}
func (s *Service) binlogmergeproc(c chan *message) {
var (
max = s.c.Group.BinLog.Size
merges = make([]*model.BMsg, 0, max)
marked = make([]*message, 0, max)
ticker = time.NewTicker(time.Duration(s.c.Group.BinLog.Ticker))
)
for {
select {
case msg, ok := <-c:
if !ok {
log.Error("binlogmergeproc closed")
return
}
p, assertOk := msg.object.(*model.BMsg)
if assertOk {
merges = append(merges, p)
}
marked = append(marked, msg)
if len(marked) < max && len(merges) < max {
continue
}
case <-ticker.C:
}
if len(merges) > 0 {
s.process(merges)
merges = make([]*model.BMsg, 0, max)
}
if len(marked) > 0 {
s.binLogDoneChan <- marked
marked = make([]*message, 0, max)
}
}
}
func (s *Service) process(bmsgs []*model.BMsg) {
for _, bmsg := range bmsgs {
if bmsg.Table == _asoAccountTable {
s.processUserInfo(bmsg)
} else if strings.HasPrefix(bmsg.Table, _tokenTablePrefix) {
s.processToken(bmsg)
} else if strings.HasPrefix(bmsg.Table, _memberTablePrefix) {
s.processMemberInfo(bmsg)
}
}
}

View File

@@ -0,0 +1,110 @@
package service
import (
"context"
"encoding/json"
"time"
"go-common/app/job/main/passport-game-cloud/model"
"go-common/library/log"
"go-common/library/queue/databus"
)
func (s *Service) encrypttransconsumeproc() {
var (
mergeRoutineNum = int64(s.c.Group.EncryptTrans.Num)
msgs = s.encryptTransDataBus.Messages()
)
for {
msg, ok := <-msgs
if !ok {
log.Error("encrypttransconsumeproc closed")
return
}
// marked head to first commit
m := &message{data: msg}
s.asoMu.Lock()
if s.asoHead == nil {
s.asoHead = m
s.asoLast = m
} else {
s.asoLast.next = m
s.asoLast = m
}
s.asoMu.Unlock()
p := new(model.PMsg)
if err := json.Unmarshal(msg.Value, p); err != nil {
log.Error("encrypttransconsumeproc unmarshal failed, json.Unmarshal(%s) error(%v)", msg.Value, err)
continue
}
if p.Table == _asoAccountTable {
p.MTS = s.transInterval.MTS(context.TODO(), p.Data.Mtime)
}
m.object = p
s.encryptTransMergeChans[p.Data.Mid%mergeRoutineNum] <- m
log.Info("encrypttransconsumeproc key:%s partition:%d offset:%d", msg.Key, msg.Partition, msg.Offset)
}
}
func (s *Service) encrypttranscommitproc() {
commits := make(map[int32]*databus.Message, s.c.Group.EncryptTrans.Size)
for {
done := <-s.encryptTransDoneChan
for _, d := range done {
d.done = true
}
s.asoMu.Lock()
for ; s.asoHead != nil && s.asoHead.done; s.asoHead = s.asoHead.next {
commits[s.asoHead.data.Partition] = s.asoHead.data
}
s.asoMu.Unlock()
for k, m := range commits {
log.Info("encrypttranscommitproc committed, key:%s partition:%d offset:%d", m.Key, m.Partition, m.Offset)
m.Commit()
delete(commits, k)
}
}
}
func (s *Service) encrypttransmergeproc(c chan *message) {
var (
max = s.c.Group.EncryptTrans.Size
merges = make([]*model.PMsg, 0, max)
marked = make([]*message, 0, max)
ticker = time.NewTicker(time.Duration(s.c.Group.EncryptTrans.Ticker))
)
for {
select {
case msg, ok := <-c:
if !ok {
log.Error("encrypttransmergeproc closed")
return
}
p, assertOK := msg.object.(*model.PMsg)
if assertOK {
merges = append(merges, p)
}
marked = append(marked, msg)
if len(marked) < max && len(merges) < max {
continue
}
case <-ticker.C:
}
if len(merges) > 0 {
s.processAsoAcc(merges)
merges = make([]*model.PMsg, 0, max)
}
if len(marked) > 0 {
s.encryptTransDoneChan <- marked
marked = make([]*message, 0, max)
}
}
}
func (s *Service) processAsoAcc(pmsgs []*model.PMsg) {
for _, p := range pmsgs {
if p.Action != "" && p.Table == _asoAccountTable {
s.processAsoAccSub(p)
}
}
}

View File

@@ -0,0 +1,267 @@
package service
import (
"context"
"encoding/json"
"time"
"go-common/app/job/main/passport-game-cloud/model"
"go-common/library/log"
"github.com/go-sql-driver/mysql"
"github.com/pkg/errors"
)
const (
_userTableUpdateDuration = time.Second
_mySQLErrCodeDuplicateEntry = 1062
_tokenTableUpdateRetryCount = 3
_tokenTableUpdateDuration = time.Second
_tokenTablePrefix = "aso_app_perm"
_tokenCacheRetryCount = 3
_tokenCacheRetryDuration = time.Second
_notifyGameRetryCount = 3
_notifyGameRetryDuration = time.Second
)
func (s *Service) processUserInfo(bmsg *model.BMsg) {
n := new(model.Info)
if err := json.Unmarshal(bmsg.New, n); err != nil {
log.Error("failed to parse binlog new, json.Unmarshal(%s) error(%v)", string(bmsg.New), err)
return
}
s.asoAccountInterval.Prom(context.TODO(), bmsg.MTS)
switch bmsg.Action {
case "insert":
s.addMemberInit(context.TODO(), n)
s.delInfoCache(context.TODO(), n.Mid)
case "update":
old := new(model.Info)
if err := json.Unmarshal(bmsg.Old, old); err != nil {
log.Error("failed to parse binlog old, json.Unmarshal(%s) error(%v)", string(bmsg.Old), err)
return
}
if n.Equals(old) {
return
}
s.delInfoCache(context.TODO(), n.Mid)
case "delete":
s.delInfoCache(context.TODO(), n.Mid)
}
}
// sub log encryption UPDATE INSERT
func (s *Service) processAsoAccSub(msg *model.PMsg) {
n := msg.Data
flag := msg.Flag
s.transInterval.Prom(context.TODO(), msg.MTS)
switch msg.Action {
case "insert":
s.addAsoAccount(context.TODO(), n)
case "update":
s.updateAsoAccount(context.TODO(), n, flag)
case "delete":
s.delAsoAccount(context.TODO(), n.Mid)
}
s.delInfoCache(context.TODO(), n.Mid)
s.notifyGame(context.TODO(), n.Mid, "", _updateUserInfo)
}
func (s *Service) processToken(bmsg *model.BMsg) {
n := new(model.Perm)
if err := json.Unmarshal(bmsg.New, n); err != nil {
log.Error("json.Unmarshal(%s) error(%v)", string(bmsg.New), err)
return
}
isGame := false
for _, id := range s.gameAppIDs {
if n.AppID == id {
isGame = true
break
}
}
if !isGame {
return
}
s.tokenInterval.Prom(context.TODO(), bmsg.MTS)
switch bmsg.Action {
case "insert":
s.addToken(context.TODO(), n)
s.setTokenCache(context.TODO(), n)
case "update":
old := new(model.Perm)
if err := json.Unmarshal(bmsg.Old, old); err != nil {
log.Error("failed to parse binlog old, json.Unmarshal(%s) error(%v)", string(bmsg.Old), err)
return
}
if n.Equals(old) {
return
}
s.updateToken(context.TODO(), n)
s.setTokenCache(context.TODO(), n)
case "delete":
s.delToken(context.TODO(), n.AccessToken)
s.delTokenCache(context.TODO(), n.AccessToken)
}
}
func (s *Service) addAsoAccount(c context.Context, a *model.AsoAccount) (err error) {
for {
_, err = s.d.AddAsoAccount(c, a)
if err == nil {
break
}
switch nErr := errors.Cause(err).(type) {
case *mysql.MySQLError:
if nErr.Number == _mySQLErrCodeDuplicateEntry {
log.Error("failed to add aso because of duplicate entry, value is (%v), error(%v)", a, err)
return
}
}
time.Sleep(_userTableUpdateDuration)
}
return
}
func (s *Service) updateAsoAccount(c context.Context, a *model.AsoAccount, flag int) (err error) {
for {
_, err = s.UpdateAsoAccount(c, a, flag)
if err == nil {
break
}
switch nErr := errors.Cause(err).(type) {
case *mysql.MySQLError:
if nErr.Number == _mySQLErrCodeDuplicateEntry {
log.Error("failed to update aso because of duplicate entry, value is (%v), error(%v)", a, err)
return
}
}
time.Sleep(_userTableUpdateDuration)
}
return
}
// UpdateAsoAccount update aso account.
func (s *Service) UpdateAsoAccount(c context.Context, t *model.AsoAccount, flag int) (affected int64, err error) {
if affected, err = s.d.UpdateAsoAccount(c, t); err != nil {
return
}
if flag != 1 {
return
}
mid := t.Mid
var tokens []string
if tokens, err = s.d.Tokens(c, mid); err != nil {
return
}
for _, token := range tokens {
s.delToken(c, token)
s.delTokenCache(c, token)
s.notifyGame(c, mid, token, _changePwd)
}
return
}
func (s *Service) delAsoAccount(c context.Context, mid int64) (err error) {
for {
if _, err = s.d.DelAsoAccount(c, mid); err == nil {
break
}
time.Sleep(_userTableUpdateDuration)
}
return
}
func (s *Service) addMemberInit(c context.Context, a *model.Info) (err error) {
for {
memberInfo := &model.Info{
Mid: a.Mid,
Uname: a.Uname,
Face: "",
}
err = s.addMemberInfo(c, memberInfo)
if err == nil {
break
}
switch nErr := errors.Cause(err).(type) {
case *mysql.MySQLError:
if nErr.Number == _mySQLErrCodeDuplicateEntry {
log.Error("failed to add member because of duplicate entry, error(%v)", err)
return
}
}
time.Sleep(_userTableUpdateDuration)
}
return
}
func (s *Service) setTokenCache(c context.Context, t *model.Perm) (err error) {
for i := 0; i < _tokenCacheRetryCount; i++ {
if err = s.d.SetTokenCache(c, t); err == nil {
break
}
time.Sleep(_tokenCacheRetryDuration)
}
return
}
func (s *Service) delTokenCache(c context.Context, accessToken string) (err error) {
for i := 0; i < _tokenCacheRetryCount; i++ {
if err = s.d.DelTokenCache(c, accessToken); err == nil {
break
}
time.Sleep(_tokenCacheRetryDuration)
}
return
}
func (s *Service) addToken(c context.Context, t *model.Perm) (err error) {
for i := 0; i < _tokenTableUpdateRetryCount; i++ {
_, err = s.d.AddToken(c, t)
if err == nil {
return
}
switch nErr := errors.Cause(err).(type) {
case *mysql.MySQLError:
if nErr.Number == _mySQLErrCodeDuplicateEntry {
log.Error("failed to add token because of duplicate entry, error(%v)", err)
return
}
}
time.Sleep(_tokenTableUpdateDuration)
}
return
}
func (s *Service) updateToken(c context.Context, t *model.Perm) (err error) {
for i := 0; i < _tokenTableUpdateRetryCount; i++ {
if _, err = s.d.UpdateToken(c, t); err == nil {
return
}
time.Sleep(_tokenTableUpdateDuration)
}
return
}
func (s *Service) delToken(c context.Context, accessToken string) (err error) {
for i := 0; i < _tokenTableUpdateRetryCount; i++ {
if _, err = s.d.DelToken(c, accessToken); err == nil {
return
}
time.Sleep(_tokenTableUpdateDuration)
}
return
}
func (s *Service) notifyGame(c context.Context, mid int64, token, action string) (err error) {
for i := 0; i < _notifyGameRetryCount; i++ {
if err = s.d.NotifyGame(c, mid, token, action); err == nil {
return
}
time.Sleep(_notifyGameRetryDuration)
}
return
}

View File

@@ -0,0 +1,73 @@
package service
import (
"context"
"fmt"
"time"
"go-common/library/log"
"go-common/library/stat/prom"
)
const (
_timeFormat = "2006-01-02 15:04:05"
)
var (
_names = make(map[string]struct{})
_loc = time.Now().Location()
)
// IntervalConfig interval config.
type IntervalConfig struct {
Name string
Rate int64
}
// Interval prom interval.
type Interval struct {
name string
rate int64
counter int64
}
// NewInterval new a interval instance.
func NewInterval(c *IntervalConfig) *Interval {
if _, ok := _names[c.Name]; ok {
panic(fmt.Sprintf("%s already exists", c.Name))
}
_names[c.Name] = struct{}{}
if c.Rate <= 0 {
c.Rate = 1000
}
return &Interval{
name: c.Name,
rate: c.Rate,
counter: 0,
}
}
// MTS get mtime ts from mtime str with interval's counter.
func (s *Interval) MTS(c context.Context, mtStr string) int64 {
s.counter++
if s.counter%s.rate == 0 {
return 0
}
if mtStr == "" {
return 0
}
t, err := time.ParseInLocation(_timeFormat, mtStr, _loc)
if err != nil {
log.Error("failed to parse mtime str for %s, time.ParseInLocation(%s, %s, %v) error(%v)", s.name, _timeFormat, mtStr, _loc, err)
return 0
}
return t.Unix()
}
// Prom prom interval if mts > 0.
func (s *Interval) Prom(c context.Context, mts int64) {
if mts > 0 {
prom.BusinessInfoCount.State(s.name, time.Now().Unix()-mts)
}
}

View File

@@ -0,0 +1,45 @@
package service
import (
"context"
"fmt"
"testing"
"time"
)
func TestNewInterval(t *testing.T) {
name := "counter_1"
NewInterval(&IntervalConfig{
Name: name,
Rate: 1000,
})
defer func() {
expectErrStr := fmt.Sprintf("%s already exists", name)
errStr := recover()
if errStr != expectErrStr {
t.Errorf("must painc when name is not unique, expcted %s but got %v", expectErrStr, errStr)
t.FailNow()
}
}()
NewInterval(&IntervalConfig{
Name: name,
Rate: 1000,
})
}
func TestInterval_Prom(t *testing.T) {
name := "counter_1"
itv := NewInterval(&IntervalConfig{
Name: name,
Rate: 1000,
})
count := 10
mtStr := time.Now().Format(_timeFormat)
for i := 0; i < count; i++ {
itv.Prom(context.TODO(), itv.MTS(context.TODO(), mtStr))
}
if itv.counter != int64(count) {
t.Errorf("interval counter of %s should be %d after get mts for %d times, but now it is %d", name, count, count, itv.counter)
t.FailNow()
}
}

View File

@@ -0,0 +1,152 @@
package service
import (
"context"
"sync"
"time"
"go-common/app/job/main/passport-game-cloud/conf"
"go-common/app/job/main/passport-game-cloud/dao"
"go-common/library/queue/databus"
)
const (
// cache retry count and duration
_accountCacheRetryCount = 3
_accountCacheRetryDuration = time.Second
// table and duration
_asoAccountTable = "aso_account"
_memberTablePrefix = "dede_member"
_changePwd = "changePwd"
_updateUserInfo = "updateUserInfo"
_gameAppID = int32(876)
)
// Service service.
type Service struct {
c *conf.Config
d *dao.Dao
missch chan func()
// prom
tokenInterval *Interval
memberInterval *Interval
asoAccountInterval *Interval
transInterval *Interval
gameAppIDs []int32
// bin log proc
binLogDataBus *databus.Databus
binLogMergeChans []chan *message
binLogDoneChan chan []*message
head, last *message
mu sync.Mutex
// aso acc proc
encryptTransDataBus *databus.Databus
encryptTransMergeChans []chan *message
encryptTransDoneChan chan []*message
asoHead, asoLast *message
asoMu sync.Mutex
}
type message struct {
next *message
data *databus.Message
object interface{}
done bool
}
// New new a service instance.
func New(c *conf.Config) (s *Service) {
gameAppIDs := make([]int32, 0)
gameAppIDs = append(gameAppIDs, _gameAppID)
for _, id := range c.Game.AppIDs {
if id == _gameAppID {
continue
}
gameAppIDs = append(gameAppIDs, id)
}
s = &Service{
c: c,
d: dao.New(c),
missch: make(chan func(), 10240),
// prom
tokenInterval: NewInterval(&IntervalConfig{
Name: "interval_token",
Rate: 1000,
}),
memberInterval: NewInterval(&IntervalConfig{
Name: "interval_member",
Rate: 1000,
}),
asoAccountInterval: NewInterval(&IntervalConfig{
Name: "interval_aso_account",
Rate: 1000,
}),
transInterval: NewInterval(&IntervalConfig{
Name: "interval_trans",
Rate: 1000,
}),
gameAppIDs: gameAppIDs,
binLogDataBus: databus.New(c.DataBus.BinLogSub),
binLogMergeChans: make([]chan *message, c.Group.BinLog.Num),
binLogDoneChan: make(chan []*message, c.Group.BinLog.Chan),
// aso acc proc
encryptTransDataBus: databus.New(c.DataBus.EncryptTransSub),
encryptTransMergeChans: make([]chan *message, c.Group.EncryptTrans.Num),
encryptTransDoneChan: make(chan []*message, c.Group.EncryptTrans.Chan),
}
// start bin log proc
go s.binlogcommitproc()
for i := 0; i < c.Group.BinLog.Num; i++ {
ch := make(chan *message, c.Group.BinLog.Chan)
s.binLogMergeChans[i] = ch
go s.binlogmergeproc(ch)
}
go s.binlogconsumeproc()
// start encrypt trans proc
go s.encrypttranscommitproc()
for i := 0; i < c.Group.EncryptTrans.Num; i++ {
ch := make(chan *message, c.Group.EncryptTrans.Chan)
s.encryptTransMergeChans[i] = ch
go s.encrypttransmergeproc(ch)
}
go s.encrypttransconsumeproc()
// go s.cacheproc()
return
}
//func (s *Service) addCache(f func()) {
// select {
// case s.missch <- f:
// default:
// log.Warn("cache chan full")
// }
//}
// cacheproc is a routine for executing closure.
//func (s *Service) cacheproc() {
// for {
// f := <-s.missch
// f()
// }
//}
// Ping check server ok.
func (s *Service) Ping(c context.Context) (err error) {
err = s.d.Ping(c)
return
}
// Close close service, including closing dao.
func (s *Service) Close() (err error) {
s.binLogDataBus.Close()
s.encryptTransDataBus.Close()
s.d.Close()
return
}

View File

@@ -0,0 +1,31 @@
package service
import (
"sync"
"testing"
"go-common/app/job/main/passport-game-cloud/conf"
. "github.com/smartystreets/goconvey/convey"
)
var (
once sync.Once
s *Service
)
func startService() {
if err := conf.Init(); err != nil {
panic(err)
}
s = New(conf.Conf)
}
func TestNew(t *testing.T) {
once.Do(startService)
Convey("game app ids should ok", t, func() {
So(s.gameAppIDs[0], ShouldEqual, _gameAppID)
t.Logf("s.gameAppIDs: %v", s.gameAppIDs)
})
}