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

21
app/job/main/figure/BUILD Normal file
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/figure/cmd:all-srcs",
"//app/job/main/figure/conf:all-srcs",
"//app/job/main/figure/dao:all-srcs",
"//app/job/main/figure/http:all-srcs",
"//app/job/main/figure/model:all-srcs",
"//app/job/main/figure/service:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,54 @@
信用积分项目-服务
===============
v1.3.1
1. 优化ping , 去掉中间件ping
v1.3.0
1. update hbase client
v1.2.1
1. 优化日志方便debug
v1.2.0
1. http router to bm
v1.1.6
1. 切换databus topic :
MemberExpLog-T --> AccountLog-T
UserActive-T --> AccountLog-T
v1.1.5
1. 修复redis超时时间错误
v1.1.4
1. 防止mid<=0并增加日志
v1.1.3
1. 引入弹幕举报
v1.1.2
1. add reply report
v1.1.1
1. fix pay data
v1.1.0
1. 引入评论举报,风纪委评分
v1.0.5
1. 增加prom监控
v1.0.4
1. 修复评论点踩数据入库问题
v1.0.3
1. 导入vip数据
v1.0.2
1. 新增数据同步功能
v1.0.1
1. 加入若干日志
v1.0.0
1. 初始化项目,更新依赖

View File

@@ -0,0 +1,10 @@
# Owner
zhaogangtao
# Author
muyang
yubaihai
# Reviewer
linmiao
zhaogangtao

View File

@@ -0,0 +1,17 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- muyang
- yubaihai
- zhaogangtao
labels:
- job
- job/main/figure
- main
options:
no_parent_owners: true
reviewers:
- linmiao
- muyang
- yubaihai
- zhaogangtao

View File

@@ -0,0 +1,10 @@
#### figure-job
##### 项目简介
> 1.用户信用分
##### 编译环境
> 请只用golang v1.8.x以上版本编译执行。
##### 依赖包
> 1.公共包go-common

View File

@@ -0,0 +1,44 @@
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 = ["figure-job-test.toml"],
importpath = "go-common/app/job/main/figure/cmd",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/figure/conf:go_default_library",
"//app/job/main/figure/http:go_default_library",
"//app/job/main/figure/service:go_default_library",
"//library/log:go_default_library",
"//library/os/signal:go_default_library",
"//library/syscall: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,212 @@
version = "1.0.0"
user = "nobody"
pid = "/tmp/figure-job.pid"
dir = "./"
perf = "127.0.0.1:7070"
checkFile = "/data/www/figure-job.html"
family = "figure-job"
[log]
dir = "/data/log/figure-job"
[bm]
addr = "0.0.0.0:7072"
timeout = "1s"
maxListen = 100
[figure]
spypath = "./data/spy"
vippath = "./data/vip"
sync = false
lawful = 80
wide = 0
friendly = 50
bounty = 0
creativity = 0
[mysql]
addr = "172.16.0.28:3306"
dsn = "root:123456@tcp(172.16.0.28:3306)/bilibili_figure?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 5
idle = 2
queryTimeout = "1s"
execTimeout = "1s"
tranTimeout = "1s"
[mysql.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[dataSource]
[dataSource.accountExp]
key = "0QEO9F8JuuIxZzNDvklH"
secret= "0QEO9F8JuuIxZzNDvklI"
group= "AccountLog-MainAccount-Figure-S"
topic= "AccountLog-T"
action="sub"
name = "figure-job/databus"
proto = "tcp"
addr = "172.16.33.158:6205"
idle = 2
active = 10
dialTimeout = "1s"
readTimeout = "60s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "1h"
[dataSource.accountReg]
key = "0QEO9F8JuuIxZzNDvklH"
secret= "0QEO9F8JuuIxZzNDvklI"
group= "PassportPurgeCache-Figure-S"
topic= "PassportPurgeCache-T"
action="sub"
name = "figure-job/databus"
proto = "tcp"
addr = "172.16.33.158:6205"
idle = 2
active = 10
dialTimeout = "1s"
readTimeout = "60s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "1h"
[dataSource.vip]
key = "0QEO9F8JuuIxZzNDvklH"
secret= "0QEO9F8JuuIxZzNDvklI"
group= "VipBinlog-Figure-S"
topic= "VipBinlog-T"
action="sub"
name = "figure-job/databus"
proto = "tcp"
addr = "172.16.33.158:6205"
idle = 2
active = 10
dialTimeout = "1s"
readTimeout = "60s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "1h"
[dataSource.spy]
key = "0QEO9F8JuuIxZzNDvklH"
secret= "0QEO9F8JuuIxZzNDvklI"
group= "Spy-Figure-S"
topic= "Spy-T"
action="sub"
name = "figure-job/databus"
proto = "tcp"
addr = "172.16.33.158:6205"
idle = 2
active = 10
dialTimeout = "1s"
readTimeout = "60s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "1h"
[dataSource.coin]
key = "0QEO9F8JuuIxZzNDvklH"
secret= "0QEO9F8JuuIxZzNDvklI"
group= "Coin-Figure-S"
topic= "Coin-T"
action="sub"
name = "figure-job/databus"
proto = "tcp"
addr = "172.16.33.158:6205"
idle = 2
active = 10
dialTimeout = "1s"
readTimeout = "60s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "1h"
[dataSource.replyInfo]
key = "0QEO9F8JuuIxZzNDvklH"
secret= "0QEO9F8JuuIxZzNDvklI"
group= "Reply-Figure-S"
topic= "Reply-T"
action="sub"
name = "figure-job/databus"
proto = "tcp"
addr = "172.16.33.158:6205"
idle = 2
active = 10
dialTimeout = "1s"
readTimeout = "60s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "1h"
# [dataSource.pay]
# key = "0QEO9F8JuuIxZzNDvklH"
# secret= "0QEO9F8JuuIxZzNDvklI"
# group= "PayBinlog-Figure-S"
# topic= "PayBinlog-T"
# action="sub"
# name = "figure-job/databus"
# proto = "tcp"
# addr = "172.16.33.158:6205"
# idle = 2
# active = 10
# dialTimeout = "1s"
# readTimeout = "60s"
# writeTimeout = "1s"
# idleTimeout = "10s"
# expire = "1h"
# [dataSource.blocked]
# key = "0QEO9F8JuuIxZzNDvklH"
# secret= "0QEO9F8JuuIxZzNDvklI"
# group= "Blocked-Figure-S"
# topic= "Blocked-T"
# action="sub"
# name = "figure-job/databus"
# proto = "tcp"
# addr = "172.16.33.158:6205"
# idle = 2
# active = 10
# dialTimeout = "1s"
# readTimeout = "60s"
# writeTimeout = "1s"
# idleTimeout = "10s"
# expire = "1h"
# [dataSource.danmaku]
# key = "0QEO9F8JuuIxZzNDvklH"
# secret= "0QEO9F8JuuIxZzNDvklI"
# group= "DMAction-Figure-S"
# topic= "DMAction-T"
# action="sub"
# name = "figure-job/databus"
# proto = "tcp"
# addr = "172.16.33.158:6205"
# idle = 2
# active = 10
# dialTimeout = "1s"
# readTimeout = "60s"
# writeTimeout = "1s"
# idleTimeout = "10s"
# expire = "1h"
[hbase]
master = ""
meta = ""
dialTimeout = "1s"
readTimeout = "10s"
readsTimeout = "10s"
writeTimeout = "10s"
writesTimeout = "10s"
[hbase.zookeeper]
root = ""
addrs = ["10.23.66.145:2181"]
timeout = "30s"
[redis]
name = "figure-service"
proto = "tcp"
addr = "172.16.33.54:6379"
idle = 100
active = 100
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "24h"
waiteMidExpire = "192h"

View File

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

View File

@@ -0,0 +1,17 @@
[property]
# 信用分同步数据目录
spypath = "./data/spy"
# vip同步数据目录
vippath = "./data/vip"
# 启动同步数据开关
sync = false
# 守序初始分
lawful = 8000
# 博览初始分
wide = 0
# 有爱初始分
friendly = 5000
# 慷慨初始分
bounty = 0
# 创造初始分
creativity = 0

View File

@@ -0,0 +1,48 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["conf_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
)
go_library(
name = "go_default_library",
srcs = ["conf.go"],
importpath = "go-common/app/job/main/figure/conf",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/cache/redis:go_default_library",
"//library/conf:go_default_library",
"//library/database/hbase.v2:go_default_library",
"//library/database/sql:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster: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,126 @@
package conf
import (
"errors"
"flag"
"go-common/library/cache/redis"
"go-common/library/conf"
"go-common/library/database/hbase.v2"
"go-common/library/database/sql"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/queue/databus"
xtime "go-common/library/time"
"github.com/BurntSushi/toml"
)
var (
confPath string
client *conf.Client
Conf = &Config{}
)
// Config def.
type Config struct {
// base
// log
Log *log.Config
// http
BM *bm.ServerConfig
Figure figure
// databus
DataSource *DataSource
// hbase
HBase *HBaseConfig
// redis
Redis *Redis
// mysql
Mysql *sql.Config
}
type figure struct {
Sync bool
SpyPath string
VipPath string
Lawful int32
Wide int32
Friendly int32
Bounty int32
Creativity int32
}
// DataSource config all figure job dataSource
type DataSource struct {
AccountExp *databus.Config
AccountReg *databus.Config
Vip *databus.Config
Spy *databus.Config
Coin *databus.Config
ReplyInfo *databus.Config
Pay *databus.Config
Blocked *databus.Config
Danmaku *databus.Config
}
// Redis conf.
type Redis struct {
*redis.Config
Expire xtime.Duration
WaiteMidExpire xtime.Duration
}
// HBaseConfig extra hbase config
type HBaseConfig struct {
*hbase.Config
ReadTimeout xtime.Duration
WriteTimeout xtime.Duration
}
func init() {
flag.StringVar(&confPath, "conf", "", "config path")
}
// Init init conf.
func Init() (err error) {
if confPath == "" {
return configCenter()
}
_, err = toml.DecodeFile(confPath, &Conf)
return
}
func configCenter() (err error) {
if client, err = conf.New(); err != nil {
panic(err)
}
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,17 @@
package conf
import (
"flag"
"testing"
)
func TestInit(t *testing.T) {
flag.Parse()
var err error
if err = Init(); err != nil {
t.Fatal(err)
}
if Conf == nil {
t.Fatal()
}
}

View File

@@ -0,0 +1,68 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"account_test.go",
"dao_test.go",
"hbase_test.go",
"mysql_test.go",
"redis_test.go",
"vip_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/figure/conf:go_default_library",
"//app/job/main/figure/model:go_default_library",
"//library/log:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"account.go",
"blocked.go",
"danmaku.go",
"dao.go",
"hbase.go",
"mysql.go",
"redis.go",
"vip.go",
],
importpath = "go-common/app/job/main/figure/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/figure/conf:go_default_library",
"//app/job/main/figure/model:go_default_library",
"//library/cache/redis:go_default_library",
"//library/database/hbase.v2:go_default_library",
"//library/database/sql:go_default_library",
"//library/log: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"],
)

View File

@@ -0,0 +1,42 @@
package dao
import (
"context"
"encoding/binary"
"time"
"go-common/app/job/main/figure/conf"
"go-common/app/job/main/figure/model"
"github.com/pkg/errors"
)
// UpdateAccountExp update user exp
func (d *Dao) UpdateAccountExp(c context.Context, mid, exp int64) (err error) {
var (
expByte = make([]byte, 8)
ctx, cancel = context.WithTimeout(c, time.Duration(conf.Conf.HBase.WriteTimeout))
)
defer cancel()
binary.BigEndian.PutUint64(expByte, uint64(exp))
values := map[string]map[string][]byte{model.USFamilyUser: map[string][]byte{model.USColumnExp: expByte}}
if _, err = d.hbase.PutStr(ctx, model.UserInfoTable, d.rowKey(mid), values); err != nil {
err = errors.Wrapf(err, "mid(%d), hbase.Put(key: %s, values: %v)", d.rowKey(mid), values)
}
return
}
// IncArchiveViews .
func (d *Dao) IncArchiveViews(c context.Context, mid int64) (err error) {
var (
incrByte = make([]byte, 8)
ctx, cancel = context.WithTimeout(c, time.Duration(conf.Conf.HBase.WriteTimeout))
)
defer cancel()
binary.BigEndian.PutUint64(incrByte, uint64(1))
values := map[string]map[string][]byte{model.USFamilyUser: map[string][]byte{model.USColumnArchiveViews: incrByte}}
if _, err = d.hbase.Increment(ctx, model.UserInfoTable, d.rowKey(mid), values); err != nil {
err = errors.Wrapf(err, "msg(%v), hbase.Increment(key: %s values: %v)", mid, d.rowKey(mid), values)
}
return
}

View File

@@ -0,0 +1,20 @@
package dao
import (
"context"
"testing"
)
func TestPubStat(t *testing.T) {
once.Do(startService)
if err := d.UpdateAccountExp(context.TODO(), 7593623, 120.00); err != nil {
t.Errorf("d.UpdateAccountExp(%d) error(%v)", 7593623, err)
}
}
func TestIncArchiveViews(t *testing.T) {
once.Do(startService)
if err := d.IncArchiveViews(context.TODO(), 7593623); err != nil {
t.Errorf("error(%v)", err)
}
}

View File

@@ -0,0 +1,27 @@
package dao
import (
"context"
"encoding/binary"
"time"
"go-common/app/job/main/figure/conf"
"go-common/app/job/main/figure/model"
"github.com/pkg/errors"
)
// BlockedRage .
func (d *Dao) BlockedRage(c context.Context, mid int64, vs int16) (err error) {
var (
rageByte = make([]byte, 8)
ctx, cancel = context.WithTimeout(c, time.Duration(conf.Conf.HBase.WriteTimeout))
)
defer cancel()
binary.BigEndian.PutUint16(rageByte, uint16(vs))
values := map[string]map[string][]byte{model.USFamilyUser: map[string][]byte{model.USColumnBlockedRage: rageByte}}
if _, err = d.hbase.PutStr(ctx, model.UserInfoTable, d.rowKey(mid), values); err != nil {
err = errors.Wrapf(err, "mid(%v), hbase.Put(key: %s values: %v)", mid, mid, values)
}
return
}

View File

@@ -0,0 +1,31 @@
package dao
import (
"bytes"
"context"
"encoding/binary"
"time"
"go-common/app/job/main/figure/conf"
"go-common/app/job/main/figure/model"
"go-common/library/log"
"github.com/pkg/errors"
)
// DanmakuReport .
func (d *Dao) DanmakuReport(c context.Context, mid int64, column string, incr int64) (err error) {
var (
key = d.rowVerKey(mid, time.Now())
ctx, cancel = context.WithTimeout(c, time.Duration(conf.Conf.HBase.WriteTimeout))
)
defer cancel()
log.Info("Put danmaku act key [%s] c [%s] incr [%d]", key, column, incr)
bytesBuffer := bytes.NewBuffer([]byte{})
binary.Write(bytesBuffer, binary.BigEndian, incr)
values := map[string]map[string][]byte{model.ACFamilyUser: map[string][]byte{column: bytesBuffer.Bytes()}}
if _, err = d.hbase.Increment(ctx, model.ActionCounterTable, key, values); err != nil {
err = errors.Wrapf(err, "msg(%d,%s,%d), hbase.Increment(key: %s values: %v)", mid, column, incr, key, values)
}
return
}

View File

@@ -0,0 +1,63 @@
package dao
import (
"context"
"time"
"go-common/app/job/main/figure/conf"
"go-common/library/cache/redis"
"go-common/library/database/hbase.v2"
"go-common/library/database/sql"
)
// Dao figure job dao
type Dao struct {
c *conf.Config
hbase *hbase.Client
db *sql.DB
redis *redis.Pool
redisExpire int
waiteMidExpire int
}
// New new a figure DAO
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
hbase: hbase.NewClient(c.HBase.Config),
db: sql.NewMySQL(c.Mysql),
redis: redis.NewPool(c.Redis.Config),
redisExpire: int(time.Duration(c.Redis.Expire) / time.Second),
waiteMidExpire: int(time.Duration(c.Redis.WaiteMidExpire) / time.Second),
}
return
}
// Ping check service health
func (d *Dao) Ping(c context.Context) (err error) {
return d.PingRedis(c)
}
// Close close all dao.
func (d *Dao) Close() {
if d.hbase != nil {
d.hbase.Close()
}
}
//Version get ever monday start time ts.
func (d *Dao) Version(now time.Time) (ts int64) {
var (
n int8
)
y, m, day := now.Date()
w := now.Weekday()
switch w {
case time.Sunday:
n = 6
default:
n = int8(w) - 1
}
t := time.Date(y, m, day, 0, 0, 0, 0, time.Local).Add(-time.Duration(n) * 24 * time.Hour)
return t.Unix()
}

View File

@@ -0,0 +1,54 @@
package dao
import (
"flag"
"path/filepath"
"sync"
"time"
"go-common/app/job/main/figure/conf"
"go-common/library/log"
. "github.com/smartystreets/goconvey/convey"
)
var (
once sync.Once
d *Dao
)
func initConf() {
if err := conf.Init(); err != nil {
panic(err)
}
log.Init(conf.Conf.Log)
defer log.Close()
}
func startService() {
initConf()
if d == nil {
d = New(conf.Conf)
}
time.Sleep(time.Second * 2)
}
func CleanDB() {
}
func init() {
dir, _ := filepath.Abs("../cmd/figure-job-test.toml")
flag.Set("conf", dir)
conf.Init()
if d == nil {
d = New(conf.Conf)
}
}
func WithDao(f func(d *Dao)) func() {
return func() {
Reset(func() { CleanDB() })
f(d)
}
}

View File

@@ -0,0 +1,110 @@
package dao
import (
"bytes"
"context"
"encoding/binary"
"fmt"
"time"
"go-common/app/job/main/figure/conf"
"go-common/app/job/main/figure/model"
"go-common/library/log"
"github.com/pkg/errors"
)
func (d *Dao) rowKey(mid int64) (res string) {
res = fmt.Sprintf("%d", mid)
return
}
func (d *Dao) rowVerKey(mid int64, now time.Time) (res string) {
res = fmt.Sprintf("%d_%d", mid, d.Version(now))
return
}
// PutSpyScore add spy score info.
func (d *Dao) PutSpyScore(c context.Context, mid int64, score int8) (err error) {
var (
key = d.rowKey(mid)
scoreB = make([]byte, 8)
ctx, cancel = context.WithTimeout(c, time.Duration(conf.Conf.HBase.WriteTimeout))
)
defer cancel()
log.Info("Put spy score key [%s] score [%d]", key, score)
binary.BigEndian.PutUint64(scoreB, uint64(score))
values := map[string]map[string][]byte{model.USFamilyUser: map[string][]byte{model.USColumnSpyScore: scoreB}}
if _, err = d.hbase.PutStr(ctx, model.UserInfoTable, key, values); err != nil {
log.Error("hbase.Put error(%v)", err)
}
return
}
// PutReplyAct add spy score info.
func (d *Dao) PutReplyAct(c context.Context, mid int64, column string, incr int64) (err error) {
var (
key = d.rowVerKey(mid, time.Now())
ctx, cancel = context.WithTimeout(c, time.Duration(conf.Conf.HBase.WriteTimeout))
)
defer cancel()
log.Info("Put reply act key [%s] c [%s] incr [%d]", key, column, incr)
bytesBuffer := bytes.NewBuffer([]byte{})
binary.Write(bytesBuffer, binary.BigEndian, incr)
values := map[string]map[string][]byte{model.ACFamilyUser: map[string][]byte{column: bytesBuffer.Bytes()}}
if _, err = d.hbase.Increment(ctx, model.ActionCounterTable, key, values); err != nil {
err = errors.Wrapf(err, "msg(%d,%s,%d), hbase.Increment(key: %s values: %v)", mid, column, incr, key, values)
}
return
}
// PutCoinUnusual coin unusual.
func (d *Dao) PutCoinUnusual(c context.Context, mid int64, column string) (err error) {
var (
key = d.rowVerKey(mid, time.Now())
incrBytes = make([]byte, 8)
ctx, cancel = context.WithTimeout(c, time.Duration(conf.Conf.HBase.WriteTimeout))
)
defer cancel()
log.Info("Put coin unusual key [%s] c [%s]", key, column)
binary.BigEndian.PutUint64(incrBytes, uint64(1))
values := map[string]map[string][]byte{model.ACFamilyUser: map[string][]byte{column: incrBytes}}
if _, err = d.hbase.Increment(ctx, model.ActionCounterTable, key, values); err != nil {
err = errors.Wrapf(err, "msg(%d,%s), hbase.Increment(key: %s values: %v)", mid, column, key, values)
}
return
}
// PutCoinCount coin count.
func (d *Dao) PutCoinCount(c context.Context, mid int64) (err error) {
var (
key = d.rowVerKey(mid, time.Now())
incrBytes = make([]byte, 8)
ctx, cancel = context.WithTimeout(c, time.Duration(conf.Conf.HBase.WriteTimeout))
)
defer cancel()
log.Info("Put coin count key [%s]", key)
binary.BigEndian.PutUint64(incrBytes, uint64(1))
values := map[string]map[string][]byte{model.ACFamilyUser: map[string][]byte{model.ACColumnCoins: incrBytes}}
if _, err = d.hbase.Increment(ctx, model.ActionCounterTable, key, values); err != nil {
err = errors.Wrapf(err, "msg(%d), hbase.Increment(key: %s values: %v)", mid, key, values)
}
return
}
// PayOrderInfo user pay order info.
func (d *Dao) PayOrderInfo(c context.Context, column string, mid, money int64) (err error) {
var (
key = d.rowVerKey(mid, time.Now())
incrBytes = make([]byte, 8)
ctx, cancel = context.WithTimeout(c, time.Duration(conf.Conf.HBase.WriteTimeout))
)
defer cancel()
log.Info("Pay Order key [%s]", key)
binary.BigEndian.PutUint64(incrBytes, uint64(money))
values := map[string]map[string][]byte{model.ACFamilyUser: map[string][]byte{column: incrBytes}}
if _, err = d.hbase.Increment(ctx, model.ActionCounterTable, key, values); err != nil {
err = errors.Wrapf(err, "msg(%d,%s,%d), hbase.Increment(key: %s values: %v)", mid, column, key, values)
}
return
}

View File

@@ -0,0 +1,54 @@
package dao
import (
"context"
"go-common/app/job/main/figure/model"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
var (
mid int64 = 15555180
score int8 = 60
)
//go test -test.v -test.run TestPutSpyScore
func TestPutSpyScore(t *testing.T) {
Convey("TestPutSpyScore no err", t, WithDao(func(d *Dao) {
err := d.PutSpyScore(context.TODO(), mid, score)
So(err, ShouldBeNil)
}))
}
//go test -test.v -test.run TestPutReplyAct
func TestPutReplyAct(t *testing.T) {
Convey("TestPutReplyAct no err", t, WithDao(func(d *Dao) {
err := d.PutReplyAct(context.TODO(), mid, model.ACColumnReplyLiked, int64(-1))
So(err, ShouldBeNil)
}))
}
//go test -test.v -test.run TestPutCoinUnusual
func TestPutCoinUnusual(t *testing.T) {
Convey("TestPutCoinUnusual no err", t, WithDao(func(d *Dao) {
err := d.PutCoinUnusual(context.TODO(), mid, model.ACColumnLowRisk)
So(err, ShouldBeNil)
}))
}
//go test -test.v -test.run TestPutCoinCount
func TestPutCoinCount(t *testing.T) {
Convey("TestPutCoinCount no err", t, WithDao(func(d *Dao) {
err := d.PutCoinCount(context.TODO(), mid)
So(err, ShouldBeNil)
}))
}
//go test -test.v -test.run TestPayOrderInfo
func TestPayOrderInfo(t *testing.T) {
Convey("PayOrderInfo no err", t, WithDao(func(d *Dao) {
err := d.PayOrderInfo(context.TODO(), "", mid, 1253)
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,49 @@
package dao
import (
"context"
"fmt"
"go-common/app/job/main/figure/model"
"go-common/library/database/sql"
"go-common/library/log"
"github.com/pkg/errors"
)
const (
_shard = 100
_insertFigure = "INSERT INTO figure_user_%02d (mid,score,lawful_score,wide_score,friendly_score,bounty_score,creativity_score,ver,ctime,mtime) VALUES (?,?,?,?,?,?,?,?,?,?)"
_existFigure = "SELECT id FROM figure_user_%02d WHERE mid=? LIMIT 1"
)
func hit(mid int64) int64 {
return mid % _shard
}
// ExistFigure exist user figure info
func (d *Dao) ExistFigure(c context.Context, mid int64) (id int64, err error) {
res := d.db.QueryRow(c, fmt.Sprintf(_existFigure, hit(mid)), mid)
if err = res.Scan(&id); err != nil {
if err == sql.ErrNoRows {
err = nil
return
}
errors.Wrapf(err, "row.Scan(%d) error", mid)
}
return
}
// SaveFigure init user figure info
func (d *Dao) SaveFigure(c context.Context, f *model.Figure) (id int64, err error) {
res, err := d.db.Exec(c, fmt.Sprintf(_insertFigure, hit(f.Mid)), f.Mid, f.Score, f.LawfulScore, f.WideScore, f.FriendlyScore, f.BountyScore, f.CreativityScore, f.Ver, f.Ctime, f.Mtime)
if err != nil {
errors.Wrapf(err, "init user(%d) Figure info error(%v)", f.Mid, err)
return
}
if id, err = res.LastInsertId(); err != nil {
log.Error("res.LastInsertId() error(%v)", err)
}
return
}

View File

@@ -0,0 +1,37 @@
package dao
import (
"context"
"testing"
"time"
"go-common/app/job/main/figure/model"
)
func TestSaveFigure(t *testing.T) {
once.Do(startService)
f := &model.Figure{
Mid: 761223,
Score: 100,
LawfulScore: d.c.Figure.Lawful,
WideScore: d.c.Figure.Wide,
FriendlyScore: d.c.Figure.Friendly,
BountyScore: d.c.Figure.Bounty,
CreativityScore: d.c.Figure.Creativity,
Ver: 1,
Ctime: time.Now(),
Mtime: time.Now(),
}
if id, err := d.SaveFigure(context.TODO(), f); err != nil {
t.Errorf("figure err (%v)", err)
} else {
t.Logf("id(%d)", id)
}
}
func TestGetFigure(t *testing.T) {
once.Do(startService)
var mid int64 = 7593623
id, _ := d.ExistFigure(context.TODO(), mid)
t.Logf("id:%d", id)
}

View File

@@ -0,0 +1,86 @@
package dao
import (
"context"
"encoding/json"
"fmt"
"go-common/app/job/main/figure/model"
"go-common/library/log"
"github.com/pkg/errors"
)
const (
_keyWaitDealUser = "w:u" // b_batch_no wait block
_figureKey = "f:%d"
)
func figureKey(mid int64) string {
return fmt.Sprintf(_figureKey, mid)
}
// keyWaitBlock return block cache key.
func keyWaitBlock(version int64, mid int64) string {
return fmt.Sprintf("%s%d%d", _keyWaitDealUser, version, mid%10000)
}
// SetWaiteUserCache set waite deal user cache.
func (d *Dao) SetWaiteUserCache(c context.Context, mid int64, ver int64) (err error) {
if mid <= 0 {
log.Error("%+v", errors.Errorf("SetWaiteUserCache mid [%d] ver [%d] error", mid, ver))
return
}
var (
key = keyWaitBlock(ver, mid)
conn = d.redis.Get(c)
)
defer conn.Close()
if err = conn.Send("SADD", key, mid); err != nil {
log.Error("conn.Send error(%v)", err)
return
}
if err = conn.Send("EXPIRE", key, d.waiteMidExpire); err != nil {
log.Error("conn.Send error(%v)", err)
return
}
if err = conn.Flush(); err != nil {
log.Error("conn.Flush error(%v)", err)
return
}
for i := 0; i < 2; i++ {
if _, err = conn.Receive(); err != nil {
log.Error("conn.Receive error(%v)", err)
return
}
}
return
}
// AddFigureInfoCache put figure to redis
func (d *Dao) AddFigureInfoCache(c context.Context, f *model.Figure) (err error) {
key := figureKey(f.Mid)
conn := d.redis.Get(c)
defer conn.Close()
values, err := json.Marshal(f)
if err != nil {
return
}
if err = conn.Send("SET", key, values); err != nil {
log.Error("conn.Send(SET, %s, %d) error(%v)", key, values, err)
return
}
if err = conn.Send("EXPIRE", key, d.redisExpire); err != nil {
log.Error("conn.Send(Expire, %s, %d) error(%v)", key, d.redisExpire, err)
return
}
return
}
// PingRedis check redis connection
func (d *Dao) PingRedis(c context.Context) (err error) {
conn := d.redis.Get(c)
_, err = conn.Do("SET", "PING", "PONG")
conn.Close()
return
}

View File

@@ -0,0 +1,32 @@
package dao
import (
"context"
"go-common/app/job/main/figure/model"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
var (
testRedisMid int64 = 15555180
)
func Test_PingRedis(t *testing.T) {
Convey("ping redis", t, WithDao(func(d *Dao) {
So(d.PingRedis(context.TODO()), ShouldBeNil)
}))
}
func Test_SetWaiteUserCache(t *testing.T) {
Convey("set waite user cache", t, WithDao(func(d *Dao) {
So(d.SetWaiteUserCache(context.TODO(), testRedisMid, 111), ShouldBeNil)
}))
}
func Test_AddFigureInfoCache(t *testing.T) {
Convey("add figure info cache", t, WithDao(func(d *Dao) {
f := &model.Figure{Mid: testRedisMid}
So(d.AddFigureInfoCache(context.TODO(), f), ShouldBeNil)
}))
}

View File

@@ -0,0 +1,27 @@
package dao
import (
"context"
"encoding/binary"
"time"
"go-common/app/job/main/figure/conf"
"go-common/app/job/main/figure/model"
"github.com/pkg/errors"
)
// UpdateVipStatus .
func (d *Dao) UpdateVipStatus(c context.Context, mid int64, vs int32) (err error) {
var (
vipByte = make([]byte, 8)
ctx, cancel = context.WithTimeout(c, time.Duration(conf.Conf.HBase.WriteTimeout))
)
defer cancel()
binary.BigEndian.PutUint64(vipByte, uint64(vs))
values := map[string]map[string][]byte{model.USFamilyUser: map[string][]byte{model.USColumnVipStatus: vipByte}}
if _, err = d.hbase.PutStr(ctx, model.UserInfoTable, d.rowKey(mid), values); err != nil {
err = errors.Wrapf(err, "mid(%v), hbase.Put(key: %s values: %v)", mid, d.rowKey(mid), values)
}
return
}

View File

@@ -0,0 +1,11 @@
package dao
import (
"context"
"testing"
)
func TestUpdateVipStatus(t *testing.T) {
once.Do(startService)
d.UpdateVipStatus(context.TODO(), 7593623, 1)
}

View File

@@ -0,0 +1,3 @@
create 'figure:userstatus', 'user'
create 'figure:acioncounter', 'user'
create 'figure:calcrecord','x'

View File

@@ -0,0 +1,34 @@
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/figure/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/figure/conf:go_default_library",
"//app/job/main/figure/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,37 @@
package http
import (
"go-common/app/job/main/figure/conf"
"go-common/app/job/main/figure/service"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
)
var (
svc *service.Service
)
// Init init a http server
func Init(s *service.Service) {
svc = s
e := bm.DefaultServer(conf.Conf.BM)
innerRouter(e)
if err := e.Start(); err != nil {
log.Error("%+v", err)
panic(err)
}
}
// innerRouter init inner router.
func innerRouter(e *bm.Engine) {
e.Ping(ping)
}
// ping check server ok.
func ping(c *bm.Context) {
// if err := svc.Ping(c); err != nil {
// log.Error("figure-job ping err (%+v)", err)
// c.AbortWithStatus(http.StatusServiceUnavailable)
// }
}

View File

@@ -0,0 +1,38 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"hbase.go",
"model.go",
"msg.go",
"reply.go",
],
importpath = "go-common/app/job/main/figure/model",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/reply/model/reply:go_default_library",
"//library/log: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"],
)

View File

@@ -0,0 +1,54 @@
package model
var (
//ActionCounterTable action counter
ActionCounterTable = "ugc:figureactioncounter"
//ACFamilyUser user family
ACFamilyUser = "user"
//ACColumnCoins column
ACColumnCoins = "coins"
//ACColumnDanmaku column
ACColumnDanmaku = "danmuka"
//ACColumnReplyAct reply act
ACColumnReplyAct = "replies"
//ACColumnReplyLiked reply like
ACColumnReplyLiked = "reply_liked"
//ACColumnReplyHate reply hate
ACColumnReplyHate = "reply_hate"
//ACColumnLowRisk low risk
ACColumnLowRisk = "coin_low_risk"
//ACColumnHighRisk high risk
ACColumnHighRisk = "coin_high_risk"
//ACColumnReplyReoprtPassed report reply passed
ACColumnReplyReoprtPassed = "report_reply_passed"
//ACColumnDanmakuReoprtPassed danmaku reply passed
ACColumnDanmakuReoprtPassed = "report_danmaku_passed"
//ACColumnPublishReplyDeleted report reply passed
ACColumnPublishReplyDeleted = "publish_reply_deleted"
//ACColumnPublishDanmakuDeleted report reply passed
ACColumnPublishDanmakuDeleted = "publish_danmaku_deleted"
//ACColumnPayMoney user pay money
ACColumnPayMoney = "pay_money"
//ACColumnPayLiveMoney user pay money for live
ACColumnPayLiveMoney = "pay_live_money"
//UserInfoTable user info
UserInfoTable = "ugc:figureuserstatus"
//USFamilyUser user family
USFamilyUser = "user"
//USColumnExp exp
USColumnExp = "exp"
//USColumnSpyScore spy score
USColumnSpyScore = "spy_score"
//USColumnArchiveViews archive views
USColumnArchiveViews = "archive_views"
//USColumnVipStatus vip status
USColumnVipStatus = "vip_status"
//USColumnBlockedRage blocked rage
USColumnBlockedRage = "blocked_rage"
)

View File

@@ -0,0 +1,60 @@
package model
import (
"encoding/json"
"time"
)
// Figure user figure model
type Figure struct {
ID int32 `json:"-"`
Mid int64 `json:"mid"`
Score int32 `json:"score"`
LawfulScore int32 `json:"lawful_score"`
WideScore int32 `json:"wide_score"`
FriendlyScore int32 `json:"friendly_score"`
BountyScore int32 `json:"bounty_score"`
CreativityScore int32 `json:"creativity_score"`
Ver int32 `json:"-"`
Ctime time.Time `json:"-"`
Mtime time.Time `json:"-"`
}
// BinlogMsg dm binlog msg
type BinlogMsg struct {
Action string `json:"action"`
Table string `json:"table"`
New json.RawMessage `json:"new"`
Old json.RawMessage `json:"old"`
}
// ReplyInfo Reply info.
type ReplyInfo struct {
Mid int64 `json:"mid"`
Oid int64 `json:"oid"`
Type int8 `json:"type"`
Ctime int64 `json:"ctime"`
}
// ReplyAction reply action.
type ReplyAction struct {
Mid int64 `json:"mid"`
Action int8 `json:"action"`
Oid int64 `json:"oid"`
Type int8 `json:"type"`
Ctime int64 `json:"ctime"`
}
// DMAction danmaku report action.
type DMAction struct {
Action string `json:"action"`
Data DMData `json:"data"`
}
// DMData danmaku report action.
type DMData struct {
ID int64 `json:"id"`
Dmid int64 `json:"dmid"`
OwnerUID int64 `json:"dm_owner_uid"`
ReportUID int64 `json:"uid"`
}

View File

@@ -0,0 +1,65 @@
package model
import (
"encoding/json"
"strconv"
"go-common/library/log"
"github.com/pkg/errors"
)
// MsgCanal canal message struct
type MsgCanal struct {
Action string `json:"action"`
Table string `json:"table"`
New json.RawMessage `json:"new"`
Old json.RawMessage `json:"old"`
}
// MsgVipInfo message for user vip staus
type MsgVipInfo struct {
Mid int64 `json:"mid"`
Type int8 `json:"type"`
Timestamp int64 `json:"ts"`
}
type MsgAccountLog struct {
Mid int64 `json:"mid"`
IP string `json:"ip"`
TS int64 `json:"ts"`
Content map[string]string `json:"content"`
}
func (m *MsgAccountLog) ExpFrom() (exp int) {
var (
fromExp = m.Content["from_exp"]
err error
)
if exp, err = strconv.Atoi(fromExp); err != nil {
err = errors.Wrapf(err, "fromExp (%s)", fromExp)
log.Error("%+v", err)
exp = 0
}
return
}
func (m *MsgAccountLog) ExpTo() (exp int) {
var (
toExp = m.Content["to_exp"]
err error
)
if exp, err = strconv.Atoi(toExp); err != nil {
err = errors.Wrapf(err, "toExp (%s)", toExp)
log.Error("%+v", err)
exp = 0
}
return
}
func (m *MsgAccountLog) IsViewExp() bool {
var (
operater = m.Content["operater"]
)
return operater == "watch"
}

View File

@@ -0,0 +1,31 @@
package model
import (
repmol "go-common/app/job/main/reply/model/reply"
)
// ReplyEvent reply event
type ReplyEvent struct {
Action string `json:"action"`
Mid int64 `json:"mid"`
Subject *repmol.Subject `json:"subject"`
Reply *repmol.Reply `json:"reply"`
Report *repmol.Report `json:"report"`
}
const (
// EventAdd add reply
EventAdd = "reply"
// EventLike add like
EventLike = "like"
// EventLikeCancel like cal
EventLikeCancel = "like_cancel"
// EventHate hate
EventHate = "hate"
// EventHateCancel hate cal
EventHateCancel = "hate_cancel"
// EventReportDel user report approved
EventReportDel = "report_del"
// EventReportRecover user report recover
EventReportRecover = "report_recover"
)

View File

@@ -0,0 +1,73 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"account_test.go",
"coin_test.go",
"reply_test.go",
"service_test.go",
"spy_test.go",
"vip_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/figure/conf:go_default_library",
"//app/job/main/figure/model:go_default_library",
"//app/job/main/reply/model/reply:go_default_library",
"//app/service/main/coin/model:go_default_library",
"//app/service/main/spy/model:go_default_library",
"//library/log:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"account.go",
"blocked.go",
"coin.go",
"danmaku.go",
"pay.go",
"reply.go",
"service.go",
"spy.go",
"sync.go",
"vip.go",
],
importpath = "go-common/app/job/main/figure/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/figure/conf:go_default_library",
"//app/job/main/figure/dao:go_default_library",
"//app/job/main/figure/model:go_default_library",
"//app/service/main/coin/model:go_default_library",
"//app/service/main/spy/model:go_default_library",
"//library/log:go_default_library",
"//library/queue/databus: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,46 @@
package service
import (
"context"
"time"
"go-common/app/job/main/figure/model"
"go-common/library/log"
)
// AccountExp handle user exp chenage message
func (s *Service) AccountExp(c context.Context, mid, exp int64) (err error) {
s.figureDao.UpdateAccountExp(c, mid, exp)
return
}
// AccountReg handle user register message, init user figure info
func (s *Service) AccountReg(c context.Context, mid int64) (err error) {
var id int64
if id, err = s.figureDao.ExistFigure(c, mid); err != nil || id != 0 {
log.Info("user(%d) already init", mid)
return
}
f := &model.Figure{
Mid: mid,
LawfulScore: s.c.Figure.Lawful,
WideScore: s.c.Figure.Wide,
FriendlyScore: s.c.Figure.Friendly,
BountyScore: s.c.Figure.Bounty,
CreativityScore: s.c.Figure.Creativity,
Ver: 1,
Ctime: time.Now(),
Mtime: time.Now(),
}
if _, err = s.figureDao.SaveFigure(c, f); err != nil {
return
}
s.figureDao.AddFigureInfoCache(c, f)
return
}
// AccountViewVideo handle user view video message
func (s *Service) AccountViewVideo(c context.Context, mid int64) (err error) {
s.figureDao.IncArchiveViews(c, mid)
return
}

View File

@@ -0,0 +1,31 @@
package service
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
var (
testAccountMid int64 = 152
testExp int64 = 10
)
func TestSaveFigure(t *testing.T) {
once.Do(startService)
s.AccountReg(context.TODO(), 7593623)
}
// go test -test.v -test.run TestAccountExp
func TestAccountExp(t *testing.T) {
Convey("TestSaveFigure put account exp", t, WithService(func(s *Service) {
So(s.AccountReg(context.TODO(), 10), ShouldBeNil)
}))
Convey("TestAccountExp put account exp", t, WithService(func(s *Service) {
So(s.AccountExp(context.TODO(), testAccountMid, testExp), ShouldBeNil)
}))
Convey("TestAccountViewVideo put account exp", t, WithService(func(s *Service) {
So(s.AccountViewVideo(context.TODO(), testAccountMid), ShouldBeNil)
}))
}

View File

@@ -0,0 +1,24 @@
package service
import (
"context"
)
var (
rageMap = map[int16]string{
1: "S",
2: "A",
3: "B",
4: "C",
}
)
// BlockedKPIInfo .
func (s *Service) BlockedKPIInfo(c context.Context, mid int64, rage int16) (err error) {
if len(rageMap[rage]) != 0 {
s.figureDao.BlockedRage(c, mid, rage)
} else {
s.figureDao.BlockedRage(c, mid, int16(0))
}
return
}

View File

@@ -0,0 +1,13 @@
package service
import (
"context"
coinm "go-common/app/service/main/coin/model"
)
// PutCoinInfo handle user coin chenage message
func (s *Service) PutCoinInfo(c context.Context, msg *coinm.DataBus) (err error) {
s.figureDao.PutCoinCount(c, msg.Mid)
return
}

View File

@@ -0,0 +1,22 @@
package service
import (
"context"
coinm "go-common/app/service/main/coin/model"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
var (
testCoinMid int64 = 130
)
// go test -test.v -test.run TestPutCoinInfo
func TestPutCoinInfo(t *testing.T) {
Convey("TestPutCoinInfo put coin info", t, WithService(func(s *Service) {
So(s.PutCoinInfo(context.TODO(), &coinm.DataBus{
Mid: testCoinMid,
}), ShouldBeNil)
}))
}

View File

@@ -0,0 +1,22 @@
package service
import (
"context"
"go-common/app/job/main/figure/model"
)
const (
_reportDel = "report_del"
)
// DanmakuReport .
func (s *Service) DanmakuReport(c context.Context, d *model.DMAction) (err error) {
if err = s.figureDao.DanmakuReport(c, d.Data.OwnerUID, model.ACColumnPublishDanmakuDeleted, -1); err != nil {
return
}
if err = s.figureDao.DanmakuReport(c, d.Data.ReportUID, model.ACColumnDanmakuReoprtPassed, 1); err != nil {
return
}
return
}

View File

@@ -0,0 +1,19 @@
package service
import (
"context"
"go-common/app/job/main/figure/model"
)
const (
_live = 11
)
// PayOrderInfo handle user coin chenage message
func (s *Service) PayOrderInfo(c context.Context, mid, money int64, merchant int8) (err error) {
column := model.ACColumnPayMoney
if merchant == _live {
column = model.ACColumnPayLiveMoney
}
return s.figureDao.PayOrderInfo(c, column, mid, money)
}

View File

@@ -0,0 +1,36 @@
package service
import (
"context"
"time"
"go-common/app/job/main/figure/model"
)
// PutReplyInfo handle user reply info chenage message
func (s *Service) PutReplyInfo(c context.Context, info *model.ReplyEvent) (err error) {
switch info.Action {
case model.EventAdd:
// only handle normal state reply
if info.Reply.State == 0 {
s.figureDao.PutReplyAct(c, info.Mid, model.ACColumnReplyAct, int64(1))
}
case model.EventLike:
s.figureDao.PutReplyAct(c, info.Reply.Mid, model.ACColumnReplyLiked, int64(1))
case model.EventLikeCancel:
s.figureDao.PutReplyAct(c, info.Reply.Mid, model.ACColumnReplyLiked, int64(-1))
case model.EventHate:
s.figureDao.PutReplyAct(c, info.Reply.Mid, model.ACColumnReplyHate, int64(1))
case model.EventHateCancel:
s.figureDao.PutReplyAct(c, info.Reply.Mid, model.ACColumnReplyHate, int64(-1))
case model.EventReportDel:
s.figureDao.PutReplyAct(c, info.Report.Mid, model.ACColumnReplyReoprtPassed, int64(1))
s.figureDao.PutReplyAct(c, info.Reply.Mid, model.ACColumnPublishReplyDeleted, int64(-1))
s.figureDao.SetWaiteUserCache(c, info.Report.Mid, s.figureDao.Version(time.Now()))
case model.EventReportRecover:
s.figureDao.PutReplyAct(c, info.Report.Mid, model.ACColumnReplyReoprtPassed, int64(-1))
s.figureDao.PutReplyAct(c, info.Reply.Mid, model.ACColumnPublishReplyDeleted, int64(1))
s.figureDao.SetWaiteUserCache(c, info.Report.Mid, s.figureDao.Version(time.Now()))
}
return
}

View File

@@ -0,0 +1,72 @@
package service
import (
"context"
"testing"
"go-common/app/job/main/figure/model"
repmol "go-common/app/job/main/reply/model/reply"
. "github.com/smartystreets/goconvey/convey"
)
var (
testReplyMid int64 = 120
testRefReplyMid int64 = 121
)
// go test -test.v -test.run TestPutReplyInfo
func TestPutReplyInfo(t *testing.T) {
Convey("TestPutReplyInfo put add reply", t, WithService(func(s *Service) {
So(s.PutReplyInfo(context.TODO(), &model.ReplyEvent{
Mid: testReplyMid,
Action: model.EventAdd,
Reply: &repmol.Reply{
Mid: testRefReplyMid,
},
}), ShouldBeNil)
}))
Convey("TestPutReplyInfo put add reply", t, WithService(func(s *Service) {
So(s.PutReplyInfo(context.TODO(), &model.ReplyEvent{
Mid: testReplyMid,
Action: model.EventLike,
Reply: &repmol.Reply{
Mid: testRefReplyMid,
},
}), ShouldBeNil)
So(s.PutReplyInfo(context.TODO(), &model.ReplyEvent{
Mid: testReplyMid,
Action: model.EventLike,
Reply: &repmol.Reply{
Mid: testRefReplyMid,
},
}), ShouldBeNil)
}))
Convey("TestPutReplyInfo put add reply", t, WithService(func(s *Service) {
So(s.PutReplyInfo(context.TODO(), &model.ReplyEvent{
Mid: testReplyMid,
Action: model.EventLikeCancel,
Reply: &repmol.Reply{
Mid: testRefReplyMid,
},
}), ShouldBeNil)
}))
Convey("TestPutReplyInfo put hate", t, WithService(func(s *Service) {
So(s.PutReplyInfo(context.TODO(), &model.ReplyEvent{
Mid: testReplyMid,
Action: model.EventHate,
Reply: &repmol.Reply{
Mid: testRefReplyMid,
},
}), ShouldBeNil)
}))
Convey("TestPutReplyInfo put hate cancel", t, WithService(func(s *Service) {
So(s.PutReplyInfo(context.TODO(), &model.ReplyEvent{
Mid: testReplyMid,
Action: model.EventHateCancel,
Reply: &repmol.Reply{
Mid: testRefReplyMid,
},
}), ShouldBeNil)
}))
}

View File

@@ -0,0 +1,533 @@
package service
import (
"context"
"encoding/json"
"io/ioutil"
"os"
"runtime/debug"
"strings"
"time"
"go-common/app/job/main/figure/conf"
"go-common/app/job/main/figure/dao"
"go-common/app/job/main/figure/model"
coinm "go-common/app/service/main/coin/model"
spym "go-common/app/service/main/spy/model"
"go-common/library/log"
"go-common/library/queue/databus"
)
const (
_insertAction = "insert"
_vipTable = "vip_user_info"
_payTable = "pay_pay_order"
_blockedTable = "blocked_kpi"
// pay success status.
_paySuccess = 2
)
// Service biz service def.
type Service struct {
c *conf.Config
figureDao *dao.Dao
accExpDatabus *databus.Databus
accRegDatabus *databus.Databus
vipDatabus *databus.Databus
spyDatabus *databus.Databus
coinDatabus *databus.Databus
replyInfoDatabus *databus.Databus
payDatabus *databus.Databus
danmakuDatabus *databus.Databus
blockedDatabus *databus.Databus
}
// New new a Service and return.
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
figureDao: dao.New(c),
}
if c.DataSource.AccountExp != nil {
s.accExpDatabus = databus.New(c.DataSource.AccountExp)
go s.accexpproc()
}
if c.DataSource.AccountReg != nil {
s.accRegDatabus = databus.New(c.DataSource.AccountReg)
go s.accregproc()
}
if c.DataSource.Vip != nil {
s.vipDatabus = databus.New(c.DataSource.Vip)
go s.vipproc()
}
if c.DataSource.Spy != nil {
s.spyDatabus = databus.New(c.DataSource.Spy)
go s.spyproc()
}
if c.DataSource.Coin != nil {
s.coinDatabus = databus.New(c.DataSource.Coin)
go s.coinproc()
}
if c.DataSource.ReplyInfo != nil {
s.replyInfoDatabus = databus.New(c.DataSource.ReplyInfo)
go s.replyinfoproc()
}
if c.DataSource.Pay != nil {
s.payDatabus = databus.New(c.DataSource.Pay)
go s.payproc()
}
if c.DataSource.Danmaku != nil {
s.danmakuDatabus = databus.New(c.DataSource.Danmaku)
go s.danmakuproc()
}
if c.DataSource.Blocked != nil {
s.blockedDatabus = databus.New(c.DataSource.Blocked)
go s.blockedproc()
}
go s.syncproc()
return s
}
// Ping check dao health.
func (s *Service) Ping(c context.Context) (err error) {
s.figureDao.Ping(c)
return
}
// Close close all dao.
func (s *Service) Close() {
s.figureDao.Close()
}
func (s *Service) accexpproc() {
defer func() {
if x := recover(); x != nil {
log.Error("s.accexpproc panic(%v) %s", x, debug.Stack())
go s.accexpproc()
log.Info("s.accexpproc recover")
}
}()
var (
err error
msg *databus.Message
msgChan = s.accExpDatabus.Messages()
ok bool
exp *model.MsgAccountLog
)
for {
select {
case msg, ok = <-msgChan:
if !ok {
log.Info("accproc msgChan closed")
}
}
if err = msg.Commit(); err != nil {
log.Error("msg.Commit err(%v)", err)
}
exp = &model.MsgAccountLog{}
if err = json.Unmarshal([]byte(msg.Value), exp); err != nil {
log.Error("json.Unmarshal(%v) err(%v)", msg, err)
continue
}
log.Info("exp Info (%+v)", exp)
if err = s.AccountExp(context.Background(), exp.Mid, int64(exp.ExpTo())); err != nil {
log.Error("s.AccountExp(%v) err(%v)", exp, err)
continue
}
s.figureDao.SetWaiteUserCache(context.Background(), exp.Mid, s.figureDao.Version(time.Now()))
if exp.IsViewExp() {
if err = s.AccountViewVideo(context.Background(), exp.Mid); err != nil {
log.Error("s.AccountExp(%v) err(%v)", exp, err)
continue
}
}
}
}
func (s *Service) accregproc() {
defer func() {
if x := recover(); x != nil {
log.Error("s.accregproc panic(%v) %s", x, debug.Stack())
go s.accregproc()
log.Info("s.accregproc recover")
}
}()
var (
err error
msg *databus.Message
msgChan = s.accRegDatabus.Messages()
ok bool
)
for {
select {
case msg, ok = <-msgChan:
if !ok {
log.Info("accproc msgChan closed")
}
}
if err = msg.Commit(); err != nil {
log.Error("msg.Commit err(%v)", err)
}
reg := &model.MsgCanal{}
if err = json.Unmarshal([]byte(msg.Value), reg); err != nil {
log.Error("json.Unmarshal(%v) err(%v)", msg, err)
continue
}
log.Info("reg log %+v", reg)
if reg.Action == _insertAction {
var info struct {
Mid int64 `json:"mid"`
}
if err = json.Unmarshal(reg.New, &info); err != nil {
log.Error("json.Unmarshal(%s) error(%v)", string(reg.New), err)
return
}
if err = s.AccountReg(context.Background(), info.Mid); err != nil {
log.Error("s.AccountReg(%v) err(%v)", reg, err)
continue
}
s.figureDao.SetWaiteUserCache(context.Background(), info.Mid, s.figureDao.Version(time.Now()))
}
}
}
func (s *Service) vipproc() {
defer func() {
if x := recover(); x != nil {
log.Error("s.vipproc panic(%v) %s", x, debug.Stack())
go s.vipproc()
log.Info("s.vipproc recover")
}
}()
var (
err error
msg *databus.Message
msgChan = s.vipDatabus.Messages()
ok bool
)
for {
select {
case msg, ok = <-msgChan:
if !ok {
log.Info("vipproc msgChan closed")
}
}
if err = msg.Commit(); err != nil {
log.Error("msg.Commit err(%v)", err)
}
v := &model.MsgCanal{}
if err = json.Unmarshal([]byte(msg.Value), v); err != nil {
log.Error("json.Unmarshal(%v) err(%v)", v, err)
continue
}
log.Info("vip log %+v", v)
if v.Table == _vipTable {
var vipInfo struct {
Mid int64 `json:"mid"`
VipStatus int32 `json:"vip_status"`
}
if err = json.Unmarshal(v.New, &vipInfo); err != nil {
log.Error("json.Unmarshal(%v) err(%v)", v.New, err)
continue
}
if err = s.UpdateVipStatus(context.Background(), vipInfo.Mid, vipInfo.VipStatus); err != nil {
log.Error("s.UpdateVipStatus(%v) err(%v)", v, err)
continue
}
s.figureDao.SetWaiteUserCache(context.Background(), vipInfo.Mid, s.figureDao.Version(time.Now()))
}
}
}
func (s *Service) spyproc() {
defer func() {
if x := recover(); x != nil {
log.Error("s.spyproc panic(%v) %s", x, debug.Stack())
go s.spyproc()
log.Info("s.spyproc recover")
}
}()
var (
err error
msg *databus.Message
msgChan = s.spyDatabus.Messages()
ok bool
)
for {
select {
case msg, ok = <-msgChan:
if !ok {
log.Info("spyproc msgChan closed")
}
}
if err = msg.Commit(); err != nil {
log.Error("msg.Commit err(%v)", err)
}
sc := &spym.ScoreChange{}
if err = json.Unmarshal([]byte(msg.Value), sc); err != nil {
log.Error("json.Unmarshal(%v) err(%v)", sc, err)
continue
}
log.Info("spy log %+v", sc)
if err = s.PutSpyScore(context.Background(), sc); err != nil {
log.Error("s.PutSpyScore(%v) err(%v)", sc, err)
continue
}
s.figureDao.SetWaiteUserCache(context.Background(), sc.Mid, s.figureDao.Version(time.Now()))
}
}
func (s *Service) coinproc() {
defer func() {
if x := recover(); x != nil {
log.Error("s.coinproc panic(%v) %s", x, debug.Stack())
go s.coinproc()
log.Info("s.coinproc recover")
}
}()
var (
err error
msg *databus.Message
msgChan = s.coinDatabus.Messages()
ok bool
)
for {
select {
case msg, ok = <-msgChan:
if !ok {
log.Info("coinproc msgChan closed")
}
}
if err = msg.Commit(); err != nil {
log.Error("msg.Commit err(%v)", err)
}
cd := &coinm.DataBus{}
if err = json.Unmarshal([]byte(msg.Value), cd); err != nil {
log.Error("json.Unmarshal(%v) err(%v)", cd, err)
continue
}
log.Info("coin log %+v", cd)
if err = s.PutCoinInfo(context.Background(), cd); err != nil {
log.Error("s.PutCoinInfo(%v) err(%v)", cd, err)
continue
}
s.figureDao.SetWaiteUserCache(context.Background(), cd.Mid, s.figureDao.Version(time.Now()))
}
}
func (s *Service) replyinfoproc() {
defer func() {
if x := recover(); x != nil {
log.Error("s.replyinfoproc panic(%v) %s", x, debug.Stack())
go s.replyinfoproc()
log.Info("s.replyinfoproc recover")
}
}()
var (
err error
msg *databus.Message
msgChan = s.replyInfoDatabus.Messages()
ok bool
)
for {
select {
case msg, ok = <-msgChan:
if !ok {
log.Info("replyinfoproc msgChan closed")
}
}
if err = msg.Commit(); err != nil {
log.Error("msg.Commit err(%v)", err)
}
m := &model.ReplyEvent{}
if err = json.Unmarshal([]byte(msg.Value), m); err != nil {
log.Error("json.Unmarshal(%v) err(%v)", m, err)
continue
}
log.Info("reply log %+v", m)
if err = s.PutReplyInfo(context.Background(), m); err != nil {
log.Error("s.PutCoinInfo(%v) err(%v)", m, err)
continue
}
if m.Action == model.EventAdd {
s.figureDao.SetWaiteUserCache(context.Background(), m.Mid, s.figureDao.Version(time.Now()))
} else {
s.figureDao.SetWaiteUserCache(context.Background(), m.Reply.Mid, s.figureDao.Version(time.Now()))
}
}
}
func (s *Service) syncproc() {
defer func() {
if x := recover(); x != nil {
log.Error("s.syncproc panic(%v) %s", x, debug.Stack())
go s.syncproc()
log.Info("s.syncproc recover")
}
}()
if s.c.Figure.Sync {
log.Info("start import data after half hour.")
time.Sleep(5 * time.Minute)
log.Info("start import data.")
var (
vipPath = s.c.Figure.VipPath
files []os.FileInfo
err error
)
if files, err = ioutil.ReadDir(vipPath); err != nil {
log.Error("ioutile.ReadDir(%s) err [%s]", vipPath, err)
}
for _, f := range files {
s.SyncUserVIP(context.TODO(), vipPath+"/"+f.Name())
}
log.Info("end import data.")
}
}
func (s *Service) payproc() {
defer func() {
if x := recover(); x != nil {
log.Error("s.payproc panic(%v) %s", x, debug.Stack())
go s.payproc()
log.Info("s.payproc recover")
}
}()
var (
err error
msg *databus.Message
msgChan = s.payDatabus.Messages()
ok bool
)
for {
select {
case msg, ok = <-msgChan:
if !ok {
log.Info("payproc msgChan closed")
}
}
if err = msg.Commit(); err != nil {
log.Error("msg.Commit err(%v)", err)
}
v := &model.MsgCanal{}
if err = json.Unmarshal([]byte(msg.Value), v); err != nil {
log.Error("json.Unmarshal(%v) err(%v)", v, err)
continue
}
log.Info("pay log %+v", v)
if strings.HasPrefix(v.Table, _payTable) {
var payOrder struct {
Mid int64 `json:"pay_mid"`
Money float64 `json:"bp"`
MerchantID int8 `json:"merchant_id"`
Status int32 `json:"status"`
}
if err = json.Unmarshal(v.New, &payOrder); err != nil {
log.Error("json.Unmarshal(%v) err(%v)", v.New, err)
continue
}
if payOrder.Status != _paySuccess {
continue
}
// update YUAN to Fen
money := int64(payOrder.Money * 100)
if err = s.PayOrderInfo(context.Background(), payOrder.Mid, money, payOrder.MerchantID); err != nil {
log.Error("s.PayOrderInfo(%v) err(%v)", payOrder, err)
continue
}
s.figureDao.SetWaiteUserCache(context.Background(), payOrder.Mid, s.figureDao.Version(time.Now()))
}
}
}
// 风纪委相关
func (s *Service) blockedproc() {
defer func() {
if x := recover(); x != nil {
log.Error("s.blockedproc panic(%v) %s", x, debug.Stack())
go s.blockedproc()
log.Info("s.blockedproc recover")
}
}()
var (
err error
msg *databus.Message
msgChan = s.blockedDatabus.Messages()
ok bool
)
for {
select {
case msg, ok = <-msgChan:
if !ok {
log.Info("blockedproc msgChan closed")
}
}
if err = msg.Commit(); err != nil {
log.Error("msg.Commit err(%v)", err)
}
v := &model.MsgCanal{}
if err = json.Unmarshal([]byte(msg.Value), v); err != nil {
log.Error("json.Unmarshal(%v) err(%v)", v, err)
continue
}
log.Info("blocked log %+v", v)
if v.Table == _blockedTable {
var KPIInfo struct {
Mid int64 `json:"mid"`
Rate int16 `json:"rate"`
}
if err = json.Unmarshal(v.New, &KPIInfo); err != nil {
log.Error("json.Unmarshal(%v) err(%v)", v.New, err)
continue
}
if err = s.BlockedKPIInfo(context.Background(), KPIInfo.Mid, KPIInfo.Rate); err != nil {
log.Error("s.BlockedKPIInfo(%v) err(%v)", KPIInfo, err)
continue
}
s.figureDao.SetWaiteUserCache(context.Background(), KPIInfo.Mid, s.figureDao.Version(time.Now()))
}
}
}
func (s *Service) danmakuproc() {
defer func() {
if x := recover(); x != nil {
log.Error("s.danmakuproc panic(%v) %s", x, debug.Stack())
go s.danmakuproc()
log.Info("s.danmakuproc recover")
}
}()
var (
err error
msg *databus.Message
msgChan = s.danmakuDatabus.Messages()
ok bool
)
for {
select {
case msg, ok = <-msgChan:
if !ok {
log.Info("danmakuproc msgChan closed")
}
}
if err = msg.Commit(); err != nil {
log.Error("msg.Commit err(%+v)", err)
}
m := &model.DMAction{}
if err = json.Unmarshal([]byte(msg.Value), m); err != nil {
log.Error("json.Unmarshal(%v) err(%+v)", m, err)
continue
}
log.Info("danmaku msg %+v", m)
if m.Action == _reportDel {
if err = s.DanmakuReport(context.Background(), m); err != nil {
log.Error("s.DanmakuReport(%v) err(%+v)", m, err)
continue
}
s.figureDao.SetWaiteUserCache(context.Background(), m.Data.OwnerUID, s.figureDao.Version(time.Now()))
s.figureDao.SetWaiteUserCache(context.Background(), m.Data.ReportUID, s.figureDao.Version(time.Now()))
}
}
}

View File

@@ -0,0 +1,58 @@
package service
import (
"flag"
"go-common/app/job/main/figure/conf"
"go-common/library/log"
"path/filepath"
"sync"
"time"
. "github.com/smartystreets/goconvey/convey"
)
var (
once sync.Once
s *Service
)
func initConf() {
if err := conf.Init(); err != nil {
panic(err)
}
log.Init(conf.Conf.Log)
defer log.Close()
}
func init() {
var (
err error
)
dir, _ := filepath.Abs("../cmd/figure-job-test.toml")
flag.Set("conf", dir)
if err = conf.Init(); err != nil {
panic(err)
}
if s == nil {
s = New(conf.Conf)
}
time.Sleep(time.Second)
}
func startService() {
initConf()
if s == nil {
s = New(conf.Conf)
}
time.Sleep(time.Second * 2)
}
func CleanCache() {
}
func WithService(f func(s *Service)) func() {
return func() {
Reset(func() { CleanCache() })
f(s)
}
}

View File

@@ -0,0 +1,21 @@
package service
import (
"context"
"go-common/app/job/main/figure/model"
spym "go-common/app/service/main/spy/model"
)
// PutSpyScore handle user spy score chenage message
func (s *Service) PutSpyScore(c context.Context, sc *spym.ScoreChange) (err error) {
s.figureDao.PutSpyScore(c, sc.Mid, sc.Score)
if sc.Reason == spym.CoinReason {
if sc.RiskLevel == spym.CoinHighRisk {
s.figureDao.PutCoinUnusual(c, sc.Mid, model.ACColumnHighRisk)
} else {
s.figureDao.PutCoinUnusual(c, sc.Mid, model.ACColumnLowRisk)
}
}
return
}

View File

@@ -0,0 +1,50 @@
package service
import (
"context"
"time"
spym "go-common/app/service/main/spy/model"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
var (
testSpyMid int64 = 111
)
// go test -test.v -test.run TestPutSpyScore
func TestPutSpyScore(t *testing.T) {
Convey("Test_PutSpyScore put no reason msg", t, WithService(func(s *Service) {
So(s.PutSpyScore(context.TODO(), &spym.ScoreChange{
Mid: testSpyMid,
Score: 80,
EventScore: 80,
BaseScore: 80,
TS: time.Now().Unix(),
}), ShouldBeNil)
}))
Convey("Test_PutSpyScore put coin-service reason msg", t, WithService(func(s *Service) {
So(s.PutSpyScore(context.TODO(), &spym.ScoreChange{
Mid: testSpyMid,
Score: 70,
EventScore: 80,
BaseScore: 80,
TS: time.Now().Unix(),
Reason: "coin-service",
RiskLevel: 3,
}), ShouldBeNil)
}))
Convey("Test_PutSpyScore put coin-service high risk reason msg", t, WithService(func(s *Service) {
So(s.PutSpyScore(context.TODO(), &spym.ScoreChange{
Mid: testSpyMid,
Score: 8,
EventScore: 80,
BaseScore: 80,
TS: time.Now().Unix(),
Reason: "coin-service",
RiskLevel: 7,
}), ShouldBeNil)
}))
}

View File

@@ -0,0 +1,50 @@
package service
import (
"bufio"
"context"
"io"
"os"
"strconv"
"strings"
"time"
"go-common/library/log"
)
func (s *Service) SyncUserVIP(ctx context.Context, file string) {
log.Info("Start sync user VIP")
f, err := os.OpenFile(file, os.O_RDONLY, os.ModePerm)
if err != nil {
log.Error("os.OpenFile(%s) , err [%s]", file, err)
return
}
br := bufio.NewReader(f)
var (
str string
mid int64
count int
)
for {
if str, err = br.ReadString('\n'); err != nil {
if err == io.EOF {
break
}
log.Error("br.ReadString error [%s]", err)
return
}
if mid, err = strconv.ParseInt(strings.TrimSpace(str), 10, 64); err != nil {
log.Error("Parse midstr [%s] error [%s]", str, err)
continue
}
if err = s.figureDao.UpdateVipStatus(ctx, mid, 1); err != nil {
log.Error("s.figureDao.UpdateVipStatus(%d,1) err [%s]", mid, err)
return
}
count++
if count%10000 == 0 {
time.Sleep(time.Second)
}
}
log.Info("End sync user VIP count [%d]", count)
}

View File

@@ -0,0 +1,11 @@
package service
import (
"context"
)
// UpdateVipStatus handle user vip staus change
func (s *Service) UpdateVipStatus(c context.Context, mid int64, vs int32) (err error) {
s.figureDao.UpdateVipStatus(c, mid, vs)
return
}

View File

@@ -0,0 +1,20 @@
package service
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
var (
testVipStatus int32 = 2
testVipMid int64 = 110
)
//go test -test.v -test.run TestUpdateVipStatus
func TestUpdateVipStatus(t *testing.T) {
Convey("TestUpdateVipStatus update vip status", t, WithService(func(s *Service) {
So(s.UpdateVipStatus(context.TODO(), testVipMid, testVipStatus), ShouldBeNil)
}))
}