Create & Init Project...
This commit is contained in:
21
app/job/main/relation-cache/BUILD
Normal file
21
app/job/main/relation-cache/BUILD
Normal 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/relation-cache/cmd:all-srcs",
|
||||
"//app/job/main/relation-cache/conf:all-srcs",
|
||||
"//app/job/main/relation-cache/dao:all-srcs",
|
||||
"//app/job/main/relation-cache/model:all-srcs",
|
||||
"//app/job/main/relation-cache/server/http:all-srcs",
|
||||
"//app/job/main/relation-cache/service:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
2
app/job/main/relation-cache/CHANGELOG.md
Normal file
2
app/job/main/relation-cache/CHANGELOG.md
Normal file
@ -0,0 +1,2 @@
|
||||
# v1.0.0
|
||||
1. 用于删除所有关系链的缓存信息
|
14
app/job/main/relation-cache/CONTRIBUTORS.md
Normal file
14
app/job/main/relation-cache/CONTRIBUTORS.md
Normal file
@ -0,0 +1,14 @@
|
||||
# Owner
|
||||
zhoujiahui
|
||||
wanghuan01
|
||||
zhaogangtao
|
||||
|
||||
# Author
|
||||
zhoujiahui
|
||||
wanghuan01
|
||||
zhaogangtao
|
||||
|
||||
# Reviewer
|
||||
zhoujiahui
|
||||
wanghuan01
|
||||
zhaogangtao
|
16
app/job/main/relation-cache/OWNERS
Normal file
16
app/job/main/relation-cache/OWNERS
Normal file
@ -0,0 +1,16 @@
|
||||
# See the OWNERS docs at https://go.k8s.io/owners
|
||||
|
||||
approvers:
|
||||
- wanghuan01
|
||||
- zhaogangtao
|
||||
- zhoujiahui
|
||||
labels:
|
||||
- job
|
||||
- job/main/relation-cache
|
||||
- main
|
||||
options:
|
||||
no_parent_owners: true
|
||||
reviewers:
|
||||
- wanghuan01
|
||||
- zhaogangtao
|
||||
- zhoujiahui
|
12
app/job/main/relation-cache/README.md
Normal file
12
app/job/main/relation-cache/README.md
Normal file
@ -0,0 +1,12 @@
|
||||
# relation-cache-job
|
||||
|
||||
# 项目简介
|
||||
1. 用于关系链的缓存处理任务
|
||||
|
||||
# 编译环境
|
||||
|
||||
|
||||
# 依赖包
|
||||
|
||||
|
||||
# 编译执行
|
1
app/job/main/relation-cache/api/http/api.md
Normal file
1
app/job/main/relation-cache/api/http/api.md
Normal file
@ -0,0 +1 @@
|
||||
# HTTP API文档
|
43
app/job/main/relation-cache/cmd/BUILD
Normal file
43
app/job/main/relation-cache/cmd/BUILD
Normal file
@ -0,0 +1,43 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_binary(
|
||||
name = "cmd",
|
||||
embed = [":go_default_library"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["main.go"],
|
||||
data = ["test.toml"],
|
||||
importpath = "go-common/app/job/main/relation-cache/cmd",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//app/job/main/relation-cache/conf:go_default_library",
|
||||
"//app/job/main/relation-cache/server/http:go_default_library",
|
||||
"//library/ecode/tip:go_default_library",
|
||||
"//library/log:go_default_library",
|
||||
"//library/net/trace: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"],
|
||||
)
|
42
app/job/main/relation-cache/cmd/main.go
Normal file
42
app/job/main/relation-cache/cmd/main.go
Normal file
@ -0,0 +1,42 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"go-common/app/job/main/relation-cache/conf"
|
||||
"go-common/app/job/main/relation-cache/server/http"
|
||||
ecode "go-common/library/ecode/tip"
|
||||
"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.Log)
|
||||
defer log.Close()
|
||||
log.Info("start")
|
||||
trace.Init(conf.Conf.Tracer)
|
||||
defer trace.Close()
|
||||
ecode.Init(conf.Conf.Ecode)
|
||||
http.Init(conf.Conf)
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
|
||||
for {
|
||||
s := <-c
|
||||
log.Info("get a signal %s", s.String())
|
||||
switch s {
|
||||
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
|
||||
log.Info("exit")
|
||||
return
|
||||
case syscall.SIGHUP:
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
35
app/job/main/relation-cache/cmd/test.toml
Normal file
35
app/job/main/relation-cache/cmd/test.toml
Normal file
@ -0,0 +1,35 @@
|
||||
|
||||
[mysql]
|
||||
addr = "127.0.0.1:3306"
|
||||
dsn = "test:test@tcp(127.0.0.1:3306)/test?timeout=200ms&readTimeout=200ms&writeTimeout=200ms&parseTime=true&loc=Local&charset=utf8,utf8mb4"
|
||||
readDSN = ["test:test@tcp(127.0.0.2:3306)/test? timeout=200ms&readTimeout=200ms&writeTimeout=200ms&parseTime=true&loc=Local&charset=utf8,utf8mb4","test:test@tcp(127.0.0.3:3306)/test?timeout=200ms&readTimeout=200ms&writeTimeout=200ms&parseTime=true&loc=Local&charset=utf8,utf8mb4"]
|
||||
active = 20
|
||||
idle = 10
|
||||
idleTimeout ="4h"
|
||||
queryTimeout = "100ms"
|
||||
execTimeout = "100ms"
|
||||
tranTimeout = "200ms"
|
||||
|
||||
[redis]
|
||||
name = "relation-cache-job"
|
||||
proto = "tcp"
|
||||
addr = ""
|
||||
idle = 10
|
||||
active = 10
|
||||
dialTimeout = "1s"
|
||||
readTimeout = "1s"
|
||||
writeTimeout = "1s"
|
||||
idleTimeout = "10s"
|
||||
expire = "1m"
|
||||
|
||||
[memcache]
|
||||
name = "relation-cache-job"
|
||||
proto = "tcp"
|
||||
addr = ""
|
||||
active = 50
|
||||
idle = 10
|
||||
dialTimeout = "1s"
|
||||
readTimeout = "1s"
|
||||
writeTimeout = "1s"
|
||||
idleTimeout = "10s"
|
||||
expire = "24h"
|
42
app/job/main/relation-cache/conf/BUILD
Normal file
42
app/job/main/relation-cache/conf/BUILD
Normal file
@ -0,0 +1,42 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
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/relation-cache/conf",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//library/cache/memcache:go_default_library",
|
||||
"//library/cache/redis:go_default_library",
|
||||
"//library/conf:go_default_library",
|
||||
"//library/database/sql:go_default_library",
|
||||
"//library/ecode/tip:go_default_library",
|
||||
"//library/log:go_default_library",
|
||||
"//library/net/http/blademaster:go_default_library",
|
||||
"//library/net/http/blademaster/middleware/verify: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"],
|
||||
)
|
105
app/job/main/relation-cache/conf/conf.go
Normal file
105
app/job/main/relation-cache/conf/conf.go
Normal file
@ -0,0 +1,105 @@
|
||||
package conf
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
|
||||
"go-common/library/cache/memcache"
|
||||
"go-common/library/cache/redis"
|
||||
"go-common/library/conf"
|
||||
"go-common/library/database/sql"
|
||||
ecode "go-common/library/ecode/tip"
|
||||
"go-common/library/log"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
"go-common/library/net/http/blademaster/middleware/verify"
|
||||
"go-common/library/net/trace"
|
||||
"go-common/library/queue/databus"
|
||||
xtime "go-common/library/time"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
)
|
||||
|
||||
var (
|
||||
confPath string
|
||||
client *conf.Client
|
||||
// Conf config
|
||||
Conf = &Config{}
|
||||
)
|
||||
|
||||
// Config .
|
||||
type Config struct {
|
||||
Log *log.Config
|
||||
BM *bm.ServerConfig
|
||||
Verify *verify.Config
|
||||
Tracer *trace.Config
|
||||
Redis *redis.Config
|
||||
Memcache *memcache.Config
|
||||
MySQL *sql.Config
|
||||
Ecode *ecode.Config
|
||||
RelationBinLog *databus.Config
|
||||
HTTPClient *bm.ClientConfig
|
||||
CacheTTL *CacheTTL
|
||||
}
|
||||
|
||||
// ClearPath clear cache path
|
||||
// type ClearPath struct {
|
||||
// Following string
|
||||
// Follower string
|
||||
// Stat string
|
||||
// }
|
||||
|
||||
// CacheTTL is
|
||||
type CacheTTL struct {
|
||||
RelationTTL xtime.Duration
|
||||
}
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&confPath, "conf", "", "default config path")
|
||||
}
|
||||
|
||||
// Init init conf
|
||||
func Init() 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
|
||||
}
|
59
app/job/main/relation-cache/dao/BUILD
Normal file
59
app/job/main/relation-cache/dao/BUILD
Normal file
@ -0,0 +1,59 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"dao.go",
|
||||
"relation.go",
|
||||
],
|
||||
importpath = "go-common/app/job/main/relation-cache/dao",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//app/job/main/relation-cache/conf:go_default_library",
|
||||
"//app/service/main/relation/model:go_default_library",
|
||||
"//library/cache/memcache:go_default_library",
|
||||
"//library/cache/redis: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",
|
||||
],
|
||||
)
|
||||
|
||||
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 = [
|
||||
"dao_test.go",
|
||||
"relation_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
rundir = ".",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//app/job/main/relation-cache/conf:go_default_library",
|
||||
"//app/service/main/relation/model:go_default_library",
|
||||
"//library/time:go_default_library",
|
||||
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
|
||||
],
|
||||
)
|
59
app/job/main/relation-cache/dao/dao.go
Normal file
59
app/job/main/relation-cache/dao/dao.go
Normal file
@ -0,0 +1,59 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"go-common/app/job/main/relation-cache/conf"
|
||||
"go-common/library/cache/memcache"
|
||||
"go-common/library/cache/redis"
|
||||
xsql "go-common/library/database/sql"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
xtime "go-common/library/time"
|
||||
)
|
||||
|
||||
// Dao dao
|
||||
type Dao struct {
|
||||
*cacheTTL
|
||||
c *conf.Config
|
||||
mc *memcache.Pool
|
||||
redis *redis.Pool
|
||||
db *xsql.DB
|
||||
client *bm.Client
|
||||
}
|
||||
|
||||
// New init mysql db
|
||||
func New(c *conf.Config) (dao *Dao) {
|
||||
dao = &Dao{
|
||||
cacheTTL: &cacheTTL{
|
||||
RelationTTL: asSecond(c.CacheTTL.RelationTTL),
|
||||
},
|
||||
c: c,
|
||||
mc: memcache.NewPool(c.Memcache),
|
||||
redis: redis.NewPool(c.Redis),
|
||||
db: xsql.NewMySQL(c.MySQL),
|
||||
client: bm.NewClient(c.HTTPClient),
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type cacheTTL struct {
|
||||
RelationTTL int64
|
||||
}
|
||||
|
||||
func asSecond(d xtime.Duration) int64 {
|
||||
return int64(time.Duration(d) / time.Second)
|
||||
}
|
||||
|
||||
// Close close the resource.
|
||||
func (d *Dao) Close() {
|
||||
d.mc.Close()
|
||||
d.redis.Close()
|
||||
d.db.Close()
|
||||
}
|
||||
|
||||
// Ping dao ping
|
||||
func (d *Dao) Ping(c context.Context) error {
|
||||
// TODO: if you need use mc,redis, please add
|
||||
return d.db.Ping(c)
|
||||
}
|
33
app/job/main/relation-cache/dao/dao_test.go
Normal file
33
app/job/main/relation-cache/dao/dao_test.go
Normal file
@ -0,0 +1,33 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"go-common/app/job/main/relation-cache/conf"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
d *Dao
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
if os.Getenv("DEPLOY_ENV") != "" {
|
||||
flag.Set("app_id", "main.account.relation-cache-job")
|
||||
flag.Set("conf_token", "db8cc8578e4447edfe1e7385c62be0e5")
|
||||
flag.Set("tree_id", "56981")
|
||||
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")
|
||||
}
|
||||
flag.Parse()
|
||||
if err := conf.Init(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
d = New(conf.Conf)
|
||||
m.Run()
|
||||
os.Exit(0)
|
||||
}
|
164
app/job/main/relation-cache/dao/relation.go
Normal file
164
app/job/main/relation-cache/dao/relation.go
Normal file
@ -0,0 +1,164 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
relation "go-common/app/service/main/relation/model"
|
||||
"go-common/library/cache/memcache"
|
||||
"go-common/library/cache/redis"
|
||||
"go-common/library/log"
|
||||
xtime "go-common/library/time"
|
||||
)
|
||||
|
||||
const (
|
||||
_prefixFollowings = "at_"
|
||||
_prefixTags = "tags_" // user tag info.
|
||||
_prefixFollowing = "pb_a_"
|
||||
_prefixStat = "c_" // key of stat
|
||||
_prefixTagCount = "rs_tmtc_%d" // key of relation tag by mid & tag's count
|
||||
)
|
||||
|
||||
func statKey(mid int64) string {
|
||||
return _prefixStat + strconv.FormatInt(mid, 10)
|
||||
}
|
||||
|
||||
func tagsKey(mid int64) string {
|
||||
return _prefixTags + strconv.FormatInt(mid, 10)
|
||||
}
|
||||
|
||||
func followingsKey(mid int64) string {
|
||||
return _prefixFollowings + strconv.FormatInt(mid, 10)
|
||||
}
|
||||
|
||||
func followingKey(mid int64) string {
|
||||
return _prefixFollowing + strconv.FormatInt(mid, 10)
|
||||
}
|
||||
|
||||
func tagCountKey(mid int64) string {
|
||||
return fmt.Sprintf(_prefixTagCount, mid)
|
||||
}
|
||||
|
||||
// DelStatCache is
|
||||
func (d *Dao) DelStatCache(ctx context.Context, mid int64) error {
|
||||
conn := d.mc.Get(ctx)
|
||||
defer conn.Close()
|
||||
if err := conn.Delete(statKey(mid)); err != nil {
|
||||
if err == memcache.ErrNotFound {
|
||||
return nil
|
||||
}
|
||||
log.Error("Failed to delete stat cache: mid: %d: %+v", mid, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DelFollowerCache del follower cache
|
||||
func (d *Dao) DelFollowerCache(ctx context.Context, fid int64) error {
|
||||
key := followingKey(fid)
|
||||
conn := d.mc.Get(ctx)
|
||||
defer conn.Close()
|
||||
if err := conn.Delete(key); err != nil {
|
||||
if err == memcache.ErrNotFound {
|
||||
err = nil
|
||||
} else {
|
||||
log.Error("conn.Delete(%s) error(%v)", key, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DelFollowing del following cache.
|
||||
func (d *Dao) DelFollowing(c context.Context, mid int64, following *relation.Following) (err error) {
|
||||
var (
|
||||
ok bool
|
||||
key = followingsKey(mid)
|
||||
)
|
||||
conn := d.redis.Get(c)
|
||||
if ok, err = redis.Bool(conn.Do("EXPIRE", key, d.RelationTTL)); err != nil {
|
||||
log.Error("redis.Bool(conn.Do(EXPIRE, %s)) error(%v)", key, err)
|
||||
} else if ok {
|
||||
if _, err = conn.Do("HDEL", key, following.Mid); err != nil {
|
||||
log.Error("conn.Do(HDEL, %s, %d) error(%v)", key, following.Mid, err)
|
||||
}
|
||||
}
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
|
||||
// DelTagsCache is
|
||||
func (d *Dao) DelTagsCache(ctx context.Context, mid int64) (err error) {
|
||||
conn := d.mc.Get(ctx)
|
||||
if err = conn.Delete(tagsKey(mid)); err != nil {
|
||||
if err == memcache.ErrNotFound {
|
||||
err = nil
|
||||
} else {
|
||||
log.Error("conn.Delete(%s) error(%v)", tagCountKey(mid), err)
|
||||
}
|
||||
}
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
|
||||
// AddFollowingCache is
|
||||
func (d *Dao) AddFollowingCache(c context.Context, mid int64, following *relation.Following) (err error) {
|
||||
var (
|
||||
ok bool
|
||||
key = followingsKey(mid)
|
||||
)
|
||||
conn := d.redis.Get(c)
|
||||
if ok, err = redis.Bool(conn.Do("EXPIRE", key, d.RelationTTL)); err != nil {
|
||||
log.Error("redis.Bool(conn.Do(EXPIRE, %s)) error(%v)", key, err)
|
||||
} else if ok {
|
||||
var ef []byte
|
||||
if ef, err = d.encode(following.Attribute, following.MTime, following.Tag, following.Special); err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = conn.Do("HSET", key, following.Mid, ef); err != nil {
|
||||
log.Error("conn.Do(HSET, %s, %d) error(%v)", key, following.Mid, err)
|
||||
}
|
||||
}
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
|
||||
// encode
|
||||
func (d *Dao) encode(attribute uint32, mtime xtime.Time, tagids []int64, special int32) (res []byte, err error) {
|
||||
ft := &relation.FollowingTags{Attr: attribute, Ts: mtime, TagIds: tagids, Special: special}
|
||||
return ft.Marshal()
|
||||
}
|
||||
|
||||
// DelFollowingCache delete following cache.
|
||||
func (d *Dao) DelFollowingCache(c context.Context, mid int64) (err error) {
|
||||
return d.delFollowingCache(c, followingKey(mid))
|
||||
}
|
||||
|
||||
// delFollowingCache delete following cache.
|
||||
func (d *Dao) delFollowingCache(c context.Context, key string) (err error) {
|
||||
conn := d.mc.Get(c)
|
||||
if err = conn.Delete(key); err != nil {
|
||||
if err == memcache.ErrNotFound {
|
||||
err = nil
|
||||
} else {
|
||||
log.Error("conn.Delete(%s) error(%v)", key, err)
|
||||
}
|
||||
}
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
|
||||
// DelTagCountCache del tag count cache.
|
||||
func (d *Dao) DelTagCountCache(c context.Context, mid int64) (err error) {
|
||||
conn := d.mc.Get(c)
|
||||
if err = conn.Delete(tagCountKey(mid)); err != nil {
|
||||
if err == memcache.ErrNotFound {
|
||||
err = nil
|
||||
} else {
|
||||
log.Error("conn.Delete(%s) error(%v)", tagCountKey(mid), err)
|
||||
}
|
||||
}
|
||||
conn.Close()
|
||||
return
|
||||
}
|
192
app/job/main/relation-cache/dao/relation_test.go
Normal file
192
app/job/main/relation-cache/dao/relation_test.go
Normal file
@ -0,0 +1,192 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
relation "go-common/app/service/main/relation/model"
|
||||
xtime "go-common/library/time"
|
||||
"testing"
|
||||
|
||||
"github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestDaostatKey(t *testing.T) {
|
||||
var (
|
||||
mid = int64(1)
|
||||
)
|
||||
convey.Convey("statKey", t, func(ctx convey.C) {
|
||||
p1 := statKey(mid)
|
||||
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
|
||||
ctx.So(p1, convey.ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaotagsKey(t *testing.T) {
|
||||
var (
|
||||
mid = int64(1)
|
||||
)
|
||||
convey.Convey("tagsKey", t, func(ctx convey.C) {
|
||||
p1 := tagsKey(mid)
|
||||
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
|
||||
ctx.So(p1, convey.ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaofollowingsKey(t *testing.T) {
|
||||
var (
|
||||
mid = int64(1)
|
||||
)
|
||||
convey.Convey("followingsKey", t, func(ctx convey.C) {
|
||||
p1 := followingsKey(mid)
|
||||
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
|
||||
ctx.So(p1, convey.ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaofollowingKey(t *testing.T) {
|
||||
var (
|
||||
mid = int64(1)
|
||||
)
|
||||
convey.Convey("followingKey", t, func(ctx convey.C) {
|
||||
p1 := followingKey(mid)
|
||||
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
|
||||
ctx.So(p1, convey.ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaotagCountKey(t *testing.T) {
|
||||
var (
|
||||
mid = int64(1)
|
||||
)
|
||||
convey.Convey("tagCountKey", t, func(ctx convey.C) {
|
||||
p1 := tagCountKey(mid)
|
||||
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
|
||||
ctx.So(p1, convey.ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoDelStatCache(t *testing.T) {
|
||||
var (
|
||||
c = context.Background()
|
||||
mid = int64(1)
|
||||
)
|
||||
convey.Convey("DelStatCache", t, func(ctx convey.C) {
|
||||
err := d.DelStatCache(c, mid)
|
||||
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoDelFollowerCache(t *testing.T) {
|
||||
var (
|
||||
c = context.Background()
|
||||
mid = int64(1)
|
||||
)
|
||||
convey.Convey("DelFollowerCache", t, func(ctx convey.C) {
|
||||
err := d.DelFollowerCache(c, mid)
|
||||
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoDelFollowing(t *testing.T) {
|
||||
var (
|
||||
c = context.Background()
|
||||
mid = int64(1)
|
||||
following = &relation.Following{}
|
||||
)
|
||||
convey.Convey("DelFollowing", t, func(ctx convey.C) {
|
||||
err := d.DelFollowing(c, mid, following)
|
||||
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoDelTagsCache(t *testing.T) {
|
||||
var (
|
||||
c = context.Background()
|
||||
mid = int64(1)
|
||||
)
|
||||
convey.Convey("DelTagsCache", t, func(ctx convey.C) {
|
||||
err := d.DelTagsCache(c, mid)
|
||||
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoAddFollowingCache(t *testing.T) {
|
||||
var (
|
||||
c = context.Background()
|
||||
mid = int64(1)
|
||||
following = &relation.Following{}
|
||||
)
|
||||
convey.Convey("AddFollowingCache", t, func(ctx convey.C) {
|
||||
err := d.AddFollowingCache(c, mid, following)
|
||||
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoencode(t *testing.T) {
|
||||
var (
|
||||
attribute = uint32(1)
|
||||
mtime xtime.Time
|
||||
tagids = []int64{1}
|
||||
special = int32(1)
|
||||
)
|
||||
convey.Convey("encode", t, func(ctx convey.C) {
|
||||
res, err := d.encode(attribute, mtime, tagids, special)
|
||||
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 TestDaoDelFollowingCache(t *testing.T) {
|
||||
var (
|
||||
c = context.Background()
|
||||
mid = int64(1)
|
||||
)
|
||||
convey.Convey("DelFollowingCache", t, func(ctx convey.C) {
|
||||
err := d.DelFollowingCache(c, mid)
|
||||
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaodelFollowingCache(t *testing.T) {
|
||||
var (
|
||||
c = context.Background()
|
||||
key = ""
|
||||
)
|
||||
convey.Convey("delFollowingCache", t, func(ctx convey.C) {
|
||||
err := d.delFollowingCache(c, key)
|
||||
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestDaoDelTagCountCache(t *testing.T) {
|
||||
var (
|
||||
c = context.Background()
|
||||
mid = int64(0)
|
||||
)
|
||||
convey.Convey("DelTagCountCache", t, func(ctx convey.C) {
|
||||
err := d.DelTagCountCache(c, mid)
|
||||
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
31
app/job/main/relation-cache/model/BUILD
Normal file
31
app/job/main/relation-cache/model/BUILD
Normal file
@ -0,0 +1,31 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"model.go",
|
||||
"retry.go",
|
||||
],
|
||||
importpath = "go-common/app/job/main/relation-cache/model",
|
||||
tags = ["automanaged"],
|
||||
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"],
|
||||
)
|
32
app/job/main/relation-cache/model/model.go
Normal file
32
app/job/main/relation-cache/model/model.go
Normal file
@ -0,0 +1,32 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
// Message define binlog databus message.
|
||||
type Message struct {
|
||||
Action string `json:"action"`
|
||||
Table string `json:"table"`
|
||||
New json.RawMessage `json:"new"`
|
||||
Old json.RawMessage `json:"old"`
|
||||
}
|
||||
|
||||
// Stat is
|
||||
type Stat struct {
|
||||
Mid int64 `json:"mid,omitempty"`
|
||||
Following int64 `json:"following"`
|
||||
Whisper int64 `json:"whisper"`
|
||||
Black int64 `json:"black"`
|
||||
Follower int64 `json:"follower"`
|
||||
}
|
||||
|
||||
// Relation is
|
||||
type Relation struct {
|
||||
Mid int64 `json:"mid,omitempty"`
|
||||
Fid int64 `json:"fid,omitempty"`
|
||||
Attribute uint32 `json:"attribute"`
|
||||
Status int `json:"status"`
|
||||
MTime string `json:"mtime"`
|
||||
CTime string `json:"ctime"`
|
||||
}
|
26
app/job/main/relation-cache/model/retry.go
Normal file
26
app/job/main/relation-cache/model/retry.go
Normal file
@ -0,0 +1,26 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Retry is
|
||||
func Retry(attempts int, sleep time.Duration, fn func() error) error {
|
||||
if err := fn(); err != nil {
|
||||
if s, ok := err.(stop); ok {
|
||||
// Return the original error for later checking
|
||||
return s.error
|
||||
}
|
||||
|
||||
if attempts--; attempts > 0 {
|
||||
time.Sleep(sleep)
|
||||
return Retry(attempts, 2*sleep, fn)
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type stop struct {
|
||||
error
|
||||
}
|
35
app/job/main/relation-cache/server/http/BUILD
Normal file
35
app/job/main/relation-cache/server/http/BUILD
Normal file
@ -0,0 +1,35 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
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/relation-cache/server/http",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//app/job/main/relation-cache/conf:go_default_library",
|
||||
"//app/job/main/relation-cache/service:go_default_library",
|
||||
"//library/log:go_default_library",
|
||||
"//library/net/http/blademaster:go_default_library",
|
||||
"//library/net/http/blademaster/middleware/verify: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"],
|
||||
)
|
53
app/job/main/relation-cache/server/http/http.go
Normal file
53
app/job/main/relation-cache/server/http/http.go
Normal file
@ -0,0 +1,53 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"go-common/app/job/main/relation-cache/conf"
|
||||
"go-common/app/job/main/relation-cache/service"
|
||||
"go-common/library/log"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
"go-common/library/net/http/blademaster/middleware/verify"
|
||||
)
|
||||
|
||||
var (
|
||||
srv *service.Service
|
||||
vfy *verify.Verify
|
||||
)
|
||||
|
||||
// Init init
|
||||
func Init(c *conf.Config) {
|
||||
srv = service.New(c)
|
||||
vfy = verify.New(c.Verify)
|
||||
engine := bm.DefaultServer(c.BM)
|
||||
router(engine)
|
||||
if err := engine.Start(); err != nil {
|
||||
log.Error("engine.Start() error(%v)", err)
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func router(e *bm.Engine) {
|
||||
e.Ping(ping)
|
||||
e.Register(register)
|
||||
g := e.Group("/x/relation-cache")
|
||||
{
|
||||
g.GET("/start", vfy.Verify, howToStart)
|
||||
}
|
||||
}
|
||||
|
||||
func ping(c *bm.Context) {
|
||||
if err := srv.Ping(c); err != nil {
|
||||
log.Error("ping error(%v)", err)
|
||||
c.AbortWithStatus(http.StatusServiceUnavailable)
|
||||
}
|
||||
}
|
||||
|
||||
func register(c *bm.Context) {
|
||||
c.JSON(map[string]interface{}{}, nil)
|
||||
}
|
||||
|
||||
// example for http request handler
|
||||
func howToStart(c *bm.Context) {
|
||||
c.String(0, "Golang 大法好 !!!")
|
||||
}
|
41
app/job/main/relation-cache/service/BUILD
Normal file
41
app/job/main/relation-cache/service/BUILD
Normal file
@ -0,0 +1,41 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"relation.go",
|
||||
"service.go",
|
||||
],
|
||||
importpath = "go-common/app/job/main/relation-cache/service",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//app/job/main/relation-cache/conf:go_default_library",
|
||||
"//app/job/main/relation-cache/dao:go_default_library",
|
||||
"//app/job/main/relation-cache/model:go_default_library",
|
||||
"//app/service/main/relation/model:go_default_library",
|
||||
"//library/log:go_default_library",
|
||||
"//library/queue/databus:go_default_library",
|
||||
"//library/time:go_default_library",
|
||||
"//vendor/github.com/pkg/errors: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"],
|
||||
)
|
149
app/job/main/relation-cache/service/relation.go
Normal file
149
app/job/main/relation-cache/service/relation.go
Normal file
@ -0,0 +1,149 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"go-common/app/job/main/relation-cache/model"
|
||||
relation "go-common/app/service/main/relation/model"
|
||||
"go-common/library/log"
|
||||
"go-common/library/queue/databus"
|
||||
xtime "go-common/library/time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
_relationFidTable = "user_relation_fid_"
|
||||
_relationMidTable = "user_relation_mid_"
|
||||
_relationStatTable = "user_relation_stat_"
|
||||
_relationTagUserTable = "user_relation_tag_user_"
|
||||
)
|
||||
|
||||
func (s *Service) relationBinLogproc(ctx context.Context) {
|
||||
for msg := range s.relationBinLog.Messages() {
|
||||
if err := s.handleRelationBinLog(ctx, msg); err != nil {
|
||||
log.Error("Failed to handle relation binlog: %s: %+v", BeautifyMessage(msg), err)
|
||||
continue
|
||||
}
|
||||
log.Info("Succeed to handle relation binlog: %s", BeautifyMessage(msg))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) handleRelationBinLog(ctx context.Context, msg *databus.Message) error {
|
||||
defer func() {
|
||||
if err := msg.Commit(); err != nil {
|
||||
log.Error("Failed to commit message: %+v", BeautifyMessage(msg))
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
mu := &model.Message{}
|
||||
if err := json.Unmarshal(msg.Value, mu); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
switch {
|
||||
case strings.HasPrefix(mu.Table, _relationStatTable):
|
||||
if err := s.stat(ctx, mu.Action, mu.New, mu.Old); err != nil {
|
||||
return err
|
||||
}
|
||||
case strings.HasPrefix(mu.Table, _relationMidTable):
|
||||
if err := s.relationMid(ctx, mu.Action, mu.New, mu.Old); err != nil {
|
||||
return err
|
||||
}
|
||||
case strings.HasPrefix(mu.Table, _relationFidTable):
|
||||
if err := s.relationFid(ctx, mu.Action, mu.New, mu.Old); err != nil {
|
||||
return err
|
||||
}
|
||||
case strings.HasPrefix(mu.Table, _relationTagUserTable):
|
||||
if err := s.tagUser(ctx, mu.New); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// stat
|
||||
func (s *Service) stat(ctx context.Context, action string, nwMsg []byte, oldMsg []byte) (err error) {
|
||||
ms := &model.Stat{}
|
||||
if err = json.Unmarshal(nwMsg, ms); err != nil {
|
||||
log.Error("json.Unmarshal(%v) error(%v)", nwMsg, err)
|
||||
return
|
||||
}
|
||||
mo := &model.Stat{}
|
||||
if len(oldMsg) > 0 {
|
||||
if err = json.Unmarshal(oldMsg, mo); err != nil {
|
||||
log.Error("json.Unmarshal(%v) error(%v)", oldMsg, err)
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
return s.dao.DelStatCache(ctx, ms.Mid)
|
||||
}
|
||||
|
||||
// relationMid
|
||||
func (s *Service) relationMid(ctx context.Context, action string, nwMsg []byte, oldMsg []byte) error {
|
||||
mr := &model.Relation{}
|
||||
if err := json.Unmarshal(nwMsg, mr); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
f := &relation.Following{
|
||||
Mid: mr.Fid,
|
||||
Attribute: mr.Attribute,
|
||||
MTime: xtime.Time(time.Now().Unix()),
|
||||
}
|
||||
if err := s.upFollowingCache(ctx, mr.Mid, f); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return s.dao.DelTagsCache(ctx, mr.Mid)
|
||||
}
|
||||
|
||||
// relationFid
|
||||
func (s *Service) relationFid(ctx context.Context, action string, nwMsg []byte, oldMsg []byte) error {
|
||||
var or *model.Relation
|
||||
mr := &model.Relation{}
|
||||
if err := json.Unmarshal(nwMsg, mr); err != nil {
|
||||
log.Error("json.Unmarshal(%v) error(%v)", nwMsg, err)
|
||||
return err
|
||||
}
|
||||
|
||||
if len(oldMsg) > 0 {
|
||||
or = new(model.Relation)
|
||||
if err := json.Unmarshal(oldMsg, or); err != nil {
|
||||
log.Error("json.Unmarshal(%v) error(%v)", oldMsg, err)
|
||||
}
|
||||
}
|
||||
|
||||
return s.dao.DelFollowerCache(ctx, mr.Fid)
|
||||
}
|
||||
|
||||
func (s *Service) tagUser(ctx context.Context, newMsg []byte) (err error) {
|
||||
var tags struct {
|
||||
Fid int64 `json:"fid"`
|
||||
Mid int64 `json:"mid"`
|
||||
}
|
||||
if err = json.Unmarshal(newMsg, &tags); err != nil {
|
||||
log.Error("json.Unmarshal err(%v)", err)
|
||||
return
|
||||
}
|
||||
return s.dao.DelTagsCache(ctx, tags.Mid)
|
||||
}
|
||||
|
||||
func (s *Service) upFollowingCache(c context.Context, mid int64, f *relation.Following) (err error) {
|
||||
if f.Attribute == 0 {
|
||||
s.dao.DelFollowing(c, mid, f)
|
||||
} else {
|
||||
if err = s.dao.AddFollowingCache(c, mid, f); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
if err = s.dao.DelFollowingCache(c, mid); err != nil {
|
||||
return
|
||||
}
|
||||
return s.dao.DelTagCountCache(c, mid)
|
||||
}
|
68
app/job/main/relation-cache/service/service.go
Normal file
68
app/job/main/relation-cache/service/service.go
Normal file
@ -0,0 +1,68 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"go-common/app/job/main/relation-cache/conf"
|
||||
"go-common/app/job/main/relation-cache/dao"
|
||||
"go-common/library/queue/databus"
|
||||
)
|
||||
|
||||
// Service struct
|
||||
type Service struct {
|
||||
c *conf.Config
|
||||
dao *dao.Dao
|
||||
relationBinLog *databus.Databus
|
||||
waiter *sync.WaitGroup
|
||||
}
|
||||
|
||||
// New init
|
||||
func New(c *conf.Config) (s *Service) {
|
||||
s = &Service{
|
||||
c: c,
|
||||
dao: dao.New(c),
|
||||
relationBinLog: databus.New(c.RelationBinLog),
|
||||
waiter: &sync.WaitGroup{},
|
||||
}
|
||||
s.Start(context.Background())
|
||||
return s
|
||||
}
|
||||
|
||||
// Start to handle requests
|
||||
func (s *Service) Start(ctx context.Context) {
|
||||
for i := 0; i < 50; i++ {
|
||||
go s.relationBinLogproc(context.Background())
|
||||
}
|
||||
}
|
||||
|
||||
// Ping Service
|
||||
func (s *Service) Ping(c context.Context) (err error) {
|
||||
return s.dao.Ping(c)
|
||||
}
|
||||
|
||||
// Close Service
|
||||
func (s *Service) Close() {
|
||||
s.dao.Close()
|
||||
}
|
||||
|
||||
// BeautifyMessage is
|
||||
func BeautifyMessage(msg *databus.Message) string {
|
||||
pmsg := struct {
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
Topic string `json:"topic"`
|
||||
Partition int32 `json:"partition"`
|
||||
Offset int64 `json:"offset"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}{
|
||||
Key: msg.Key,
|
||||
Value: string(msg.Value),
|
||||
Topic: msg.Topic,
|
||||
Partition: msg.Partition,
|
||||
Offset: msg.Offset,
|
||||
Timestamp: msg.Timestamp,
|
||||
}
|
||||
return fmt.Sprintf("%+v", pmsg)
|
||||
}
|
Reference in New Issue
Block a user