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

View File

@@ -0,0 +1,27 @@
# v1.1.0
1. 审核日志上报
# v1.0.7
1. 优化account notify
# v1.0.6
1. remove sync old
# v1.0.5
1. fix account notify model
# v1.0.4
1. 同步新增业务类型
# v1.0.3
1. 用户答题后及时检查是否解封
# v1.0.2
1. 加入AccountNotify清理缓存
# v1.0.1
1. 适配小黑屋封禁
2. 同步老库数据并且订阅老库member_block_type
# v1.0.0
1. 项目初始化

View File

@@ -0,0 +1,10 @@
# Owner
zhaogangtao
wanghuan01
zhoujiahui
# Author
muyang
# Reviewer
zhaogangtao

16
app/job/main/block/OWNERS Normal file
View File

@@ -0,0 +1,16 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- muyang
- wanghuan01
- zhaogangtao
- zhoujiahui
labels:
- job
- job/main/block
- main
options:
no_parent_owners: true
reviewers:
- muyang
- zhaogangtao

View File

@@ -0,0 +1,12 @@
# block-job
# 项目简介
封禁job服务
# 编译环境
golang > 1.8
# 依赖包
go-common
# 编译执行

View File

@@ -0,0 +1,41 @@
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 = ["block-job-test.toml"],
importpath = "go-common/app/job/main/block/cmd",
tags = ["automanaged"],
deps = [
"//app/job/main/block/conf:go_default_library",
"//app/job/main/block/http:go_default_library",
"//library/log:go_default_library",
"//library/queue/databus/report: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,117 @@
[log]
dir = "/data/log/block-job"
[db]
addr = "127.0.0.1:3306"
dsn = "root:54985498@tcp(127.0.0.1:3306)/bilibili_block?timeout=200ms&readTimeout=200ms&writeTimeout=200ms&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 20
idle = 10
idleTimeout ="4h"
queryTimeout = "1s"
execTimeout = "1s"
tranTimeout = "2s"
[db.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[memcache]
name = "block"
proto = "tcp"
addr = ""
idle = 5
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "24h"
[bm]
addr = "0.0.0.0:7551"
maxListen = 10
timeout = "1s"
[httpClient]
key = "33ac033ce123e999"
secret = "0b2847315d32989a248294e350ac3ede"
dial = "1s"
timeout = "5s"
keepAlive = "60s"
[httpClient.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[databus]
[databus.credit]
key = "***"
secret= "***"
group= "Credit-MainAccountLaw-S"
topic= "Credit-T"
action="sub"
name = "block-job/databus"
proto = "tcp"
addr = "127.0.0.1:6205"
idle = 2
active = 10
dialTimeout = "1s"
readTimeout = "60s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "1h"
[accountNotify]
key = "4ba46ba31f9a44ef"
secret = "99985eb4451cfb1b899ca0fbe3c4bdc8"
group = "AccountNotify-MainAccount-P"
topic = "AccountNotify-T"
action = "pub"
buffer = 128
name = "usersuit-admin/databus"
proto = "tcp"
addr = "172.16.33.158:6205"
active = 1
idle = 1
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
[property]
limitExpireCheckLimit = 100
limitExpireCheckTick = "5m"
creditExpireCheckLimit = 100
creditExpireCheckTick = "5m"
msgURL = "http://message.bilibili.co/api/notify/send.user.notify.do"
[property.flag]
expireCheck = true # 自动解禁检查
creditSub = true # 小黑屋答题状态订阅
[property.msg]
[property.msg.blockRemove]
code = "2_3_6"
title = "账号封禁解除通知"
content = "你的账号已经解除封禁,封禁期间禁止使用的各项社区功能已经恢复。请遵守社区规范,共同维护良好的社区氛围。"
[managerLog]
Key = "2511663d546f1413"
Secret = "cde3b480836cc76df3d635470f991caa"
Group = "LogAudit-MainSearch-P"
Topic = "LogAudit-T"
Action = "pub"
Buffer = 10240
Name = "log-audit/log-sub"
Proto = "tcp"
Addr = "172.18.33.50:6205"
Active = 10
Idle = 5
DialTimeout = "200ms"
ReadTimeout = "200ms"
WriteTimeout = "200ms"
IdleTimeout = "80s"

View File

@@ -0,0 +1,46 @@
package main
import (
"flag"
"os"
"os/signal"
"syscall"
"go-common/app/job/main/block/conf"
"go-common/app/job/main/block/http"
"go-common/library/log"
manager "go-common/library/queue/databus/report"
)
func main() {
flag.Parse()
if err := conf.Init(); err != nil {
log.Error("conf.Init() err(%+v)", err)
panic(err)
}
log.Init(conf.Conf.Log)
defer log.Close()
http.Init()
// manager log init
manager.InitManager(conf.Conf.ManagerLog)
log.Info("block-job start")
signalHandler()
}
func signalHandler() {
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
s := <-c
log.Info("block get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
log.Info("block-job exit")
return
case syscall.SIGHUP:
default:
return
}
}
}

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"],
deps = ["//vendor/github.com/smartystreets/goconvey/convey:go_default_library"],
)
go_library(
name = "go_default_library",
srcs = ["conf.go"],
importpath = "go-common/app/job/main/block/conf",
tags = ["automanaged"],
deps = [
"//app/job/main/block/model:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/conf:go_default_library",
"//library/database/sql:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/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,115 @@
package conf
import (
"errors"
"flag"
"go-common/app/job/main/block/model"
"go-common/library/cache/memcache"
"go-common/library/conf"
"go-common/library/database/sql"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/queue/databus"
xtime "go-common/library/time"
"github.com/BurntSushi/toml"
)
// global var
var (
confPath string
client *conf.Client
// Conf config
Conf = &Config{}
)
// Config config set
type Config struct {
Log *log.Config
Memcache *memcache.Config
DB *sql.Config
BM *bm.ServerConfig
HTTPClient *bm.ClientConfig
Databus *Databus
AccountNotify *databus.Config
Property *Property
// manager log config
ManagerLog *databus.Config
}
// Databus .
type Databus struct {
Credit *databus.Config
}
// Property .
type Property struct {
LimitExpireCheckLimit int
LimitExpireCheckTick xtime.Duration
CreditExpireCheckLimit int
CreditExpireCheckTick xtime.Duration
MSGURL string
MSG *MSG
Flag *struct {
ExpireCheck bool
CreditSub bool
}
}
// MSG .
type MSG struct {
BlockRemove model.MSG
}
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
}

View File

@@ -0,0 +1,28 @@
package conf
import (
"flag"
"os"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestMain(m *testing.M) {
defer os.Exit(0)
flag.Set("conf", "../cmd/block-job-test.toml")
var err error
if err = Init(); err != nil {
panic(err)
}
m.Run()
}
func TestConf(t *testing.T) {
Convey("conf", t, func() {
So(Conf.Property.MSG, ShouldNotBeNil)
So(Conf.Property.MSG.BlockRemove, ShouldNotBeNil)
t.Log(Conf.Property.MSG)
})
}

View File

@@ -0,0 +1,55 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["dao_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/block/conf:go_default_library",
"//app/job/main/block/model:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"http.go",
"mc.go",
"mysql.go",
],
importpath = "go-common/app/job/main/block/dao",
tags = ["automanaged"],
deps = [
"//app/job/main/block/conf:go_default_library",
"//app/job/main/block/model:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/database/sql:go_default_library",
"//library/ecode:go_default_library",
"//library/net/http/blademaster: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,60 @@
package dao
import (
"context"
"go-common/app/job/main/block/conf"
"go-common/library/cache/memcache"
xsql "go-common/library/database/sql"
bm "go-common/library/net/http/blademaster"
"github.com/pkg/errors"
)
// Dao dao
type Dao struct {
mc *memcache.Pool
db *xsql.DB
httpClient *bm.Client
}
// New init mysql db
func New() (dao *Dao) {
dao = &Dao{
mc: memcache.NewPool(conf.Conf.Memcache),
db: xsql.NewMySQL(conf.Conf.DB),
httpClient: bm.NewClient(conf.Conf.HTTPClient),
}
return
}
// Close close the resource.
func (d *Dao) Close() {
d.mc.Close()
d.db.Close()
}
// Ping dao ping
func (d *Dao) Ping(c context.Context) (err error) {
if err = d.db.Ping(c); err != nil {
return
}
if err = d.pingMC(c); err != nil {
return
}
return
}
// pingMc ping
func (d *Dao) pingMC(c context.Context) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
return
}
func (d *Dao) BeginTX(c context.Context) (tx *xsql.Tx, err error) {
if tx, err = d.db.Begin(c); err != nil {
err = errors.WithStack(err)
}
return
}

View File

@@ -0,0 +1,68 @@
package dao
import (
"context"
"flag"
"testing"
"go-common/app/job/main/block/conf"
"go-common/app/job/main/block/model"
. "github.com/smartystreets/goconvey/convey"
)
var (
dao *Dao
ctx = context.TODO()
)
func TestMain(m *testing.M) {
flag.Set("conf", "../cmd/block-service-test.toml")
var err error
if err = conf.Init(); err != nil {
panic(err)
}
dao = New()
defer dao.Close()
m.Run()
}
func TestDB(t *testing.T) {
Convey("db", t, func() {
tx, err := dao.BeginTX(ctx)
So(err, ShouldBeNil)
var (
mid int64 = 46333
)
err = dao.UpsertAddBlockCount(ctx, mid)
So(err, ShouldBeNil)
err = dao.TxUpsertUser(ctx, tx, mid, model.BlockStatusFalse)
So(err, ShouldBeNil)
var (
history = &model.DBHistory{
MID: mid,
Source: model.BlockSourceRemove,
Comment: "ut test",
Action: model.BlockActionAdminRemove,
}
)
err = dao.TxInsertHistory(ctx, tx, history)
So(err, ShouldBeNil)
err = tx.Rollback()
So(err, ShouldBeNil)
})
}
func TestTool(t *testing.T) {
Convey("tool", t, func() {
var (
mids = []int64{1, 2, 3, 46333, 35858}
)
str := midsToParam(mids)
So(str, ShouldEqual, "1,2,3,46333,35858")
})
}

View File

@@ -0,0 +1,47 @@
package dao
import (
"context"
"fmt"
"net/url"
"strings"
"go-common/app/job/main/block/conf"
"go-common/library/ecode"
"github.com/pkg/errors"
)
// SendSysMsg send sys msg.
func (d *Dao) SendSysMsg(c context.Context, code string, mids []int64, title string, content string, remoteIP string) (err error) {
params := url.Values{}
params.Set("mc", code)
params.Set("title", title)
params.Set("data_type", "4")
params.Set("context", content)
params.Set("mid_list", midsToParam(mids))
var res struct {
Code int `json:"code"`
Data *struct {
Status int8 `json:"status"`
Remark string `json:"remark"`
} `json:"data"`
}
if err = d.httpClient.Post(c, conf.Conf.Property.MSGURL, remoteIP, params, &res); err != nil {
err = errors.WithStack(err)
return
}
if res.Code != 0 {
err = errors.WithStack(ecode.Int(res.Code))
return
}
return
}
func midsToParam(mids []int64) (str string) {
strs := make([]string, 0, len(mids))
for _, mid := range mids {
strs = append(strs, fmt.Sprintf("%d", mid))
}
return strings.Join(strs, ",")
}

View File

@@ -0,0 +1,67 @@
package dao
import (
"context"
"fmt"
"go-common/library/cache/memcache"
"github.com/pkg/errors"
)
func userKey(mid int64) (key string) {
key = fmt.Sprintf("u_%d", mid)
return
}
func syncBlockTypeID() (key string) {
return "sync_bt_cur_id"
}
func (d *Dao) SetSyncBlockTypeID(c context.Context, id int64) (err error) {
var (
key = syncBlockTypeID()
conn = d.mc.Get(c)
)
defer conn.Close()
if err = conn.Set(&memcache.Item{Key: key, Object: id, Expiration: 3600 * 24, Flags: memcache.FlagJSON}); err != nil {
err = errors.WithStack(err)
return
}
return
}
func (d *Dao) SyncBlockTypeID(c context.Context) (id int64, err error) {
var (
key = syncBlockTypeID()
conn = d.mc.Get(c)
item *memcache.Item
)
defer conn.Close()
if item, err = conn.Get(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
err = errors.WithStack(err)
return
}
if err = conn.Scan(item, &id); err != nil {
err = errors.WithStack(err)
return
}
return
}
func (d *Dao) DeleteUserCache(c context.Context, mid int64) (err error) {
var (
key = userKey(mid)
conn = d.mc.Get(c)
)
defer conn.Close()
if err = conn.Delete(key); err != nil {
err = errors.WithStack(err)
return
}
return
}

View File

@@ -0,0 +1,134 @@
package dao
import (
"context"
"fmt"
"go-common/app/job/main/block/model"
xsql "go-common/library/database/sql"
"github.com/pkg/errors"
)
const (
_upsertUser = `INSERT INTO block_user (mid,status) VALUES (?,?) ON DUPLICATE KEY UPDATE status=?`
_userStatusList = `SELECT id,mid FROM block_user WHERE status=? AND id>? LIMIT ?`
_userExtra = `SELECT id,mid,credit_answer_flag,action_time FROM block_extra WHERE mid=? ORDER BY id DESC LIMIT 1`
_userLastHistory = `SELECT id,mid,source,area,action,start_time,duration FROM block_history_%d WHERE mid=? ORDER BY id DESC LIMIT 1`
_upsertAddBlockCount = `INSERT INTO block_user_detail (mid,block_count) VALUES (?,1) ON DUPLICATE KEY UPDATE block_count=block_count+1`
_upsertExtra = `INSERT INTO block_extra (mid,credit_answer_flag,action_time) VALUES (?,?,?) ON DUPLICATE KEY UPDATE credit_answer_flag=? , action_time=?`
_insertHistory = `INSERT INTO block_history_%d (mid,admin_id,admin_name,source,area,reason,comment,action,start_time,duration,notify) VALUES (?,?,?,?,?,?,?,?,?,?,?)`
)
func historyIdx(mid int64) int64 {
return mid % 10
}
func (d *Dao) UserStatusList(c context.Context, status model.BlockStatus, startID int64, limit int) (maxID int64, mids []int64, err error) {
var (
rows *xsql.Rows
)
if rows, err = d.db.Query(c, _userStatusList, status, startID, limit); err != nil {
err = errors.WithStack(err)
return
}
defer rows.Close()
for rows.Next() {
var (
id, mid int64
)
if err = rows.Scan(&id, &mid); err != nil {
err = errors.WithStack(err)
return
}
if maxID < id {
maxID = id
}
mids = append(mids, mid)
}
if err = rows.Err(); err != nil {
err = errors.WithStack(err)
return
}
return
}
func (d *Dao) UserLastHistory(c context.Context, mid int64) (his *model.DBHistory, err error) {
var (
sql = fmt.Sprintf(_userLastHistory, historyIdx(mid))
)
row := d.db.QueryRow(c, sql, mid)
his = &model.DBHistory{}
if err = row.Scan(&his.ID, &his.MID, &his.Source, &his.Area, &his.Action, &his.StartTime, &his.Duration); err != nil {
if err == xsql.ErrNoRows {
err = nil
his = nil
return
}
err = errors.WithStack(err)
return
}
return
}
func (d *Dao) UserExtra(c context.Context, mid int64) (ex *model.DBExtra, err error) {
row := d.db.QueryRow(c, _userExtra, mid)
ex = &model.DBExtra{}
if err = row.Scan(&ex.ID, &ex.MID, &ex.CreditAnswerFlag, &ex.ActionTime); err != nil {
if err == xsql.ErrNoRows {
err = nil
ex = nil
return
}
err = errors.WithStack(err)
return
}
return
}
func (d *Dao) TxUpsertUser(c context.Context, tx *xsql.Tx, mid int64, status model.BlockStatus) (err error) {
if _, err = tx.Exec(_upsertUser, mid, status, status); err != nil {
err = errors.WithStack(err)
return
}
return
}
func (d *Dao) InsertExtra(c context.Context, ex *model.DBExtra) (err error) {
if _, err = d.db.Exec(c, _upsertExtra, ex.MID, ex.CreditAnswerFlag, ex.ActionTime, ex.CreditAnswerFlag, ex.ActionTime); err != nil {
err = errors.WithStack(err)
return
}
return
}
func (d *Dao) TxUpsertExtra(c context.Context, tx *xsql.Tx, ex *model.DBExtra) (err error) {
if _, err = tx.Exec(_upsertExtra, ex.MID, ex.CreditAnswerFlag, ex.ActionTime, ex.CreditAnswerFlag, ex.ActionTime); err != nil {
err = errors.WithStack(err)
return
}
return
}
func (d *Dao) TxInsertHistory(c context.Context, tx *xsql.Tx, h *model.DBHistory) (err error) {
var (
sql = fmt.Sprintf(_insertHistory, historyIdx(h.MID))
)
if _, err = tx.Exec(sql, h.MID, h.AdminID, h.AdminName, h.Source, h.Area, h.Reason, h.Comment, h.Action, h.StartTime, h.Duration, h.Notify); err != nil {
err = errors.WithStack(err)
return
}
return
}
func (d *Dao) UpsertAddBlockCount(c context.Context, mid int64) (err error) {
if _, err = d.db.Exec(c, _upsertAddBlockCount, mid); err != nil {
err = errors.WithStack(err)
return
}
return
}

58
app/job/main/block/db.sql Normal file
View File

@@ -0,0 +1,58 @@
# 新增 block_user 表
CREATE TABLE `block_user` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增id',
`mid` INT(11) NOT NULL COMMENT '用户mid',
`status` TINYINT(4) NOT NULL COMMENT '封禁状态',
`ctime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_mid` (`mid`),
KEY `ix_mtime` (`mtime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='封禁服务用户表';
# 新增 block_user_detail 表 ,用户详情表,用作聚合数据用
CREATE TABLE `block_user_detail` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增id',
`mid` INT(11) NOT NULL COMMENT '用户mid',
`block_count` INT(11) NOT NULL COMMENT '封禁计次',
`ctime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_mid` (`mid`),
KEY `ix_mtime` (`mtime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='封禁服务用户详情表';
# 新增 block_history 表 —— 10张分表
CREATE TABLE `block_history_[0-9]` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增id',
`mid` INT(11) NOT NULL COMMENT '用户mid',
`admin_id` INT(11) NOT NULL COMMENT '管理员id',
`admin_name` VARCHAR(16) NOT NULL COMMENT '管理员name',
`source` TINYINT(4) NOT NULL COMMENT '封禁来源',
`area` TINYINT(4) NOT NULL COMMENT '封禁业务',
`reason` VARCHAR(50) NOT NULL COMMENT '封禁理由',
`comment` VARCHAR(50) NOT NULL COMMENT '封禁备注',
`action` TINYINT(4) NOT NULL COMMENT '操作类型',
`start_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '开始生效时间',
`duration` INT(11) NOT NULL COMMENT '生效时长(秒)',
`notify` TINYINT(4) NOT NULL COMMENT '是否通知',
`ctime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `ix_mid` (`mid`),
KEY `ix_action` (`action`),
KEY `ix_mtime` (`mtime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='封禁服务用户历史表';
# 新增 block_extra 表 封禁业务标识
CREATE TABLE `block_extra` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增id',
`mid` INT(11) NOT NULL COMMENT '用户mid',
`credit_answer_flag` TINYINT(4) NOT NULL COMMENT '小黑屋答题标识',
`action_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '行为发生时间',
`ctime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_mid` (`mid`),
KEY `ix_mtime` (`mtime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='封禁业务标识';

View File

@@ -0,0 +1,33 @@
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/block/http",
tags = ["automanaged"],
deps = [
"//app/job/main/block/conf:go_default_library",
"//app/job/main/block/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,38 @@
package http
import (
"go-common/app/job/main/block/conf"
"go-common/app/job/main/block/service"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
)
var (
svc *service.Service
)
// Init init
func Init() {
initService()
engine := bm.DefaultServer(conf.Conf.BM)
router(engine)
if err := engine.Start(); err != nil {
log.Error("%+v", err)
panic(err)
}
}
// initService init services.
func initService() {
svc = service.New()
}
// router init inner router api path.
func router(e *bm.Engine) {
//init api
e.GET("/monitor/ping", ping)
}
// ping check server ok.
func ping(c *bm.Context) {
}

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 = [
"blackhouse.go",
"dao.go",
"model.go",
"msg.go",
"notify.go",
],
importpath = "go-common/app/job/main/block/model",
tags = ["automanaged"],
deps = ["//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"],
)

View File

@@ -0,0 +1,11 @@
package model
import (
xtime "go-common/library/time"
)
// CreditAnswerMSG param struct
type CreditAnswerMSG struct {
MID int64 `json:"mid"`
MTime xtime.Time `json:"mtime"`
}

View File

@@ -0,0 +1,56 @@
package model
import (
"time"
)
// DBUser .
type DBUser struct {
ID int64
MID int64
Status BlockStatus
CTime time.Time
MTime time.Time
}
// DBUserDetail .
type DBUserDetail struct {
ID int64
MID int64
BlockCount int
CTime time.Time
MTime time.Time
}
// DBHistory .
type DBHistory struct {
ID int64
MID int64
AdminID int64
AdminName string
Source BlockSource
Area BlockArea
Reason string
Comment string
Action BlockAction
StartTime time.Time
Duration int64
Notify bool
CTime time.Time
MTime time.Time
}
// DBExtra .
type DBExtra struct {
ID int64
MID int64
CreditAnswerFlag bool
ActionTime time.Time
CTime time.Time
MTime time.Time
}
// MCBlockInfo .
type MCBlockInfo struct {
BlockStatus BlockStatus `json:"bs"`
}

View File

@@ -0,0 +1,184 @@
package model
import (
"time"
)
// BlockStatus 封禁状态 0. 未封禁 1. 永久封禁 2. 限时封禁
type BlockStatus uint8
const (
// BlockStatusFalse 未封禁
BlockStatusFalse BlockStatus = iota
// BlockStatusForever 永久封禁
BlockStatusForever
// BlockStatusLimit 限时封禁
BlockStatusLimit
// BlockStatusCredit 小黑屋封禁
BlockStatusCredit
)
// BlockSource 封禁来源 1. 小黑屋(小黑屋和manager后台封禁) 2. 系统封禁(反作弊及监控系统上报) 3.解封 (所有后台,用户前台自助的解封)
type BlockSource uint8
const (
// BlockSourceCredit 小黑屋封禁
BlockSourceCredit BlockSource = iota + 1
// BlockSourceSys 系统封禁
BlockSourceSys
// BlockSourceRemove 解封
BlockSourceRemove
)
// String .
func (b BlockSource) String() string {
switch b {
case BlockSourceCredit:
return "小黑屋封禁"
case BlockSourceSys:
return "系统封禁"
case BlockSourceRemove:
return "解封"
default:
return ""
}
}
const (
// BlockLogBizID 用户审核日志
BlockLogBizID = 122
// BlockJOBManagerID blockjob manager uid
BlockJOBManagerID = 1493
// BlockJOBManagerName blockjob manager name
BlockJOBManagerName = "blockjob"
)
// BlockArea 封禁业务
type BlockArea uint8
// const .
const (
BlockAreaNone BlockArea = iota
BlockAreaReply
BlockAreaDanmaku
BlockAreaMessage
BlockAreaTag
BlockAreaProfile // 个人资料
BlockAreaArchive
BlockAreaMusic
BlockAreaArticle
BlockAreaSpaceBanner // 空间头图
BlockAreaDynamic // 动态
BlockAreaAlbum // 相册
BlockAreaQuickVideo //小视频
)
// String .
func (b BlockArea) String() string {
switch b {
case BlockAreaReply:
return "评论"
case BlockAreaDanmaku:
return "弹幕"
case BlockAreaMessage:
return "私信"
case BlockAreaTag:
return "标签"
case BlockAreaProfile:
return "个人资料"
case BlockAreaArchive:
return "投稿"
case BlockAreaMusic:
return "音频"
case BlockAreaArticle:
return "专栏"
case BlockAreaSpaceBanner:
return "空间头图"
case BlockAreaDynamic:
return "动态"
case BlockAreaAlbum:
return "相册"
case BlockAreaQuickVideo:
return "小视频"
default:
return ""
}
}
// BlockAction .
type BlockAction uint8
const (
// BlockActionLimit 限时封禁
BlockActionLimit BlockAction = iota + 1
// BlockActionForever 永久封禁
BlockActionForever
// BlockActionAdminRemove 后台解封
BlockActionAdminRemove
// BlockActionSelfRemove 自助解封
BlockActionSelfRemove
)
// String .
func (b BlockAction) String() string {
switch b {
case BlockActionLimit:
return "限时封禁"
case BlockActionForever:
return "永久封禁"
case BlockActionAdminRemove:
return "后台解封"
case BlockActionSelfRemove:
return "自动解封"
default:
return ""
}
}
// BlockInfo 封禁信息
type BlockInfo struct {
MID int64 `json:"mid"`
BlockStatus BlockStatus `json:"block_status"` // blockStatus 封禁状态 0. 未封禁 1. 永久封禁 2. 限时封禁
// EndTime int64 `json:"end_time"` // 结束封禁时间 unix time 永久封禁为0
}
// ParseDB .
func (b *BlockInfo) ParseDB(data *DBUser) {
b.MID = data.MID
b.BlockStatus = data.Status
}
// ParseMC .
func (b *BlockInfo) ParseMC(data *MCBlockInfo, mid int64) {
b.MID = mid
b.BlockStatus = data.BlockStatus
}
// BlockHistory 封禁历史
type BlockHistory struct {
Area BlockArea `json:"type"`
Operator string `json:"operator"` // 操作人
Reason string `json:"reason"` // 封禁原因
Action BlockAction `json:"action"` // 操作类型
ActionTime int64 `json:"action_time"` // 操作时间
RemoveTime int64 `json:"remove_time"` // 解封时间
Comment string `json:"comment"`
}
// ParseDB .
func (b *BlockHistory) ParseDB(data *DBHistory) {
b.Area = data.Area
b.Operator = data.AdminName
b.Reason = data.Reason
b.Action = data.Action
b.ActionTime = data.StartTime.Unix()
b.RemoveTime = data.StartTime.Add(time.Second * time.Duration(data.Duration)).Unix()
b.Comment = data.Comment
}
// BlockMessage 通知消息体
type BlockMessage struct {
MID int64 `json:"mid"` // 用户mid
Area BlockArea `json:"area"` // BlockArea 封禁类型 1. 小黑屋(小黑屋和manager后台封禁) 2. 系统封禁(反作弊及监控系统上报) 3.解封 (所有后台,用户前台自助的解封)
Status BlockStatus `json:"status"` // blockStatus 封禁状态 0. 未封禁 1. 永久封禁 2. 限时封禁
}

View File

@@ -0,0 +1,8 @@
package model
// MSG .
type MSG struct {
Code string
Title string
Content string
}

View File

@@ -0,0 +1,8 @@
package model
// AccountNotify .
type AccountNotify struct {
UID int64 `json:"mid"`
Type string `json:"type"`
Action string `json:"action"`
}

View File

@@ -0,0 +1,58 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["service_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/block/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"audit_log.go",
"blackhouse.go",
"limit.go",
"msg.go",
"notify.go",
"service.go",
],
importpath = "go-common/app/job/main/block/service",
tags = ["automanaged"],
deps = [
"//app/job/main/block/conf:go_default_library",
"//app/job/main/block/dao:go_default_library",
"//app/job/main/block/model:go_default_library",
"//library/cache:go_default_library",
"//library/database/sql:go_default_library",
"//library/log:go_default_library",
"//library/queue/databus:go_default_library",
"//library/queue/databus/report: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,48 @@
package service
import (
"context"
"strconv"
"time"
"go-common/app/job/main/block/model"
"go-common/library/log"
manager "go-common/library/queue/databus/report"
)
// AddAuditLog .
func (s *Service) AddAuditLog(c context.Context, tp model.BlockAction, uid int64, uname string, oids []int64, duration time.Duration, source model.BlockSource, area model.BlockArea, reason, comment string, notify bool, stime time.Time) error {
var (
err error
dur = int64(duration / time.Second)
notifyStr = strconv.FormatBool(notify)
)
for _, oid := range oids {
managerInfo := &manager.ManagerInfo{
UID: uid,
Uname: uname,
Business: model.BlockLogBizID,
Type: int(tp),
Action: tp.String(),
Oid: oid,
Ctime: time.Now(),
Index: []interface{}{dur, uint8(source), uint8(area), reason, comment, notifyStr},
Content: map[string]interface{}{
"duration": dur,
"source": source,
"area": area,
"reason": reason,
"comment": comment,
"notify": notifyStr,
"action_time": stime.Unix(),
"remove_time": stime.Add(time.Second * time.Duration(dur)).Unix(),
},
}
if err = manager.Manager(managerInfo); err != nil {
log.Error("manager.Manager(%+v) error(%+v)", managerInfo, err)
continue
}
log.Info("s.managerSendLog(%+v)", managerInfo)
}
return err
}

View File

@@ -0,0 +1,200 @@
package service
import (
"context"
"encoding/json"
"fmt"
"time"
"go-common/app/job/main/block/conf"
"go-common/app/job/main/block/model"
xsql "go-common/library/database/sql"
"go-common/library/log"
"go-common/library/queue/databus"
"github.com/pkg/errors"
)
func (s *Service) creditExpireHandler(c context.Context) {
if conf.Conf.Property.CreditExpireCheckLimit <= 0 {
log.Error("conf.Conf.Property.creditExpireCheckLimit [%d] <= 0", conf.Conf.Property.CreditExpireCheckLimit)
return
}
var (
mids = make([]int64, conf.Conf.Property.CreditExpireCheckLimit)
startID int64
err error
)
for len(mids) >= conf.Conf.Property.CreditExpireCheckLimit {
log.Info("black house expire handle startID (%d)", startID)
if startID, mids, err = s.dao.UserStatusList(c, model.BlockStatusCredit, startID, conf.Conf.Property.CreditExpireCheckLimit); err != nil {
log.Error("%+v", err)
return
}
for _, mid := range mids {
log.Info("Start handle black house mid (%d)", mid)
var ok bool
if ok, err = s.creditExpireCheck(c, mid); err != nil {
log.Error("%+v", err)
continue
}
if ok {
log.Info("Start remove black house mid (%d)", mid)
if err = s.creditExpireRemove(c, mid); err != nil {
log.Error("%+v", err)
}
}
}
}
}
func (s *Service) creditExpireCheck(c context.Context, mid int64) (ok bool, err error) {
var (
his *model.DBHistory
ex *model.DBExtra
)
if his, err = s.dao.UserLastHistory(c, mid); err != nil {
return
}
if his == nil {
return
}
log.Info("Credit check his (%+v)", his)
if his.Action != model.BlockActionLimit || his.Source != model.BlockSourceCredit {
return
}
if ex, err = s.dao.UserExtra(c, mid); err != nil {
return
}
if ex == nil {
return
}
log.Info("Credit check extra (%+v)", his)
if ex.ActionTime.Before(his.StartTime) {
return
}
if his.StartTime.Add(time.Duration(his.Duration) * time.Second).After(time.Now()) {
return
}
ok = true
return
}
func (s *Service) creditExpireRemove(c context.Context, mid int64) (err error) {
var (
db = &model.DBHistory{
MID: mid,
AdminID: -1,
AdminName: "sys",
Source: model.BlockSourceRemove,
Area: model.BlockAreaNone,
Reason: "小黑屋自动解封",
Comment: "小黑屋自动解封",
Action: model.BlockActionSelfRemove,
StartTime: time.Now(),
Duration: 0,
Notify: false,
}
tx *xsql.Tx
)
if tx, err = s.dao.BeginTX(c); err != nil {
return
}
if err = s.dao.TxInsertHistory(c, tx, db); err != nil {
tx.Rollback()
return
}
if err = s.dao.TxUpsertUser(c, tx, mid, model.BlockStatusFalse); err != nil {
tx.Rollback()
return
}
if err = tx.Commit(); err != nil {
err = errors.WithStack(err)
}
s.mission(func() {
if err := s.notifyRemoveMSG(context.TODO(), []int64{mid}); err != nil {
log.Error("%+v", err)
}
})
s.cache.Save(func() {
if err := s.dao.DeleteUserCache(context.TODO(), mid); err != nil {
log.Error("%+v", err)
}
if databusErr := s.accountNotify(context.TODO(), mid); databusErr != nil {
log.Error("%+v", databusErr)
}
})
return
}
func (s *Service) notifyRemoveMSG(c context.Context, mids []int64) (err error) {
code, title, content := s.MSGRemoveInfo()
if err = s.dao.SendSysMsg(c, code, mids, title, content, ""); err != nil {
return
}
return
}
// databus
func (s *Service) creditsubproc() {
defer func() {
if x := recover(); x != nil {
log.Error("%+v", errors.WithStack(fmt.Errorf("s.creditsubproc panic(%v)", x)))
go s.creditsubproc()
log.Info("s.creditsubproc recover")
}
}()
var (
msg *databus.Message
eventMSG *model.CreditAnswerMSG
err error
msgChan = s.creditSub.Messages()
c = context.TODO()
)
for msg = range msgChan {
if err = msg.Commit(); err != nil {
log.Error("msg.Commit error(%v)", err)
}
eventMSG = &model.CreditAnswerMSG{}
if err = json.Unmarshal([]byte(msg.Value), eventMSG); err != nil {
log.Error("%+v", errors.WithStack(err))
continue
}
if err = s.handleCreditAnswerMSG(c, eventMSG); err != nil {
log.Error("%+v", err)
continue
}
log.Info("s.handleCreditAnswerMSG(%v) msg", eventMSG)
}
log.Info("creditsubproc end")
}
func (s *Service) handleCreditAnswerMSG(c context.Context, msg *model.CreditAnswerMSG) (err error) {
if msg.MID <= 0 {
return
}
var (
extra = &model.DBExtra{
MID: msg.MID,
CreditAnswerFlag: true,
ActionTime: msg.MTime.Time(),
}
checkFlag bool
)
if err = s.dao.InsertExtra(c, extra); err != nil {
return
}
// 及时检查解封
log.Info("Start check black house mid (%d) from answer", extra.MID)
if checkFlag, err = s.creditExpireCheck(c, extra.MID); err != nil {
return
}
if checkFlag {
log.Info("Start remove black house mid (%d)", extra.MID)
if err = s.creditExpireRemove(c, extra.MID); err != nil {
return
}
}
return
}

View File

@@ -0,0 +1,115 @@
package service
import (
"context"
"time"
"go-common/app/job/main/block/conf"
"go-common/app/job/main/block/model"
xsql "go-common/library/database/sql"
"go-common/library/log"
"github.com/pkg/errors"
)
func (s *Service) limitExpireHandler(c context.Context) {
if conf.Conf.Property.LimitExpireCheckLimit <= 0 {
log.Error("conf.Conf.Property.LimitExpireCheckLimit [%d] <= 0", conf.Conf.Property.LimitExpireCheckLimit)
return
}
var (
mids = make([]int64, conf.Conf.Property.LimitExpireCheckLimit)
startID int64
err error
)
for len(mids) >= conf.Conf.Property.LimitExpireCheckLimit {
log.Info("limit expire handle startID (%d)", startID)
if startID, mids, err = s.dao.UserStatusList(c, model.BlockStatusLimit, startID, conf.Conf.Property.LimitExpireCheckLimit); err != nil {
log.Error("%+v", err)
return
}
for _, mid := range mids {
var ok bool
if ok, err = s.limitExpireCheck(c, mid); err != nil {
log.Error("%+v", err)
continue
}
if ok {
s.limitExpireRemove(c, mid)
}
time.Sleep(time.Millisecond * 100)
}
}
}
func (s *Service) limitExpireCheck(c context.Context, mid int64) (ok bool, err error) {
var (
his *model.DBHistory
)
if his, err = s.dao.UserLastHistory(c, mid); err != nil {
return
}
if his == nil {
return
}
if his.Action != model.BlockActionLimit {
return
}
if his.StartTime.Add(time.Duration(his.Duration) * time.Second).After(time.Now()) {
return
}
ok = true
return
}
func (s *Service) limitExpireRemove(c context.Context, mid int64) (err error) {
var (
_reason, _comment = "系统自动解封", "系统自动解封"
stime = time.Now()
db = &model.DBHistory{
MID: mid,
AdminID: model.BlockJOBManagerID,
AdminName: model.BlockJOBManagerName,
Source: model.BlockSourceRemove,
Area: model.BlockAreaNone,
Reason: _reason,
Comment: _comment,
Action: model.BlockActionSelfRemove,
StartTime: stime,
Duration: 0,
Notify: false,
}
tx *xsql.Tx
)
if tx, err = s.dao.BeginTX(c); err != nil {
return
}
if err = s.dao.TxInsertHistory(c, tx, db); err != nil {
tx.Rollback()
return
}
if err = s.dao.TxUpsertUser(c, tx, mid, model.BlockStatusFalse); err != nil {
tx.Rollback()
return
}
if err = tx.Commit(); err != nil {
err = errors.WithStack(err)
}
s.mission(func() {
if err := s.notifyRemoveMSG(context.TODO(), []int64{mid}); err != nil {
log.Error("%+v", err)
}
})
s.mission(func() {
s.AddAuditLog(context.TODO(), model.BlockActionSelfRemove, model.BlockJOBManagerID, model.BlockJOBManagerName, []int64{mid}, 0, model.BlockSourceRemove, model.BlockAreaNone, _reason, _comment, false, stime)
})
s.cache.Save(func() {
if err := s.dao.DeleteUserCache(context.TODO(), mid); err != nil {
log.Error("%+v", err)
}
if databusErr := s.accountNotify(context.TODO(), mid); databusErr != nil {
log.Error("%+v", databusErr)
}
})
return
}

View File

@@ -0,0 +1,13 @@
package service
import (
"go-common/app/job/main/block/conf"
)
// MSGRemoveInfo get msg info
func (s *Service) MSGRemoveInfo() (code string, title, content string) {
code = conf.Conf.Property.MSG.BlockRemove.Code
title = conf.Conf.Property.MSG.BlockRemove.Title
content = conf.Conf.Property.MSG.BlockRemove.Content
return
}

View File

@@ -0,0 +1,18 @@
package service
import (
"context"
"strconv"
"go-common/app/job/main/block/model"
"github.com/pkg/errors"
)
func (s *Service) accountNotify(c context.Context, mid int64) (err error) {
msg := &model.AccountNotify{UID: mid, Action: "blockUser"}
if err = s.accountNotifyPub.Send(c, strconv.FormatInt(msg.UID, 10), msg); err != nil {
err = errors.Errorf("mid(%d) s.accountNotify.Send(%+v) error(%+v)", msg.UID, msg, err)
}
return
}

View File

@@ -0,0 +1,114 @@
package service
import (
"context"
"fmt"
"time"
"go-common/app/job/main/block/conf"
"go-common/app/job/main/block/dao"
"go-common/library/cache"
"go-common/library/log"
"go-common/library/queue/databus"
"github.com/pkg/errors"
)
// Service struct
type Service struct {
dao *dao.Dao
cache *cache.Cache
missch chan func()
creditSub *databus.Databus
accountNotifyPub *databus.Databus
}
// New init
func New() (s *Service) {
s = &Service{
dao: dao.New(),
cache: cache.New(1, 10240),
missch: make(chan func(), 10240),
creditSub: databus.New(conf.Conf.Databus.Credit),
accountNotifyPub: databus.New(conf.Conf.AccountNotify),
}
// 自动解禁检查
if conf.Conf.Property.Flag.ExpireCheck {
go s.limitcheckproc()
go s.creditcheckproc()
}
// 小黑屋答题状态订阅
if conf.Conf.Property.Flag.CreditSub {
go s.creditsubproc()
}
go s.missproc()
return s
}
// 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()
}
func (s *Service) limitcheckproc() {
defer func() {
if x := recover(); x != nil {
log.Error("service.limitcheckproc panic(%v)", x)
go s.limitcheckproc()
log.Info("service.limitcheckproc recover")
}
}()
for {
log.Info("limit check start")
s.limitExpireHandler(context.TODO())
log.Info("limit check end")
time.Sleep(time.Duration(conf.Conf.Property.LimitExpireCheckTick))
}
}
func (s *Service) creditcheckproc() {
defer func() {
if x := recover(); x != nil {
log.Error("%+v", errors.WithStack(fmt.Errorf("service.creditcheckproc panic(%v)", x)))
go s.creditcheckproc()
log.Info("service.creditcheckproc recover")
}
}()
for {
log.Info("black house check start")
s.creditExpireHandler(context.TODO())
log.Info("black house check end")
time.Sleep(time.Duration(conf.Conf.Property.CreditExpireCheckTick))
}
}
func (s *Service) missproc() {
defer func() {
if x := recover(); x != nil {
log.Error("service.missproc panic(%v)", x)
go s.missproc()
log.Info("service.missproc recover")
}
}()
for {
f := <-s.missch
f()
}
}
func (s *Service) mission(f func()) {
select {
case s.missch <- f:
default:
log.Error("s.missch full")
}
}

View File

@@ -0,0 +1,37 @@
package service
import (
"context"
"flag"
"os"
"testing"
"go-common/app/job/main/block/conf"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
c context.Context
)
func TestMain(m *testing.M) {
defer os.Exit(0)
flag.Set("conf", "../cmd/block-job-test.toml")
var err error
if err = conf.Init(); err != nil {
panic(err)
}
s = New()
defer s.Close()
m.Run()
}
func TestService(t *testing.T) {
Convey("", t, func() {
s.Ping(c)
s.Close()
})
}