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,60 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["document_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/interface/main/kvo/conf:go_default_library",
"//app/interface/main/kvo/model/module:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/container/pool:go_default_library",
"//library/database/sql:go_default_library",
"//library/net/netutil/breaker:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"document.go",
"service.go",
],
importpath = "go-common/app/interface/main/kvo/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/kvo/conf:go_default_library",
"//app/interface/main/kvo/dao:go_default_library",
"//app/interface/main/kvo/model:go_default_library",
"//app/interface/main/kvo/model/module:go_default_library",
"//library/database/sql:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/stat/prom: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,179 @@
package service
import (
"context"
"encoding/json"
"time"
"go-common/app/interface/main/kvo/model"
"go-common/app/interface/main/kvo/model/module"
"go-common/library/database/sql"
"go-common/library/ecode"
"go-common/library/log"
)
// Document get document
func (s *Service) Document(c context.Context, mid int64, moduleKey string, timestamp int64, checkSum int64) (setting *module.Setting, err error) {
var (
uc *model.UserConf
rm json.RawMessage
moduleKeyID int
)
if moduleKeyID = module.VerifyModuleKey(moduleKey); moduleKeyID == 0 {
err = ecode.RequestErr
return
}
uc, err = s.userConf(c, mid, moduleKeyID)
if err != nil {
return
}
if uc.CheckSum == 0 || uc.Timestamp == 0 {
err = ecode.NotModified
return
}
// 数据没有变动
if uc.CheckSum == checkSum && uc.Timestamp == timestamp {
err = ecode.NotModified
return
}
rm, err = s.document(c, uc.CheckSum)
if err != nil {
return
}
setting = &module.Setting{
Timestamp: uc.Timestamp,
CheckSum: uc.CheckSum,
Data: rm,
}
return
}
func (s *Service) userConf(c context.Context, mid int64, moduleKeyID int) (uc *model.UserConf, err error) {
uc, err = s.da.UserConfCache(c, mid, moduleKeyID)
if err != nil {
log.Error("service.userConf.UserConfCache(%v,%v) err:%v", mid, moduleKeyID, err)
}
if uc != nil {
s.sp.Incr("user_conf_cached")
return
}
uc, err = s.da.UserConf(c, mid, moduleKeyID)
if err != nil {
log.Error("service.userConf(%v,%v) err:%v", mid, moduleKeyID, err)
return
}
if uc == nil {
uc = &model.UserConf{
Mid: mid,
ModuleKey: moduleKeyID,
}
s.sp.Incr("default_user_conf")
}
s.sp.Incr("user_conf_missed")
s.updateUcCache(mid, moduleKeyID)
return
}
func (s *Service) document(c context.Context, checkSum int64) (rm json.RawMessage, err error) {
var (
doc *model.Document
)
rm, err = s.da.DocumentCache(c, checkSum)
if err != nil {
log.Error("service.document.DocumentCache(%v) err:%v", checkSum, err)
}
if rm != nil {
s.sp.Incr("document_cached")
return
}
doc, err = s.da.Document(c, checkSum)
if err != nil {
log.Error("service.document(%v) err:%v", checkSum, err)
return
}
if doc == nil {
err = ecode.NothingFound
s.sp.Incr("user_conf_document_error")
return
}
s.sp.Incr("document_missed")
rm = json.RawMessage(doc.Doc)
s.da.SetDocumentCache(c, checkSum, rm)
return
}
// AddDocument add a user document
func (s *Service) AddDocument(c context.Context, mid int64, moduleKey string, data string, timestamp int64, oldSum int64, now time.Time) (resp *model.UserConf, err error) {
var (
uc *model.UserConf
doc *model.Document
rm json.RawMessage
checkSum int64
tx *sql.Tx
moduleKeyID int
)
if moduleKeyID = module.VerifyModuleKey(moduleKey); moduleKeyID == 0 {
return nil, ecode.RequestErr
}
if rm, checkSum, err = module.Result(moduleKeyID, data); err != nil {
log.Error("service.GetModule(%v,%s) err:%v", moduleKey, data, err)
return nil, ecode.RequestErr
}
if len(rm) > s.docLimit {
err = ecode.KvoDataOverLimit
return
}
if uc, err = s.da.UserConf(c, mid, moduleKeyID); err != nil {
log.Error("service.AddDocument.UserConf(%v,%v) err:%v", mid, moduleKeyID, err)
return
}
s.updateUcCache(mid, moduleKeyID)
if uc != nil {
if uc.Timestamp != timestamp {
err = ecode.KvoTimestampErr
log.Error("service.AddDocument.CompareTimeStamp(%v,%v,%v) err:%v", mid, uc.Timestamp, timestamp, err)
return
}
if uc.CheckSum != oldSum {
err = ecode.KvoCheckSumErr
return
}
if uc.CheckSum == checkSum {
err = ecode.NotModified
return
}
}
// trans
tx, err = s.da.BeginTx(c)
if err != nil {
log.Error("s.da.BeginTx err:%v", err)
return
}
if err = s.da.TxUpUserConf(c, tx, mid, moduleKeyID, checkSum, now); err != nil {
log.Error("s.da.TxUpUserConf(%v,%v,%v) error(%v)", mid, moduleKeyID, checkSum, err)
tx.Rollback()
return
}
doc, err = s.da.Document(c, checkSum)
if err != nil {
tx.Rollback()
return
}
if doc == nil {
if err = s.da.TxUpDocuement(c, tx, checkSum, string(rm), now); err != nil {
log.Error("s.da.TxUpDocuement(%v,%v,%v) error(%v)", mid, moduleKeyID, checkSum, err)
tx.Rollback()
return
}
}
if err = tx.Commit(); err != nil {
log.Error("tx.Commit(), error(%v)", err)
}
resp = &model.UserConf{
CheckSum: checkSum,
Timestamp: now.Unix(),
}
s.updateUcCache(mid, moduleKeyID)
return
}

View File

@@ -0,0 +1,78 @@
package service
import (
"context"
"encoding/json"
"testing"
"time"
conf "go-common/app/interface/main/kvo/conf"
"go-common/app/interface/main/kvo/model/module"
"go-common/library/cache/memcache"
"go-common/library/container/pool"
"go-common/library/database/sql"
"go-common/library/net/netutil/breaker"
xtime "go-common/library/time"
. "github.com/smartystreets/goconvey/convey"
)
func getService() *Service {
s := New(&conf.Config{
Rule: &conf.Rule{DocLimit: 1024 * 1024 * 1024},
Memcache: &conf.KvoMemcache{
Kvo: &memcache.Config{
Config: &pool.Config{
Active: 10,
Idle: 4,
IdleTimeout: xtime.Duration(time.Second),
},
Name: "kvo",
Proto: "tcp",
Addr: "127.0.0.1:11211",
DialTimeout: xtime.Duration(time.Second),
ReadTimeout: xtime.Duration(time.Second),
WriteTimeout: xtime.Duration(time.Second),
},
Expire: xtime.Duration(time.Hour),
},
Mysql: &sql.Config{
Addr: "localhost:3306",
DSN: "root:123@tcp(localhost:3306)/bilibili?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8,utf8mb4",
Active: 10,
Idle: 4,
IdleTimeout: xtime.Duration(time.Second),
QueryTimeout: xtime.Duration(time.Second),
ExecTimeout: xtime.Duration(time.Second),
TranTimeout: xtime.Duration(time.Second),
Breaker: &breaker.Config{
Window: xtime.Duration(time.Second),
Sleep: xtime.Duration(time.Second),
Bucket: 10,
Ratio: 0.5,
Request: 100,
},
},
})
return s
}
func TestAddDocument(t *testing.T) {
Convey("", t, func() {
s := getService()
p := &module.Player{
PlayerWebDanmakuAutoscaling: false,
}
bs, _ := json.Marshal(p)
_, err := s.AddDocument(context.Background(), 1, "player", string(bs), 0, 0, time.Now())
So(nil, ShouldEqual, err)
})
}
func TestDocument(t *testing.T) {
Convey("", t, func() {
s := getService()
_, err := s.Document(context.Background(), 1, "player", 1234, 12345)
So(nil, ShouldEqual, err)
})
}

View File

@@ -0,0 +1,67 @@
package service
import (
"context"
conf "go-common/app/interface/main/kvo/conf"
"go-common/app/interface/main/kvo/dao"
"go-common/library/log"
"go-common/library/stat/prom"
)
// Service kvo main service
type Service struct {
da *dao.Dao
docLimit int
sp *prom.Prom
cacheUcCh chan *cacheUc
}
type cacheUc struct {
mid int64
moduleKeyID int
}
// New get a kvo service
func New(c *conf.Config) *Service {
da := dao.New(c)
s := &Service{
da: da,
// limit data size
docLimit: c.Rule.DocLimit,
cacheUcCh: make(chan *cacheUc, 1024),
sp: prom.New().WithCounter("conf_cache", []string{"method"}),
}
go s.cacheUcProc()
return s
}
func (s *Service) updateUcCache(mid int64, moduleKeyID int) {
select {
case s.cacheUcCh <- &cacheUc{
mid: mid,
moduleKeyID: moduleKeyID,
}:
default:
log.Info("s.cacheUcCh is full")
}
}
func (s *Service) cacheUcProc() {
for cuc := range s.cacheUcCh {
uc, err := s.da.UserConf(context.Background(), cuc.mid, cuc.moduleKeyID)
if err != nil {
log.Error("service.cacheUcProc(%v,%v),err:%v", cuc.mid, cuc.moduleKeyID)
continue
}
if uc != nil {
s.da.SetUserConfCache(context.Background(), uc)
}
}
}
// Ping kvo service check
func (s *Service) Ping(ctx context.Context) (err error) {
return s.da.Ping(ctx)
}