Create & Init Project...

This commit is contained in:
2019-04-22 18:49:16 +08:00
commit fc4fa37393
25440 changed files with 4054998 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/job/main/app-wall/cmd:all-srcs",
"//app/job/main/app-wall/conf:all-srcs",
"//app/job/main/app-wall/dao/offer:all-srcs",
"//app/job/main/app-wall/dao/seq:all-srcs",
"//app/job/main/app-wall/dao/unicom:all-srcs",
"//app/job/main/app-wall/http:all-srcs",
"//app/job/main/app-wall/model:all-srcs",
"//app/job/main/app-wall/service/offer:all-srcs",
"//app/job/main/app-wall/service/unicom:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,123 @@
# APP WALL JOB
## v1.3.7
> 1.修复流量包和流量卡数据共存问题
## v1.3.6
> 1.修复每月福利社发放积分
## v1.3.5
> 1.修复每月福利社发放积分
## v1.3.4
> 1.click error修改
## v1.3.3
> 1.sync.WaitGroup
## v1.3.2
1.1.去掉net/ip调用
## v1.3.1
1.删除多余代码
## v1.3.0
1.更换report-click的databus
## v1.2.3
1.福利社用户日志
## v1.2.2
1.去除结果找不到的错误
## v1.2.1
1.缓存修改
## v1.2.0
1.update infoc sdk
## v1.1.9
1.删除identify
## v1.1.8
1.seq server
## v1.1.7
1.增加用户添加日志
2.关闭logCh
## v1.1.6
1.增加积分返还日志
## v1.1.5
1.联通IP异步同步下沉
## v1.1.4
1.增加日志
## v1.1.3
1.异步消费逻辑放到job
## v1.1.2
1.修改test
## v1.1.1
1.联通礼包每月结算
2.不是免流卡不加积分
## v1.1.0
1.修改缓存有效时间
## v1.0.9
1.修复DB没更新问题
## v1.0.8
1.修改日志
## v1.0.7
1.修改日志
## v1.0.6
1.修复消费问题
## v1.0.5
1.联通礼包基本消费
## v1.0.4
1.修复激活
## v1.0.1
1.激活增加安卓imei
## v1.0.0
1.客户端新增用户激活消费

View File

@@ -0,0 +1,9 @@
# Owner
peiyifei
renwei
haoguanwei
# Author
zhangxin
# Reviewer

View File

@@ -0,0 +1,15 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- haoguanwei
- peiyifei
- renwei
- zhangxin
labels:
- job
- job/main/app-wall
- main
options:
no_parent_owners: true
reviewers:
- zhangxin

View File

@@ -0,0 +1,12 @@
# app-wall-job
# 项目简介
1.app-wall job
# 编译环境
# 依赖包
# 编译执行

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 = ["app-wall-job-test.toml"],
importpath = "go-common/app/job/main/app-wall/cmd",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/app-wall/conf:go_default_library",
"//app/job/main/app-wall/http:go_default_library",
"//library/ecode/tip:go_default_library",
"//library/log:go_default_library",
"//library/net/trace: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,221 @@
# This is a TOML document. Boom
version = "1.0.0"
user = "nobody"
pid = "/tmp/app-wall-job.pid"
dir = "./"
perf = "0.0.0.0:7610"
chanNum = 8
chanDBNum = 8
tick = "20s"
monthly=false
[unicomuserInfoc2]
taskID = "000951"
proto = "tcp"
addr = ""
chanSize = 10240
[unicomPackInfoc]
taskID = "000918"
proto = "tcp"
addr = ""
chanSize = 10240
[log]
dir = "/data/log/app-wall-job"
[tracer]
family = "app-wall-job"
proto = "unixgram"
addr = "/var/run/dapper-collect/dapper-collect.sock"
[host]
app = "http://app.bilibili.co"
unicomFlow = "http://open.10010.com"
unicom = "http://123.125.99.7:9001"
[bm]
[bm.inner]
addr = "0.0.0.0:7611"
maxListen = 10
timeout = "1s"
[bm.local]
addr = "0.0.0.0:7612"
maxListen = 10
timeout = "1s"
[identify]
whiteAccessKey = ""
whiteMid = 0
[identify.app]
key = "6a29f8ed87407c11"
secret = "d3c5a85f5b895a03735b5d20a273bc57"
[identify.memcache]
name = "go-business/identify"
proto = "tcp"
addr = "172.16.33.54:11211"
active = 5
idle = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "80s"
[identify.host]
auth = "http://passport.bilibili.com"
secret = "http://open.bilibili.com"
[identify.httpClient]
key = "f022126a8a365e20"
secret = "b7b86838145d634b487e67b811b8fab2"
dial = "30ms"
timeout = "100ms"
keepAlive = "60s"
[identify.httpClient.breaker]
window = "10s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[identify.httpClient.url]
"http://passport.bilibili.co/intranet/auth/tokenInfo" = {timeout = "100ms"}
"http://passport.bilibili.co/intranet/auth/cookieInfo" = {timeout = "100ms"}
"http://open.bilibili.co/api/getsecret" = {timeout = "500ms"}
[ecode]
domain = "uat-api.bilibili.co"
all = "1h"
diff = "5m"
[ecode.clientconfig]
key = "c1a1cb2d89c33794"
secret = "dda47eeca111e03e6845017505baea13"
dial = "2000ms"
timeout = "2s"
keepAlive = "10s"
timer = 128
[ecode.clientconfig.breaker]
window ="3s"
sleep ="100ms"
bucket = 10
ratio = 0.5
request = 100
[mysql]
[mysql.show]
addr = "172.16.33.205:3308"
dsn = "test:test@tcp(172.16.33.205:3308)/bilibili_show?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 5
idle = 2
idleTimeout ="4h"
queryTimeout = "1s"
execTimeout = "1s"
tranTimeout = "1s"
[mysql.show.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[redis]
[redis.feed]
name = "app-wall-job/active"
proto = "tcp"
addr = "172.16.0.148:6379"
active = 10
idle = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "1m"
[seq]
businessID =1
token ="Y1zHA2esXfd2T6bc1VRHkFWryD01Aswi"
[seqRPC]
pullInterval = "10s"
[seqRPC.client]
timeout = "200ms"
[seqRPC.client.breaker]
window ="3s"
sleep ="100ms"
bucket = 10
ratio = 0.5
request = 100
[seqRPC.zookeeper]
root = "/microservice/seq-proxy/"
addrs = ["172.16.33.169:2181"]
timeout = "30s"
[consumer]
topic = "app-wall-job"
group = "lancer_main_dw_channel_new_devices"
Offset = "new"
Brokers = ["172.19.40.183:9092,172.19.40.184:9092,172.19.40.185:9092,172.19.40.186:9092,172.19.40.187:9092,172.19.40.188:92,172.19.40.189:9092,172.19.40.190:9092,172.19.40.191:9092,172.19.40.192:9092"]
[httpClient]
key = "e7482d29be4a95b8"
secret = "9e803791cdef756e75faee68e12b7442"
dial = "30ms"
timeout = "100ms"
keepAlive = "60s"
[httpClient.breaker]
window = "10s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[HTTPUnicom]
key = "e7482d29be4a95b8"
secret = "9e803791cdef756e75faee68e12b7442"
dial = "500ms"
timeout = "4s"
keepAlive = "60s"
timer = 10
[HTTPUnicom.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[unicom]
packKeyExpired = "24h"
keyExpired = "24h"
[memcache]
[memcache.operator]
name = "app-show/archive"
proto = "tcp"
addr = "172.16.33.54:11213"
active = 50
idle = 10
dialTimeout = "50ms"
readTimeout = "100ms"
writeTimeout = "100ms"
idleTimeout = "80s"
expire = "10s"
[reportDatabus]
key = "8e27ab7e39270b59"
secret = "477df6a068d7332a163f95abbad2079c"
group = "ArchiveClick-MainAppSvr-2-S"
topic = "ArchiveClick-T"
action = "sub"
name = "report-click/sub"
proto = "tcp"
addr = "172.18.33.50:6205"
active = 5
idle = 1
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
# [consumer]
# topic = "lancer_main_dw_channel_new_devices"
# group = "app-wall-job"
# offset = "new"
# brokers = ["172.19.40.183:9092"]

View File

@@ -0,0 +1,53 @@
package main
import (
"flag"
"os"
"os/signal"
"syscall"
"go-common/app/job/main/app-wall/conf"
"go-common/app/job/main/app-wall/http"
ecode "go-common/library/ecode/tip"
"go-common/library/log"
"go-common/library/net/trace"
"go-common/library/queue/databus/report"
)
func main() {
flag.Parse()
if err := conf.Init(); err != nil {
log.Error("conf.Init() error(%v)", err)
panic(err)
}
// init log
log.Init(conf.Conf.Log)
defer log.Close()
log.Info("app-wall start")
// init trace
trace.Init(conf.Conf.Tracer)
defer trace.Close()
// ecode init
ecode.Init(conf.Conf.Ecode)
// report init
report.InitUser(conf.Conf.Report)
// service init
http.Init(conf.Conf)
// init pprof conf.Conf.Perf
// init signal
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
s := <-c
log.Info("app-wall get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
http.Close()
log.Info("app-wall exit")
return
case syscall.SIGHUP:
default:
return
}
}
}

View File

@@ -0,0 +1,43 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["conf.go"],
importpath = "go-common/app/job/main/app-wall/conf",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/cache/memcache:go_default_library",
"//library/cache/redis:go_default_library",
"//library/conf:go_default_library",
"//library/database/sql:go_default_library",
"//library/ecode/tip:go_default_library",
"//library/log:go_default_library",
"//library/log/infoc:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/rpc:go_default_library",
"//library/net/trace:go_default_library",
"//library/queue/databus:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/BurntSushi/toml:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,175 @@
package conf
import (
"errors"
"flag"
"go-common/library/cache/memcache"
"go-common/library/cache/redis"
"go-common/library/conf"
"go-common/library/database/sql"
ecode "go-common/library/ecode/tip"
"go-common/library/log"
"go-common/library/log/infoc"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/rpc"
"go-common/library/net/trace"
"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 {
// base
// elk
Log *log.Config
// http
BM *HTTPServers
// tracer
Tracer *trace.Config
// redis
Redis *Redis
// memcache
Memcache *Memcache
// db
MySQL *MySQL
// databus
ReportDatabus *databus.Config
// chan number
ChanNum int64
// chan db number
ChanDBNum int64
// ecode
Ecode *ecode.Config
// Report
Report *databus.Config
// client
Consumer *Consumer
// HTTPClient
HTTPClient *bm.ClientConfig
// HTTPUnicom
HTTPUnicom *bm.ClientConfig
// host
Host *Host
// unicom
Unicom *Unicom
// infoc2
UnicomUserInfoc2 *infoc.Config
UnicomPackInfoc *infoc.Config
// tick time
Tick xtime.Duration
// monthly
Monthly bool
// seq
SeqRPC *rpc.ClientConfig
// Seq
Seq *Seq
}
type Seq struct {
BusinessID int64
Token string
}
// HTTPServers Http Servers
type HTTPServers struct {
Outer *bm.ServerConfig
Inner *bm.ServerConfig
Local *bm.ServerConfig
}
type MySQL struct {
Show *sql.Config
}
type Unicom struct {
PackKeyExpired xtime.Duration
KeyExpired xtime.Duration
}
type Memcache struct {
Operator *struct {
*memcache.Config
Expire xtime.Duration
}
}
type Redis struct {
Feed *struct {
*redis.Config
}
}
type Consumer struct {
Group string
Topic string
Offset string
Brokers []string
}
type Host struct {
APP string
UnicomFlow string
Unicom string
}
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,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",
"redis_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/app-wall/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"redis.go",
],
importpath = "go-common/app/job/main/app-wall/dao/offer",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/app-wall/conf:go_default_library",
"//library/cache/redis:go_default_library",
"//library/ecode:go_default_library",
"//library/log: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,70 @@
package offer
import (
"context"
"net/url"
"go-common/app/job/main/app-wall/conf"
"go-common/library/cache/redis"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"github.com/pkg/errors"
)
const (
_active = "/x/wall/offer/active2"
)
// Dao dao
type Dao struct {
c *conf.Config
redis *redis.Pool
client *bm.Client
active string
}
// New init mysql db
func New(c *conf.Config) (dao *Dao) {
dao = &Dao{
c: c,
redis: redis.NewPool(c.Redis.Feed.Config),
client: bm.NewClient(c.HTTPClient),
active: c.Host.APP + _active,
}
return
}
// Close close the resource.
func (dao *Dao) Close() (err error) {
return dao.redis.Close()
}
// Ping dao ping
func (dao *Dao) Ping(c context.Context) (err error) {
return dao.PingRedis(c)
}
func (d *Dao) Active(c context.Context, os, imei, androidid, mac, ip string) (err error) {
params := url.Values{}
params.Set("os", os)
params.Set("imei", imei)
params.Set("androidid", androidid)
params.Set("mac", mac)
var res struct {
Code int `json:"code"`
}
if err = d.client.Post(c, d.active, ip, params, &res); err != nil {
return
}
if res.Code != ecode.OK.Code() {
err = errors.Wrap(ecode.Int(res.Code), d.active+"?"+params.Encode())
if res.Code == ecode.RequestErr.Code() {
log.Error("%+v", err)
err = nil
return
}
}
return
}

View File

@@ -0,0 +1,36 @@
package offer
import (
"context"
"flag"
"path/filepath"
"testing"
"time"
. "github.com/smartystreets/goconvey/convey"
"go-common/app/job/main/app-wall/conf"
)
var (
d *Dao
)
func ctx() context.Context {
return context.Background()
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-wall-job-test.toml")
flag.Set("conf", dir)
conf.Init()
d = New(conf.Conf)
time.Sleep(time.Second)
}
func TestActive(t *testing.T) {
Convey("Active", t, func() {
err := d.Active(ctx(), "", "", "", "", "")
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,56 @@
package offer
import (
"context"
"encoding/json"
"go-common/library/cache/redis"
"github.com/pkg/errors"
)
const (
_failList = "act_list"
)
func keyRetry() string {
return _failList
}
// PushFail rpush fail item to redis
func (d *Dao) PushFail(c context.Context, a interface{}) (err error) {
var bs []byte
conn := d.redis.Get(c)
key := keyRetry()
defer conn.Close()
if bs, err = json.Marshal(a); err != nil {
err = errors.Wrapf(err, "%v", a)
return
}
if _, err = conn.Do("RPUSH", key, bs); err != nil {
err = errors.Wrapf(err, "conn.Do(RPUSH,%s,%s)", key, bs)
}
return
}
// PopFail lpop fail item from redis
func (d *Dao) PopFail(c context.Context) (bs []byte, err error) {
conn := d.redis.Get(c)
key := keyRetry()
if bs, err = redis.Bytes(conn.Do("LPOP", key)); err != nil {
if err == redis.ErrNil {
err = nil
} else {
err = errors.Wrapf(err, "redis.Bytes(conn.Do(LPOP, %s))", key)
}
}
conn.Close()
return
}
func (d *Dao) PingRedis(c context.Context) (err error) {
var conn = d.redis.Get(c)
_, err = conn.Do("SET", "PING", "PONG")
conn.Close()
return
}

View File

@@ -0,0 +1,14 @@
package offer
import (
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestPushFail(t *testing.T) {
Convey("PushFail", t, func() {
err := d.PushFail(ctx(), "")
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,47 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["seq_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/app-wall/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["seq.go"],
importpath = "go-common/app/job/main/app-wall/dao/seq",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/app-wall/conf:go_default_library",
"//app/service/main/seq-server/model:go_default_library",
"//app/service/main/seq-server/rpc/client:go_default_library",
"//library/log: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,40 @@
package seq
import (
"context"
"go-common/app/job/main/app-wall/conf"
seq "go-common/app/service/main/seq-server/model"
seqrpc "go-common/app/service/main/seq-server/rpc/client"
"go-common/library/log"
)
type Dao struct {
c *conf.Config
seqRPC *seqrpc.Service2
businessID int64
token string
}
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
seqRPC: seqrpc.New2(c.SeqRPC),
businessID: c.Seq.BusinessID,
token: c.Seq.Token,
}
return
}
// SeqID
func (d *Dao) SeqID(ctx context.Context) (requestNo int64, err error) {
arg := &seq.ArgBusiness{
BusinessID: d.businessID,
Token: d.token,
}
if requestNo, err = d.seqRPC.ID(ctx, arg); err != nil {
log.Error("d.seqRPC.ID error (%v)", err)
return
}
return
}

View File

@@ -0,0 +1,37 @@
package seq
import (
"context"
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/job/main/app-wall/conf"
. "github.com/smartystreets/goconvey/convey"
)
var (
d *Dao
)
func ctx() context.Context {
return context.Background()
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-wall-test.toml")
flag.Set("conf", dir)
conf.Init()
d = New(conf.Conf)
time.Sleep(time.Second)
}
func TestSeqID(t *testing.T) {
Convey("SeqID", t, func() {
res, err := d.SeqID(ctx())
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,56 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["unicom_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/app-wall/conf:go_default_library",
"//app/job/main/app-wall/model/unicom:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"api.go",
"cache.go",
"dao.go",
],
importpath = "go-common/app/job/main/app-wall/dao/unicom",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/app-wall/conf:go_default_library",
"//app/job/main/app-wall/model:go_default_library",
"//app/job/main/app-wall/model/unicom:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/database/sql:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
],
)
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,183 @@
package unicom
import (
"bytes"
"context"
"crypto/md5"
"encoding/base64"
"encoding/hex"
"encoding/json"
"net/http"
"net/url"
"sort"
"strconv"
"strings"
"time"
"go-common/app/job/main/app-wall/model"
"go-common/app/job/main/app-wall/model/unicom"
"go-common/library/ecode"
"go-common/library/log"
httpx "go-common/library/net/http/blademaster"
)
const (
// unicom
_unicomUser = "000012"
_unicomPass = "1pibH5e1BN4V"
_unicomAppKey = "com.aop.app.bilibili"
_unicomMethodQryFlowChange = "com.ssp.method.outqryflowchange"
_unicomSecurity = "DVniSMVU6Z3cCIG3vbOn4Fqbof+QJ/6etD+lpa4M4clgj/Dv6XT0syTR8Xgu5nVzKuzro8eiTUzHy/QAzGjp+A=="
// url
_unicomFlowExchangeURL = "/openservlet"
_unicomIPURL = "/web/statistics/subsystem_2/query_ip.php"
)
// FlowQry unicom phone qryflowchange
func (d *Dao) FlowQry(c context.Context, phone int, requestNo int64, outorderid, orderid string, ts time.Time) (orderstatus, msg string, err error) {
param := url.Values{}
param.Set("appkey", _unicomAppKey)
param.Set("apptx", strconv.FormatInt(requestNo, 10))
param.Set("method", _unicomMethodQryFlowChange)
param.Set("orderid", orderid)
param.Set("outorderid", outorderid)
param.Set("timestamp", ts.Format("2006-01-02 15:04:05"))
param.Set("usernumber", strconv.Itoa(phone))
urlVal := d.urlParams(param)
urlVal = urlVal + "&" + d.sign(urlVal)
var res struct {
Code string `json:"respcode"`
Orderstatus string `json:"orderstatus"`
Failurtype string `json:"failurtype"`
Msg string `json:"respdesc"`
}
if err = d.unicomHTTPGet(c, d.unicomFlowExchangeURL+"?"+urlVal, nil, &res); err != nil {
log.Error("unicom flowQry url(%v) error(%v)", d.unicomFlowExchangeURL+"?"+urlVal, err)
return
}
b, _ := json.Marshal(&res)
log.Info("unicom flowQry url(%v) response(%s)", d.unicomFlowExchangeURL+"?"+urlVal, b)
msg = res.Msg
if res.Code != "0000" {
err = ecode.String(res.Code)
log.Error("unicom flowQry url(%v) code(%v) msg(%v)", d.unicomFlowExchangeURL+"?"+urlVal, res.Code, res.Msg)
return
}
orderstatus = res.Orderstatus
return
}
// UnicomIP unicom ip orders
func (d *Dao) UnicomIP(c context.Context, now time.Time) (unicomIPs []*unicom.UnicomIP, err error) {
params := url.Values{}
params.Set("user", _unicomUser)
tick := strconv.FormatInt(now.Unix(), 10)
params.Set("tick", tick)
mh := md5.Sum([]byte(_unicomUser + tick + _unicomPass))
var (
key string
)
if key = hex.EncodeToString(mh[:]); len(key) > 16 {
key = key[:16]
}
params.Set("key", key)
var res struct {
Code int `json:"code"`
LastUpdateTime int64 `json:"last_update_time"`
Desc []struct {
StartIP string `json:"start_ip"`
Length string `json:"length"`
} `json:"desc"`
}
if err = d.unicomHTTPPost(c, d.unicomIPURL, params, &res); err != nil {
log.Error("unicom ip order url(%s) error(%v)", d.unicomIPURL+"?"+params.Encode(), err)
return
}
if res.Code != 0 {
err = ecode.Int(res.Code)
log.Error("unicom ip order url(%s) res code (%d)", d.unicomIPURL+"?"+params.Encode(), res.Code)
return
}
b, _ := json.Marshal(&res)
log.Info("unicom ip url(%s) response(%s)", d.unicomIPURL+"?"+params.Encode(), b)
for _, uip := range res.Desc {
uiplen, _ := strconv.Atoi(uip.Length)
if uiplen < 1 {
log.Error("unicom ip length 0")
continue
}
ipEndInt := model.InetAtoN(uip.StartIP) + uint32((uiplen - 1))
ipEnd := model.InetNtoA(ipEndInt)
unicomIP := &unicom.UnicomIP{}
unicomIP.UnicomIPStrToint(uip.StartIP, ipEnd)
unicomIPs = append(unicomIPs, unicomIP)
}
return
}
// unicomHTTPGet http get
func (d *Dao) unicomHTTPGet(c context.Context, urlStr string, params url.Values, res interface{}) (err error) {
return d.wallHTTP(c, d.uclient, http.MethodGet, urlStr, params, res)
}
// unicomHTTPPost http post
func (d *Dao) unicomHTTPPost(c context.Context, urlStr string, params url.Values, res interface{}) (err error) {
return d.wallHTTP(c, d.uclient, http.MethodPost, urlStr, params, res)
}
// wallHTTP http
func (d *Dao) wallHTTP(c context.Context, client *httpx.Client, method, urlStr string, params url.Values, res interface{}) (err error) {
var (
req *http.Request
)
ru := urlStr
if params != nil {
ru = urlStr + "?" + params.Encode()
}
switch method {
case http.MethodGet:
req, err = http.NewRequest(http.MethodGet, ru, nil)
default:
req, err = http.NewRequest(http.MethodPost, urlStr, strings.NewReader(params.Encode()))
}
if err != nil {
log.Error("unicom_http.NewRequest url(%s) error(%v)", urlStr+"?"+params.Encode(), err)
return
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("X-BACKEND-BILI-REAL-IP", "")
return client.Do(c, req, &res)
}
func (d *Dao) urlParams(v url.Values) string {
if v == nil {
return ""
}
var buf bytes.Buffer
keys := make([]string, 0, len(v))
for k := range v {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
vs := v[k]
prefix := k + "="
for _, v := range vs {
if buf.Len() > 0 {
buf.WriteByte('&')
}
buf.WriteString(prefix)
buf.WriteString(v)
}
}
return buf.String()
}
func (d *Dao) sign(params string) string {
str := strings.Replace(params, "&", "$", -1)
str2 := strings.Replace(str, "=", "$", -1)
mh := md5.Sum([]byte(_unicomSecurity + "$" + str2 + "$" + _unicomSecurity))
signparam := url.Values{}
signparam.Set("sign", base64.StdEncoding.EncodeToString(mh[:]))
return signparam.Encode()
}

View File

@@ -0,0 +1,248 @@
package unicom
import (
"context"
"fmt"
"time"
"go-common/app/job/main/app-wall/model/unicom"
"go-common/library/cache/memcache"
"go-common/library/log"
)
const (
_prefix = "unicoms_user_%v"
_userbindkey = "unicoms_user_bind_%d"
_userbindreceive = "unicom_pack_receives_%d"
_userflowkey = "unicom_user_flow_%v"
_userflowlistkey = "unicom_user_flow_list"
)
func keyUserBind(mid int64) string {
return fmt.Sprintf(_userbindkey, mid)
}
func keyUserBindReceive(mid int64) string {
return fmt.Sprintf(_userbindreceive, mid)
}
func keyUnicom(usermob string) string {
return fmt.Sprintf(_prefix, usermob)
}
func keyUserFlow(key string) string {
return fmt.Sprintf(_userflowkey, key)
}
// UserBindCache user bind cache
func (d *Dao) UserBindCache(c context.Context, mid int64) (ub *unicom.UserBind, err error) {
var (
key = keyUserBind(mid)
conn = d.mc.Get(c)
r *memcache.Item
)
defer conn.Close()
if r, err = conn.Get(key); err != nil {
if err != memcache.ErrNotFound {
log.Error("UserBindCache error(%v) or mid(%v)", err, mid)
}
return
}
if err = conn.Scan(r, &ub); err != nil {
log.Error("r.Scan(%s) error(%v)", r.Value, err)
}
return
}
// AddUserBindCache add user user bind cache
func (d *Dao) AddUserBindCache(c context.Context, mid int64, ub *unicom.UserBind) (err error) {
var (
key = keyUserBind(mid)
conn = d.mc.Get(c)
)
if err = conn.Set(&memcache.Item{Key: key, Object: ub, Flags: memcache.FlagJSON, Expiration: 0}); err != nil {
log.Error("AddUserBindCache d.mc.Set(%s,%v) error(%v)", key, ub, err)
}
conn.Close()
return
}
// DeleteUserBindCache delete user bind cache
func (d *Dao) DeleteUserBindCache(c context.Context, mid int64) (err error) {
var (
key = keyUserBind(mid)
conn = d.mc.Get(c)
)
defer conn.Close()
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
log.Error("DeleteUserBindCache MemchDB.Delete(%s) error(%v)", key, err)
return
}
return
}
// UserPackReceiveCache user pack cache
func (d *Dao) UserPackReceiveCache(c context.Context, mid int64) (count int, err error) {
var (
key = keyUserBindReceive(mid)
conn = d.mc.Get(c)
r *memcache.Item
)
defer conn.Close()
if r, err = conn.Get(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
log.Error("UserBindCache MemchDB.Get(%s) error(%v)", key, err)
return
}
if err = conn.Scan(r, &count); err != nil {
log.Error("r.Scan(%s) error(%v)", r.Value, err)
}
return
}
// AddUserPackReceiveCache add user pack cache
func (d *Dao) AddUserPackReceiveCache(c context.Context, mid int64, count int, now time.Time) (err error) {
var (
key = keyUserBindReceive(mid)
conn = d.mc.Get(c)
currenttimeSec = int32((now.Hour() * 60 * 60) + (now.Minute() * 60) + now.Second())
overtime int32
)
if overtime = d.expire - currenttimeSec; overtime < 1 {
overtime = d.expire
}
log.Info("AddUserPackReceiveCache mid(%d) overtime(%d)", mid, overtime)
if err = conn.Set(&memcache.Item{Key: key, Object: count, Flags: memcache.FlagJSON, Expiration: overtime}); err != nil {
log.Error("AddUserPackReceiveCache d.mc.Set(%s,%v) error(%v)", key, count, err)
}
conn.Close()
return
}
// DeleteUserPackReceiveCache delete user pack cache
func (d *Dao) DeleteUserPackReceiveCache(c context.Context, mid int64) (err error) {
var (
key = keyUserBindReceive(mid)
conn = d.mc.Get(c)
)
defer conn.Close()
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
log.Error("DeleteUserPackReceiveCache MemchDB.Delete(%s) error(%v)", key, err)
return
}
return
}
// UnicomCache
func (d *Dao) UnicomCache(c context.Context, usermob string) (u []*unicom.Unicom, err error) {
var (
key = keyUnicom(usermob)
conn = d.mc.Get(c)
r *memcache.Item
)
defer conn.Close()
if r, err = conn.Get(key); err != nil {
log.Error("unicomCache MemchDB.Get(%s) error(%v)", key, err)
return
}
if err = conn.Scan(r, &u); err != nil {
log.Error("r.Scan(%s) error(%v)", r.Value, err)
}
return
}
//UserFlowCache unicom flow cache
func (d *Dao) UserFlowCache(c context.Context, keyStr string) (err error) {
var (
key = keyUserFlow(keyStr)
conn = d.mc.Get(c)
r *memcache.Item
res struct{}
)
defer conn.Close()
if r, err = conn.Get(key); err != nil {
log.Error("UserFlowCache MemchDB.Get(%s) error(%v)", key, err)
return
}
if err = conn.Scan(r, &res); err != nil {
log.Error("r.Scan(%s) error(%v)", r.Value, err)
}
return
}
// AddUserFlowCache add user pack cache
func (d *Dao) AddUserFlowCache(c context.Context, keyStr string) (err error) {
var (
key = keyUserFlow(keyStr)
conn = d.mc.Get(c)
)
if err = conn.Set(&memcache.Item{Key: key, Object: struct{}{}, Flags: memcache.FlagJSON, Expiration: d.flowKeyExpired}); err != nil {
log.Error("AddUserPackCache d.mc.Set(%s) error(%v)", key, err)
}
conn.Close()
return
}
// DeleteUserPackCache delete user pack cache
func (d *Dao) DeleteUserFlowCache(c context.Context, keyStr string) (err error) {
var (
key = keyUserFlow(keyStr)
conn = d.mc.Get(c)
)
defer conn.Close()
if err = conn.Delete(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
log.Error("DeleteUserFlowCache MemchDB.Delete(%s) error(%v)", key, err)
return
}
return
}
//UserFlowListCache unicom flow cache
func (d *Dao) UserFlowListCache(c context.Context) (res map[string]*unicom.UnicomUserFlow, err error) {
var (
key = _userflowlistkey
conn = d.mc.Get(c)
r *memcache.Item
)
defer conn.Close()
if r, err = conn.Get(key); err != nil {
if err == memcache.ErrNotFound {
err = nil
return
}
log.Error("UserFlowListCache MemchDB.Get(%s) error(%v)", key, err)
return
}
if err = conn.Scan(r, &res); err != nil {
log.Error("r.Scan(%s) error(%v)", r.Value, err)
}
return
}
// AddUserFlowListCache add user pack cache
func (d *Dao) AddUserFlowListCache(c context.Context, list map[string]*unicom.UnicomUserFlow) (err error) {
var (
key = _userflowlistkey
conn = d.mc.Get(c)
)
if err = conn.Set(&memcache.Item{Key: key, Object: list, Flags: memcache.FlagJSON, Expiration: d.flowKeyExpired}); err != nil {
log.Error("AddUserFlowListCache d.mc.Set(%s,%v) error(%v)", key, list, err)
}
conn.Close()
return
}

View File

@@ -0,0 +1,207 @@
package unicom
import (
"context"
"database/sql"
"time"
"go-common/app/job/main/app-wall/conf"
"go-common/app/job/main/app-wall/model/unicom"
"go-common/library/cache/memcache"
xsql "go-common/library/database/sql"
"go-common/library/log"
httpx "go-common/library/net/http/blademaster"
)
const (
// unicom integral change
_upUserIntegralSQL = `UPDATE unicom_user_bind SET integral=?,flow=?,monthlytime=? WHERE mid=? AND state=1`
_orderUserSyncSQL = `SELECT usermob,spid,type,ordertime,endtime FROM unicom_order WHERE usermob=? AND type=0 ORDER BY type DESC`
_bindAllSQL = `SELECT mid,usermob,monthlytime FROM unicom_user_bind WHERE state=1 LIMIT ?,?`
_userBindSQL = `SELECT usermob,phone,mid,state,integral,flow,monthlytime FROM unicom_user_bind WHERE state=1 AND mid=?`
// update unicom ip
_inUnicomIPSyncSQL = `INSERT IGNORE INTO unicom_ip (ipbegion,ipend,isopen,ctime,mtime) VALUES(?,?,?,?,?) ON DUPLICATE KEY UPDATE
ipbegion=?,ipend=?,isopen=?,mtime=?`
_upUnicomIPSQL = `UPDATE unicom_ip SET isopen=?,mtime=? WHERE ipbegion=? AND ipend=?`
_ipSyncSQL = `SELECT ipbegion,ipend FROM unicom_ip WHERE isopen=1`
_inUserPackLogSQL = `INSERT INTO unicom_user_packs_log (phone,usermob,mid,request_no,ptype,integral,pdesc) VALUES (?,?,?,?,?,?,?)`
_inUserIntegralLogSQL = `INSERT INTO unicom_user_integral_log (phone,mid,unicom_desc,ptype,integral,flow,pdesc) VALUES (?,?,?,?,?,?,?)`
)
type Dao struct {
db *xsql.DB
uclient *httpx.Client
// memcache
mc *memcache.Pool
flowKeyExpired int32
expire int32
// unicom integral change
upUserIntegralSQL *xsql.Stmt
orderUserSyncSQL *xsql.Stmt
bindAllSQL *xsql.Stmt
userBindSQL *xsql.Stmt
ipSyncSQL *xsql.Stmt
inUserPackLogSQL *xsql.Stmt
inUserIntegralLogSQL *xsql.Stmt
// unicom url
unicomFlowExchangeURL string
unicomIPURL string
}
func New(c *conf.Config) (d *Dao) {
d = &Dao{
db: xsql.NewMySQL(c.MySQL.Show),
uclient: httpx.NewClient(conf.Conf.HTTPUnicom),
// memcache
mc: memcache.NewPool(c.Memcache.Operator.Config),
expire: int32(time.Duration(c.Unicom.PackKeyExpired) / time.Second),
flowKeyExpired: int32(time.Duration(c.Unicom.KeyExpired) / time.Second),
// unicom url
unicomFlowExchangeURL: c.Host.UnicomFlow + _unicomFlowExchangeURL,
unicomIPURL: c.Host.Unicom + _unicomIPURL,
}
// unicom integral change
d.upUserIntegralSQL = d.db.Prepared(_upUserIntegralSQL)
d.orderUserSyncSQL = d.db.Prepared(_orderUserSyncSQL)
d.bindAllSQL = d.db.Prepared(_bindAllSQL)
d.userBindSQL = d.db.Prepared(_userBindSQL)
d.ipSyncSQL = d.db.Prepared(_ipSyncSQL)
d.inUserPackLogSQL = d.db.Prepared(_inUserPackLogSQL)
d.inUserIntegralLogSQL = d.db.Prepared(_inUserIntegralLogSQL)
return
}
// UpUserIntegral update unicom user integral
func (d *Dao) UpUserIntegral(ctx context.Context, ub *unicom.UserBind) (row int64, err error) {
res, err := d.upUserIntegralSQL.Exec(ctx, ub.Integral, ub.Flow, ub.Monthly, ub.Mid)
if err != nil {
log.Error("update user integral sql error(%v)", err)
return 0, err
}
return res.RowsAffected()
}
// OrdersUserFlow select user OrdersSync
func (d *Dao) OrdersUserFlow(ctx context.Context, usermob string) (res []*unicom.Unicom, err error) {
rows, err := d.orderUserSyncSQL.Query(ctx, usermob)
if err != nil {
log.Error("query error (%v)", err)
return
}
defer rows.Close()
for rows.Next() {
u := &unicom.Unicom{}
if err = rows.Scan(&u.Usermob, &u.Spid, &u.TypeInt, &u.Ordertime, &u.Endtime); err != nil {
log.Error("OrdersUserFlow row.Scan err (%v)", err)
return
}
res = append(res, u)
}
return
}
//BindAll select bind all mid state 1
func (d *Dao) BindAll(ctx context.Context, start, end int) (res []*unicom.UserBind, err error) {
rows, err := d.bindAllSQL.Query(ctx, start, end)
if err != nil {
log.Error("query error (%v)", err)
return
}
defer rows.Close()
for rows.Next() {
u := &unicom.UserBind{}
if err = rows.Scan(&u.Mid, &u.Usermob, &u.Monthly); err != nil {
log.Error("BindAll rows.Scan error(%v)", err)
return
}
res = append(res, u)
}
return
}
// UserBind unicom select user bind
func (d *Dao) UserBind(ctx context.Context, mid int64) (res *unicom.UserBind, err error) {
row := d.userBindSQL.QueryRow(ctx, mid)
if row == nil {
log.Error("userBindSQL is null")
return
}
res = &unicom.UserBind{}
if err = row.Scan(&res.Usermob, &res.Phone, &res.Mid, &res.State, &res.Integral, &res.Flow, &res.Monthly); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("userBindSQL row.Scan error(%v)", err)
}
res = nil
return
}
return
}
// InUnicomIPSync insert or update unicom_ip
func (d *Dao) InUnicomIPSync(tx *xsql.Tx, u *unicom.UnicomIP, now time.Time) (row int64, err error) {
res, err := tx.Exec(_inUnicomIPSyncSQL, u.Ipbegin, u.Ipend, 1, now, now,
u.Ipbegin, u.Ipend, 1, now)
if err != nil {
log.Error("tx.inUnicomIPSyncSQL.Exec error(%v)", err)
return 0, err
}
return res.RowsAffected()
}
// UpUnicomIP update unicom_ip state
func (d *Dao) UpUnicomIP(tx *xsql.Tx, ipstart, ipend, state int, now time.Time) (row int64, err error) {
res, err := tx.Exec(_upUnicomIPSQL, state, now, ipstart, ipend)
if err != nil {
log.Error("tx.upUnicomIPSQL.Exec error(%v)", err)
return 0, err
}
return res.RowsAffected()
}
// IPSync select all ipSync
func (d *Dao) IPSync(ctx context.Context) (res []*unicom.UnicomIP, err error) {
rows, err := d.ipSyncSQL.Query(ctx)
if err != nil {
log.Error("query error (%v)", err)
return
}
defer rows.Close()
res = []*unicom.UnicomIP{}
for rows.Next() {
u := &unicom.UnicomIP{}
if err = rows.Scan(&u.Ipbegin, &u.Ipend); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
u.UnicomIPChange()
res = append(res, u)
}
return
}
// InUserPackLog insert unicom user pack log
func (d *Dao) InUserPackLog(ctx context.Context, u *unicom.UserPackLog) (row int64, err error) {
res, err := d.inUserPackLogSQL.Exec(ctx, u.Phone, u.Usermob, u.Mid, u.RequestNo, u.Type, u.Integral, u.Desc)
if err != nil {
log.Error("insert user pack log integral sql error(%v)", err)
return 0, err
}
return res.RowsAffected()
}
// InUserIntegralLog insert unicom user add integral and flow log
func (d *Dao) InUserIntegralLog(ctx context.Context, u *unicom.UserIntegralLog) (row int64, err error) {
res, err := d.inUserIntegralLogSQL.Exec(ctx, u.Phone, u.Mid, u.UnicomDesc, u.Type, u.Integral, u.Flow, u.Desc)
if err != nil {
log.Error("insert user add integral and flow sql error(%v)", err)
return 0, err
}
return res.RowsAffected()
}
// BeginTran begin a transacition
func (d *Dao) BeginTran(ctx context.Context) (tx *xsql.Tx, err error) {
return d.db.Begin(ctx)
}

View File

@@ -0,0 +1,108 @@
package unicom
import (
"context"
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/job/main/app-wall/conf"
"go-common/app/job/main/app-wall/model/unicom"
. "github.com/smartystreets/goconvey/convey"
)
var (
d *Dao
)
func ctx() context.Context {
return context.Background()
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-wall-job-test.toml")
flag.Set("conf", dir)
conf.Init()
d = New(conf.Conf)
time.Sleep(time.Second)
}
func TestUpUserIntegral(t *testing.T) {
Convey("UpUserIntegral", t, func() {
res, err := d.UpUserIntegral(ctx(), &unicom.UserBind{})
So(err, ShouldBeNil)
So(res, ShouldNotBeEmpty)
})
}
func TestOrdersUserFlow(t *testing.T) {
Convey("OrdersUserFlow", t, func() {
res, err := d.OrdersUserFlow(ctx(), "")
So(err, ShouldBeNil)
So(res, ShouldNotBeEmpty)
})
}
func TestBindAll(t *testing.T) {
Convey("BindAll", t, func() {
res, err := d.BindAll(ctx(), 1, 1)
So(err, ShouldBeNil)
So(res, ShouldNotBeEmpty)
})
}
func TestUserBind(t *testing.T) {
Convey("UserBind", t, func() {
res, err := d.UserBind(ctx(), 1)
So(err, ShouldBeNil)
So(res, ShouldNotBeEmpty)
})
}
func TestIPSync(t *testing.T) {
Convey("IPSync", t, func() {
res, err := d.IPSync(ctx())
So(err, ShouldBeNil)
So(res, ShouldNotBeEmpty)
})
}
func TestInUserPackLog(t *testing.T) {
Convey("InUserPackLog", t, func() {
res, err := d.InUserPackLog(ctx(), nil)
So(err, ShouldBeNil)
So(res, ShouldNotBeEmpty)
})
}
func TestInUserIntegralLog(t *testing.T) {
Convey("InUserIntegralLog", t, func() {
res, err := d.InUserIntegralLog(ctx(), nil)
So(err, ShouldBeNil)
So(res, ShouldNotBeEmpty)
})
}
func TestUserBindCache(t *testing.T) {
Convey("UserBindCache", t, func() {
res, err := d.UserBindCache(ctx(), 1)
So(err, ShouldBeNil)
So(res, ShouldNotBeEmpty)
})
}
func TestAddUserBindCache(t *testing.T) {
Convey("AddUserBindCache", t, func() {
err := d.AddUserBindCache(ctx(), 1, nil)
So(err, ShouldBeNil)
})
}
func TestDeleteUserPackReceiveCache(t *testing.T) {
Convey("DeleteUserPackReceiveCache", t, func() {
err := d.DeleteUserPackReceiveCache(ctx(), 1)
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,35 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["http.go"],
importpath = "go-common/app/job/main/app-wall/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/app-wall/conf:go_default_library",
"//app/job/main/app-wall/service/offer:go_default_library",
"//app/job/main/app-wall/service/unicom: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,54 @@
package http
import (
"net/http"
"go-common/app/job/main/app-wall/conf"
"go-common/app/job/main/app-wall/service/offer"
"go-common/app/job/main/app-wall/service/unicom"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
)
var (
offerSvc *offer.Service
unicomSvc *unicom.Service
)
// Init init
func Init(c *conf.Config) {
initService(c)
// init router
engineInner := bm.DefaultServer(c.BM.Inner)
outerRouter(engineInner)
if err := engineInner.Start(); err != nil {
log.Error("bm.DefaultServer error(%v)", err)
panic(err)
}
}
// initService init services.
func initService(c *conf.Config) {
offerSvc = offer.New(c)
unicomSvc = unicom.New(c)
}
// Close
func Close() {
offerSvc.Close()
unicomSvc.Close()
}
// outerRouter init outer router api path.
func outerRouter(e *bm.Engine) {
//init api
e.Ping(ping)
}
// ping check server ok.
func ping(c *bm.Context) {
if err := offerSvc.Ping(c); err != nil {
log.Error("app-wall-job service ping error(%+v)", err)
c.AbortWithStatus(http.StatusServiceUnavailable)
}
}

View File

@@ -0,0 +1,32 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["const.go"],
importpath = "go-common/app/job/main/app-wall/model",
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/job/main/app-wall/model/offer:all-srcs",
"//app/job/main/app-wall/model/unicom:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,35 @@
package model
import "net"
const (
TypeIOS = "ios"
TypeAndriod = "android"
)
// InetAtoN conver ip addr to uint32.
func InetAtoN(s string) (sum uint32) {
ip := net.ParseIP(s)
if ip == nil {
return
}
ip = ip.To4()
if ip == nil {
return
}
sum += uint32(ip[0]) << 24
sum += uint32(ip[1]) << 16
sum += uint32(ip[2]) << 8
sum += uint32(ip[3])
return sum
}
// InetNtoA conver uint32 to ip addr.
func InetNtoA(sum uint32) string {
ip := make(net.IP, net.IPv4len)
ip[0] = byte((sum >> 24) & 0xFF)
ip[1] = byte((sum >> 16) & 0xFF)
ip[2] = byte((sum >> 8) & 0xFF)
ip[3] = byte(sum & 0xFF)
return ip.String()
}

View File

@@ -0,0 +1,31 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"message.go",
"retry.go",
],
importpath = "go-common/app/job/main/app-wall/model/offer",
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,8 @@
package offer
type ActiveMsg struct {
OS string `json:"os,omitempty"`
IMEI string `json:"imei,omitempty"`
Androidid string `json:"androidid,omitempty"`
Mac string `json:"mac,omitempty"`
}

View File

@@ -0,0 +1,17 @@
package offer
const (
ActionActive = "active"
)
type Retry struct {
Action string `json:"action,omitempty"`
Data *Data `json:"data,omitempty"`
}
type Data struct {
OS string `json:"os,omitempty"`
IMEI string `json:"imei,omitempty"`
Androidid string `json:"androidid,omitempty"`
Mac string `json:"mac,omitempty"`
}

View File

@@ -0,0 +1,32 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["unicom.go"],
importpath = "go-common/app/job/main/app-wall/model/unicom",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/app-wall/model:go_default_library",
"//library/time:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,140 @@
package unicom
import (
"fmt"
"strconv"
"strings"
"time"
"go-common/app/job/main/app-wall/model"
xtime "go-common/library/time"
)
type UserBind struct {
Usermob string `json:"usermob,omitempty"`
Phone int `json:"phone"`
Mid int64 `json:"mid"`
State int `json:"state,omitempty"`
Integral int `json:"integral"`
Flow int `json:"flow"`
Monthly time.Time `json:"monthly"`
}
// type
type ClickMsg struct {
Plat int8
AID int64
MID int64
Lv int8
BvID string
CTime int64
STime int64
IP string
KafkaBs []byte
EpID int64
SeasonType int
UserAgent string
}
type Unicom struct {
Usermob string `json:"-"`
Spid int `json:"spid"`
TypeInt int `json:"type"`
Ordertime xtime.Time `json:"ordertime"`
Endtime xtime.Time `json:"endtime,omitempty"`
}
type UnicomUserFlow struct {
Phone int `json:"phone"`
Mid int64 `json:"mid"`
Integral int `json:"integral"`
Flow int `json:"flow"`
Outorderid string `json:"outorderid"`
Orderid string `json:"orderid"`
Desc string `json:"desc"`
}
type UnicomIP struct {
Ipbegin int `json:"-"`
Ipend int `json:"-"`
IPStartUint uint32 `json:"-"`
IPEndUint uint32 `json:"-"`
}
type UserPackLog struct {
Phone int `json:"-"`
Usermob string `json:"-"`
Mid int64 `json:"-"`
RequestNo string `json:"-"`
Type int `json:"-"`
Desc string `json:"-"`
Integral int `json:"-"`
}
type UserIntegralLog struct {
Phone int `json:"-"`
Mid int64 `json:"-"`
UnicomDesc string `json:"-"`
Type int `json:"-"`
Integral int `json:"-"`
Flow int `json:"-"`
Desc string `json:"-"`
}
func (u *UnicomIP) UnicomIPStrToint(ipstart, ipend string) {
u.Ipbegin = ipToInt(ipstart)
u.Ipend = ipToInt(ipend)
}
// ipToint
func ipToInt(ipString string) (ipInt int) {
tmp := strings.Split(ipString, ".")
if len(tmp) < 4 {
return
}
var ipStr string
for _, tip := range tmp {
var (
ipLen = len(tip)
last int
ip1 string
)
if ipLen < 3 {
last = 3 - ipLen
switch last {
case 1:
ip1 = "0" + tip
case 2:
ip1 = "00" + tip
case 3:
ip1 = "000"
}
} else {
ip1 = tip
}
ipStr = ipStr + ip1
}
ipInt, _ = strconv.Atoi(ipStr)
return
}
func (u *UnicomIP) UnicomIPChange() {
u.IPStartUint = u.unicomIPTOUint(u.Ipbegin)
u.IPEndUint = u.unicomIPTOUint(u.Ipend)
}
func (u *UnicomIP) unicomIPTOUint(ip int) (ipUnit uint32) {
var (
ip1, ip2, ip3, ip4 int
ipStr string
)
var _initIP = "%d.%d.%d.%d"
ip1 = ip / 1000000000
ip2 = (ip / 1000000) % 1000
ip3 = (ip / 1000) % 1000
ip4 = ip % 1000
ipStr = fmt.Sprintf(_initIP, ip1, ip2, ip3, ip4)
ipUnit = model.InetAtoN(ipStr)
return
}

View File

@@ -0,0 +1,60 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"active_test.go",
"retry_test.go",
"service_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/app-wall/conf:go_default_library",
"//app/job/main/app-wall/model/offer:go_default_library",
"//vendor/github.com/bsm/sarama-cluster:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"active.go",
"retry.go",
"service.go",
],
importpath = "go-common/app/job/main/app-wall/service/offer",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/app-wall/conf:go_default_library",
"//app/job/main/app-wall/dao/offer:go_default_library",
"//app/job/main/app-wall/model:go_default_library",
"//app/job/main/app-wall/model/offer:go_default_library",
"//library/log:go_default_library",
"//vendor/github.com/Shopify/sarama:go_default_library",
"//vendor/github.com/bsm/sarama-cluster: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,113 @@
package offer
import (
"context"
"fmt"
"strconv"
"strings"
"go-common/app/job/main/app-wall/model"
"go-common/app/job/main/app-wall/model/offer"
"go-common/library/log"
)
func (s *Service) activeConsumer() {
defer s.waiter.Done()
LOOP:
for {
select {
case err := <-s.consumer.Errors():
log.Error("group(%s) topic(%s) addr(%s) catch error(%+v)", s.c.Consumer.Group, s.c.Consumer.Topic, s.c.Consumer.Brokers, err)
continue
case notify := <-s.consumer.Notifications():
log.Info("notification(%v)", notify)
continue
case msg, ok := <-s.consumer.Messages():
if !ok {
log.Error("active consumer exit!")
break LOOP
}
s.consumer.MarkOffset(msg, "")
active, err := s.checkMsgIllegal(msg.Value)
if err != nil {
log.Error("s.checkMsgIllegal(%s) error(%v)", msg.Value, err)
continue
}
if active == nil {
continue
}
s.activeChan <- active
}
}
}
func (s *Service) checkMsgIllegal(msg []byte) (active *offer.ActiveMsg, err error) {
var (
msgs []string
pid int64
os string
androidid string
imei string
)
msgs = strings.Split(string(msg), "|")
if len(msgs) < 9 {
err = fmt.Errorf("active msg(%s) split len(%d)<9", msg, len(msgs))
return
}
if pid, err = strconv.ParseInt(msgs[8], 10, 64); err != nil {
return
}
if pid%10 == 3 {
os = model.TypeAndriod
if len(msgs) > 22 {
androidid = msgs[22]
}
if len(msgs) > 23 {
imei = msgs[23]
}
if imei == "" {
log.Warn("active msg(%s) imei(%s) is illegal", msg, imei)
} else {
log.Warn("active msg(%s) imei(%s) is legal", msg, imei)
}
if androidid == "" {
log.Warn("active msg(%s) androidid(%s) is illegal", msg, androidid)
}
if androidid == "" && imei == "" {
err = fmt.Errorf("active msg(%s) androidid(%s) and imei(%s) is illegal", msg, androidid, imei)
return
}
} else {
err = fmt.Errorf("active msg(%s) pid(%d) platform not android", msg, pid)
return
}
active = &offer.ActiveMsg{OS: os, IMEI: imei, Androidid: androidid, Mac: ""}
return
}
func (s *Service) activeproc() {
defer s.waiter.Done()
for {
msg, ok := <-s.activeChan
if !ok {
log.Error("active chan id closed")
break
}
s.active(msg)
}
}
func (s *Service) active(msg *offer.ActiveMsg) {
var err error
c := context.TODO()
if err = retry(func() (err error) {
return s.dao.Active(c, msg.OS, msg.IMEI, msg.Androidid, msg.Mac, "")
}, _upActiveRetry, _sleep); err != nil {
log.Error("%+v", err)
if err = s.syncRetry(c, offer.ActionActive, msg.OS, msg.IMEI, msg.Androidid, msg.Mac); err != nil {
log.Error("%+v", err)
}
return
}
log.Info("active device os(%s) imei(%s) androidid(%s) mac(%s) success", msg.OS, msg.IMEI, msg.Androidid, msg.Mac)
}

View File

@@ -0,0 +1,81 @@
package offer
import (
"reflect"
"testing"
"go-common/app/job/main/app-wall/model/offer"
)
func TestService_activeConsumer(t *testing.T) {
tests := []struct {
name string
s *Service
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.s.activeConsumer()
})
}
}
func TestService_checkMsgIllegal(t *testing.T) {
type args struct {
msg []byte
}
tests := []struct {
name string
s *Service
args args
wantActive *offer.ActiveMsg
wantErr bool
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotActive, err := tt.s.checkMsgIllegal(tt.args.msg)
if (err != nil) != tt.wantErr {
t.Errorf("Service.checkMsgIllegal() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(gotActive, tt.wantActive) {
t.Errorf("Service.checkMsgIllegal() = %v, want %v", gotActive, tt.wantActive)
}
})
}
}
func TestService_activeproc(t *testing.T) {
tests := []struct {
name string
s *Service
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.s.activeproc()
})
}
}
func TestService_active(t *testing.T) {
type args struct {
msg *offer.ActiveMsg
}
tests := []struct {
name string
s *Service
args args
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.s.active(tt.args.msg)
})
}
}

View File

@@ -0,0 +1,72 @@
package offer
import (
"context"
"encoding/json"
"time"
"go-common/app/job/main/app-wall/model/offer"
"go-common/library/log"
)
const (
_upActiveRetry = 5
_sleep = 100 * time.Millisecond
)
func (s *Service) retryproc() {
defer s.waiter.Done()
var (
bs []byte
err error
)
c := context.TODO()
msg := &offer.Retry{}
for {
if s.closed {
break
}
if bs, err = s.dao.PopFail(c); err != nil {
time.Sleep(5 * time.Second)
continue
}
if len(bs) == 0 {
time.Sleep(5 * time.Second)
continue
}
if err = json.Unmarshal(bs, msg); err != nil {
log.Error("json.Unmarshal(%s) error(%v)", bs, err)
continue
}
log.Info("retry action(%s) data(%s)", msg.Action, bs)
switch msg.Action {
case offer.ActionActive:
if msg.Data != nil {
if err = retry(func() (err error) {
return s.dao.Active(c, msg.Data.OS, msg.Data.IMEI, msg.Data.Androidid, msg.Data.Mac, "")
}, _upActiveRetry, _sleep); err != nil {
log.Error("%+v", err)
if err = s.syncRetry(c, offer.ActionActive, msg.Data.OS, msg.Data.IMEI, msg.Data.Androidid, msg.Data.Mac); err != nil {
log.Error("%+v", err)
}
return
}
}
}
}
}
func retry(callback func() error, retry int, sleep time.Duration) (err error) {
for i := 0; i < retry; i++ {
if err = callback(); err == nil {
return
}
time.Sleep(sleep)
}
return
}
func (s *Service) syncRetry(c context.Context, action, os, imei, androidid, mac string) (err error) {
retry := &offer.Retry{Action: action, Data: &offer.Data{OS: os, IMEI: imei, Androidid: androidid, Mac: mac}}
return s.dao.PushFail(c, retry)
}

View File

@@ -0,0 +1,69 @@
package offer
import (
"context"
"testing"
"time"
)
func TestService_retryproc(t *testing.T) {
tests := []struct {
name string
s *Service
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.s.retryproc()
})
}
}
func Test_retry(t *testing.T) {
type args struct {
callback func() error
retry int
sleep time.Duration
}
tests := []struct {
name string
args args
wantErr bool
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := retry(tt.args.callback, tt.args.retry, tt.args.sleep); (err != nil) != tt.wantErr {
t.Errorf("retry() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestService_syncRetry(t *testing.T) {
type args struct {
c context.Context
action string
os string
imei string
androidid string
mac string
}
tests := []struct {
name string
s *Service
args args
wantErr bool
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := tt.s.syncRetry(tt.args.c, tt.args.action, tt.args.os, tt.args.imei, tt.args.androidid, tt.args.mac); (err != nil) != tt.wantErr {
t.Errorf("Service.syncRetry() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}

View File

@@ -0,0 +1,88 @@
package offer
import (
"context"
"strings"
"sync"
"time"
"go-common/app/job/main/app-wall/conf"
offerDao "go-common/app/job/main/app-wall/dao/offer"
"go-common/app/job/main/app-wall/model/offer"
"go-common/library/log"
"github.com/Shopify/sarama"
cluster "github.com/bsm/sarama-cluster"
)
// Service struct
type Service struct {
c *conf.Config
dao *offerDao.Dao
consumer *cluster.Consumer
activeChan chan *offer.ActiveMsg
closed bool
waiter sync.WaitGroup
}
// New init
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
dao: offerDao.New(c),
activeChan: make(chan *offer.ActiveMsg, 10240),
closed: false,
}
var err error
if s.consumer, err = s.NewConsumer(); err != nil {
log.Error("%+v", err)
panic(err)
}
s.waiter.Add(1)
go s.activeConsumer()
s.waiter.Add(1)
go s.activeproc()
// retry consumer
for i := 0; i < 4; i++ {
s.waiter.Add(1)
go s.retryproc()
}
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.closed = true
s.consumer.Close()
s.waiter.Wait()
log.Info("app-wall-job closed.")
}
// NewConsumer new cluster consumer.
func (s *Service) NewConsumer() (*cluster.Consumer, error) {
// cluster config
cfg := cluster.NewConfig()
// NOTE cluster auto commit offset interval
cfg.Consumer.Offsets.CommitInterval = time.Second * 1
// NOTE set fetch.wait.max.ms
cfg.Consumer.MaxWaitTime = time.Millisecond * 100
// NOTE errors that occur during offset management,if enabled, c.Errors channel must be read
cfg.Consumer.Return.Errors = true
// NOTE notifications that occur during consumer, if enabled, c.Notifications channel must be read
cfg.Group.Return.Notifications = true
// The initial offset to use if no offset was previously committed.
// default: OffsetOldest
if strings.ToLower(s.c.Consumer.Offset) != "new" {
cfg.Consumer.Offsets.Initial = sarama.OffsetOldest
} else {
cfg.Consumer.Offsets.Initial = sarama.OffsetNewest
}
// new cluster consumer
log.Info("s.c.Consumer.Brokers: %v", s.c.Consumer.Brokers)
return cluster.NewConsumer(s.c.Consumer.Brokers, s.c.Consumer.Group, []string{s.c.Consumer.Topic}, cfg)
}

View File

@@ -0,0 +1,98 @@
package offer
import (
"context"
"flag"
"path/filepath"
"reflect"
"testing"
"go-common/app/job/main/app-wall/conf"
cluster "github.com/bsm/sarama-cluster"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func init() {
dir, _ := filepath.Abs("../../cmd/app-wall-job-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
}
func TestNew(t *testing.T) {
type args struct {
c *conf.Config
}
tests := []struct {
name string
args args
wantS *Service
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if gotS := New(tt.args.c); !reflect.DeepEqual(gotS, tt.wantS) {
t.Errorf("New() = %v, want %v", gotS, tt.wantS)
}
})
}
}
func TestService_Ping(t *testing.T) {
type args struct {
c context.Context
}
tests := []struct {
name string
s *Service
args args
wantErr bool
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := tt.s.Ping(tt.args.c); (err != nil) != tt.wantErr {
t.Errorf("Service.Ping() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestService_Close(t *testing.T) {
tests := []struct {
name string
s *Service
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.s.Close()
})
}
}
func TestService_NewConsumer(t *testing.T) {
tests := []struct {
name string
s *Service
want *cluster.Consumer
wantErr error
}{
// TODO: Add test cases.
}
for _, tt := range tests {
Convey(tt.name, t, func() {
got, err := tt.s.NewConsumer()
So(err, ShouldEqual, tt.wantErr)
So(got, ShouldResemble, tt.want)
})
}
}

View File

@@ -0,0 +1,59 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["unicom_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/app-wall/conf:go_default_library",
"//app/job/main/app-wall/model/unicom:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"infoc.go",
"service.go",
"unicom.go",
],
importpath = "go-common/app/job/main/app-wall/service/unicom",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/app-wall/conf:go_default_library",
"//app/job/main/app-wall/dao/seq:go_default_library",
"//app/job/main/app-wall/dao/unicom:go_default_library",
"//app/job/main/app-wall/model/unicom:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/log/infoc:go_default_library",
"//library/queue/databus:go_default_library",
"//library/queue/databus/report:go_default_library",
"//library/stat/prom:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,88 @@
package unicom
import (
"strconv"
"time"
"go-common/app/job/main/app-wall/conf"
"go-common/library/log"
binfoc "go-common/library/log/infoc"
)
type infoc struct {
usermob string
phone string
mid string
leve string
integral string
flow string
unicomtype string
now string
}
type packInfoc struct {
usermob string
phone string
mid string
requestNo string
packName string
packIntegral string
packType string
now string
}
// unicomInfoc unicom user infoc
func (s *Service) unicomInfoc(usermob string, phone, leve, integral, flow int, utype string, mid int64, now time.Time) {
select {
case s.logCh[mid%s.c.ChanDBNum] <- infoc{usermob, strconv.Itoa(phone), strconv.FormatInt(mid, 10),
strconv.Itoa(leve), strconv.Itoa(integral), strconv.Itoa(flow), utype, strconv.FormatInt(now.Unix(), 10)}:
default:
log.Warn("unicomInfoc log buffer is full")
}
}
func (s *Service) unicomInfocproc(i int64) {
var (
cliChan = s.logCh[i]
packinf = binfoc.New(conf.Conf.UnicomUserInfoc2)
)
for {
i, ok := <-cliChan
if !ok {
log.Warn("infoc proc exit")
return
}
switch v := i.(type) {
case infoc:
packinf.Info(v.now, "0", v.usermob, v.phone, v.mid, v.leve, v.integral, v.flow, v.unicomtype)
log.Info("unicomInfocproc log mid(%v) phone(%v)", v.mid, v.phone)
}
}
}
// unicomPackInfoc unicom pack infoc
func (s *Service) unicomPackInfoc(usermob, packName, orderNumber string, phone, packIntegral, packType int, mid int64, now time.Time) {
select {
case s.packCh <- packInfoc{usermob, strconv.Itoa(phone), strconv.FormatInt(mid, 10),
orderNumber, packName, strconv.Itoa(packIntegral), strconv.Itoa(packType), strconv.FormatInt(now.Unix(), 10)}:
default:
log.Warn("unicomPackInfoc log buffer is full")
}
}
func (s *Service) unicomPackInfocproc() {
var (
packinf = binfoc.New(conf.Conf.UnicomPackInfoc)
)
for {
i, ok := <-s.packCh
if !ok {
log.Warn("infoc proc exit")
return
}
switch v := i.(type) {
case packInfoc:
packinf.Info(v.now, "0", v.usermob, v.phone, v.mid, v.requestNo, v.packName, v.packIntegral, v.packType)
}
}
}

View File

@@ -0,0 +1,122 @@
package unicom
import (
"sync"
"time"
"go-common/app/job/main/app-wall/conf"
seqDao "go-common/app/job/main/app-wall/dao/seq"
unicomDao "go-common/app/job/main/app-wall/dao/unicom"
"go-common/app/job/main/app-wall/model/unicom"
"go-common/library/log"
"go-common/library/queue/databus"
"go-common/library/stat/prom"
)
type Service struct {
c *conf.Config
dao *unicomDao.Dao
seqdao *seqDao.Dao
clickSub *databus.Databus
closed bool
// waiter
waiter sync.WaitGroup
cliChan []chan *unicom.ClickMsg
dbcliChan []chan *unicom.UserBind
// infoc
logCh []chan interface{}
packCh chan interface{}
packLogCh chan interface{}
integralLogCh []chan interface{}
// prom
pHit *prom.Prom
pMiss *prom.Prom
// tick
tick time.Duration
lastmonth map[int]bool
}
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
dao: unicomDao.New(c),
clickSub: databus.New(c.ReportDatabus),
seqdao: seqDao.New(c),
// infoc
packCh: make(chan interface{}, 1024),
packLogCh: make(chan interface{}, 1024),
// close
closed: false,
// prom
pHit: prom.CacheHit,
pMiss: prom.CacheMiss,
lastmonth: map[int]bool{},
// tick
tick: time.Duration(c.Tick),
}
for i := int64(0); i < s.c.ChanNum; i++ {
s.cliChan = append(s.cliChan, make(chan *unicom.ClickMsg, 300000))
}
for i := int64(0); i < s.c.ChanDBNum; i++ {
s.dbcliChan = append(s.dbcliChan, make(chan *unicom.UserBind, 1024))
s.integralLogCh = append(s.integralLogCh, make(chan interface{}, 1024))
s.logCh = append(s.logCh, make(chan interface{}, 1024))
}
for i := int64(0); i < s.c.ChanNum; i++ {
s.waiter.Add(1)
go s.cliChanProc(i)
}
for i := int64(0); i < s.c.ChanDBNum; i++ {
s.waiter.Add(1)
go s.unicomInfocproc(i)
go s.addUserIntegralLogproc(i)
}
for i := int64(0); i < s.c.ChanDBNum; i++ {
s.waiter.Add(1)
go s.dbcliChanProc(i)
}
s.waiter.Add(1)
go s.clickConsumer()
s.waiter.Add(1)
now := time.Now()
if s.c.Monthly {
// s.updatemonth(now)
s.upBindAll()
}
s.waiter.Add(1)
s.loadUnicomIPOrder(now)
s.loadUnicomFlow()
go s.loadproc()
s.waiter.Add(1)
go s.unicomPackInfocproc()
go s.addUserPackLogproc()
return
}
// Close Service
func (s *Service) Close() {
s.closed = true
time.Sleep(time.Second * 2)
s.clickSub.Close()
for i := 0; i < len(s.cliChan); i++ {
close(s.cliChan[i])
}
for i := 0; i < len(s.dbcliChan); i++ {
close(s.dbcliChan[i])
close(s.integralLogCh[i])
close(s.logCh[i])
}
s.waiter.Wait()
log.Info("app-wall-job unicom flow closed.")
}
// cacheproc load cache
func (s *Service) loadproc() {
for {
time.Sleep(s.tick)
now := time.Now()
s.loadUnicomFlow()
s.updatemonth(now)
s.loadUnicomIPOrder(now)
}
}

View File

@@ -0,0 +1,653 @@
package unicom
import (
"context"
"encoding/json"
"errors"
"fmt"
"strconv"
"strings"
"time"
"go-common/app/job/main/app-wall/model/unicom"
"go-common/library/cache/memcache"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/queue/databus/report"
)
const (
_initIPUnicomKey = "ipunicom_%v_%v"
)
func (s *Service) clickConsumer() {
defer s.waiter.Done()
msgs := s.clickSub.Messages()
for {
msg, ok := <-msgs
if !ok || s.closed {
log.Info("s.clickSub.Cloesd")
return
}
msg.Commit()
var (
sbs [][]byte
err error
)
if err = json.Unmarshal(msg.Value, &sbs); err != nil {
log.Error("json.Unmarshal(%v) error(%v)", msg.Value, err)
continue
}
for _, bs := range sbs {
var (
err error
click *unicom.ClickMsg
)
if click, err = s.checkMsgIllegal(bs); err != nil {
log.Error("s.checkMsgIllegal(%s) error(%v)", strings.Replace(string(bs), "\001", "|", -1), err)
continue
}
log.Info("clickConsumer s.checkMsgIllegal(%s)", strings.Replace(string(bs), "\001", "|", -1))
s.cliChan[click.AID%s.c.ChanNum] <- click
}
}
}
func (s *Service) checkMsgIllegal(msg []byte) (click *unicom.ClickMsg, err error) {
var (
aid int64
clickMsg []string
plat int64
bvID string
mid int64
lv int64
ctime int64
stime int64
epid int64
ip string
seasonType int
userAgent string
)
clickMsg = strings.Split(string(msg), "\001")
if len(clickMsg) < 10 {
err = errors.New("click msg error")
return
}
if aid, err = strconv.ParseInt(clickMsg[1], 10, 64); err != nil {
err = fmt.Errorf("aid(%s) error", clickMsg[1])
return
}
if aid <= 0 {
err = fmt.Errorf("wocao aid(%s) error", clickMsg[1])
return
}
if plat, err = strconv.ParseInt(clickMsg[0], 10, 64); err != nil {
err = fmt.Errorf("plat(%s) error", clickMsg[0])
return
}
if plat != 3 && plat != 4 {
err = fmt.Errorf("plat(%d) is not android or ios", plat)
return
}
userAgent = clickMsg[10]
bvID = clickMsg[8]
if bvID == "" {
err = fmt.Errorf("bvID(%s) is illegal", clickMsg[8])
return
}
if clickMsg[4] != "" && clickMsg[4] != "0" {
if mid, err = strconv.ParseInt(clickMsg[4], 10, 64); err != nil {
err = fmt.Errorf("mid(%s) is illegal", clickMsg[4])
return
}
}
if clickMsg[5] != "" {
if lv, err = strconv.ParseInt(clickMsg[5], 10, 64); err != nil {
err = fmt.Errorf("lv(%s) is illegal", clickMsg[5])
return
}
}
if ctime, err = strconv.ParseInt(clickMsg[6], 10, 64); err != nil {
err = fmt.Errorf("ctime(%s) is illegal", clickMsg[6])
return
}
if stime, err = strconv.ParseInt(clickMsg[7], 10, 64); err != nil {
err = fmt.Errorf("stime(%s) is illegal", clickMsg[7])
return
}
if ip = clickMsg[9]; ip == "" {
err = errors.New("ip is illegal")
return
}
if clickMsg[17] != "" {
if epid, err = strconv.ParseInt(clickMsg[17], 10, 64); err != nil {
err = fmt.Errorf("epid(%s) is illegal", clickMsg[17])
return
}
if clickMsg[15] != "null" {
if seasonType, err = strconv.Atoi(clickMsg[15]); err != nil {
err = fmt.Errorf("seasonType(%s) is illegal", clickMsg[15])
return
}
}
}
click = &unicom.ClickMsg{
Plat: int8(plat),
AID: aid,
MID: mid,
Lv: int8(lv),
CTime: ctime,
STime: stime,
BvID: bvID,
IP: ip,
KafkaBs: msg,
EpID: epid,
SeasonType: seasonType,
UserAgent: userAgent,
}
return
}
func (s *Service) cliChanProc(i int64) {
defer s.waiter.Done()
var (
cli *unicom.ClickMsg
cliChan = s.cliChan[i]
)
for {
var (
ub *unicom.UserBind
c = context.TODO()
err error
ok bool
count int
addFlow int
now = time.Now()
u *unicom.Unicom
cardType string
)
if cli, ok = <-cliChan; !ok || s.closed {
return
}
if count, err = s.dao.UserPackReceiveCache(c, cli.MID); err != nil {
log.Error("s.dao.UserBindCache error(%v) mid(%v) count(%v)", err, cli.MID, count)
continue
}
if count > 0 {
log.Info("s.dao.UserBindCache mid(%v) count(%v)", cli.MID, count)
continue
}
if ub, err = s.dao.UserBindCache(c, cli.MID); err != nil {
continue
}
if ub == nil || ub.Phone == 0 {
continue
}
res := s.unicomInfo(c, ub.Usermob, now)
if u, ok = res[ub.Usermob]; !ok || u == nil {
continue
}
switch u.Spid {
case 10019:
cardType = "22卡"
case 10020:
cardType = "33卡"
case 10021:
cardType = "小电视卡"
default:
log.Info("unicom spid equal 979 (%v)", ub)
continue
}
ub.Integral = ub.Integral + 10
switch cli.Lv {
case 0, 1, 2, 3:
addFlow = 10
case 4:
addFlow = 15
case 5:
addFlow = 20
case 6:
addFlow = 30
}
ub.Flow = ub.Flow + addFlow
if err = s.dao.AddUserBindCache(c, ub.Mid, ub); err != nil {
log.Error("s.dao.AddUserBindCache error(%v)", err)
continue
}
if err = s.dao.AddUserPackReceiveCache(c, ub.Mid, 1, now); err != nil {
log.Error("s.dao.AddUserPackReceiveCache error(%v)", err)
continue
}
s.dbcliChan[ub.Mid%s.c.ChanDBNum] <- ub
log.Info("unicom mobile cliChanProc userbind(%v)", ub)
s.unicomInfoc(ub.Usermob, ub.Phone, int(cli.Lv), 10, addFlow, cardType, ub.Mid, now)
s.addUserIntegralLog(&unicom.UserIntegralLog{Phone: ub.Phone, Mid: ub.Mid, UnicomDesc: cardType, Type: 0, Integral: 10, Flow: addFlow, Desc: "每日礼包"})
}
}
func (s *Service) dbcliChanProc(i int64) {
defer s.waiter.Done()
var (
ub *unicom.UserBind
dbcliChan = s.dbcliChan[i]
)
for {
var (
c = context.TODO()
ok bool
row int64
err error
)
if ub, ok = <-dbcliChan; !ok || s.closed {
return
}
if row, err = s.dao.UpUserIntegral(c, ub); err != nil || row == 0 {
log.Error("s.dao.UpUserIntegral ub(%v) error(%v) or result==0", ub, err)
continue
}
log.Info("unicom mobile dbcliChanProc userbind(%v)", ub)
}
}
// unicomInfo
func (s *Service) unicomInfo(c context.Context, usermob string, now time.Time) (res map[string]*unicom.Unicom) {
var (
err error
u []*unicom.Unicom
)
res = map[string]*unicom.Unicom{}
if u, err = s.dao.UnicomCache(c, usermob); err == nil && len(u) > 0 {
s.pHit.Incr("unicoms_cache")
} else {
if u, err = s.dao.OrdersUserFlow(context.TODO(), usermob); err != nil {
log.Error("unicom_s.dao.OrdersUserFlow error(%v)", err)
return
}
s.pMiss.Incr("unicoms_cache")
}
if len(u) > 0 {
row := &unicom.Unicom{}
for _, user := range u {
if user.TypeInt == 1 && now.Unix() <= int64(user.Endtime) {
*row = *user
break
} else if user.TypeInt == 0 {
if user.Spid == 979 {
continue
}
if int64(row.Ordertime) > int64(user.Ordertime) {
continue
}
*row = *user
}
}
if row.Spid == 0 {
return
}
res[usermob] = row
}
return
}
func (s *Service) upBindAll() {
var (
orders []*unicom.UserBind
err error
start = 0
end = 1000
)
for {
var tmp []*unicom.UserBind
if tmp, err = s.dao.BindAll(context.TODO(), start, end); err != nil {
log.Error("s.dao.BindAll error(%v)", err)
return
}
start = end + start
if len(tmp) == 0 {
break
}
orders = append(orders, tmp...)
}
for _, b := range orders {
var (
c = context.TODO()
u *unicom.Unicom
ok bool
now = time.Now()
integral int
ub *unicom.UserBind
err error
cardType string
)
if now.Month() == b.Monthly.Month() && now.Year() == b.Monthly.Year() {
continue
}
res := s.unicomInfo(c, b.Usermob, now)
if u, ok = res[b.Usermob]; !ok || u == nil {
continue
}
switch u.Spid {
case 10019:
integral = 220
cardType = "22卡"
case 10020:
integral = 330
cardType = "33卡"
case 10021:
integral = 660
cardType = "小电视卡"
default:
continue
}
if ub, err = s.dao.UserBindCache(c, b.Mid); err != nil {
continue
}
if ub == nil || ub.Phone == 0 {
continue
}
ub.Integral = ub.Integral + integral
ub.Monthly = now
if err = s.dao.AddUserBindCache(c, ub.Mid, ub); err != nil {
log.Error("s.dao.AddUserBindCache error(%v)", err)
continue
}
s.dbcliChan[ub.Mid%s.c.ChanDBNum] <- ub
log.Info("unicom mobile upBindAll userbind(%v)", ub)
s.unicomInfoc(ub.Usermob, ub.Phone, 0, integral, 0, cardType, ub.Mid, now)
s.addUserIntegralLog(&unicom.UserIntegralLog{Phone: ub.Phone, Mid: ub.Mid, UnicomDesc: cardType, Type: 1, Integral: integral, Flow: 0, Desc: "每月礼包"})
}
}
func (s *Service) updatemonth(now time.Time) {
m := int(now.Month())
if lmonth, ok := s.lastmonth[m]; !ok || !lmonth {
if now.Day() == 1 {
s.upBindAll()
s.lastmonth[m] = true
if m = m + 1; m > 12 {
m = 1
}
s.lastmonth[m] = false
log.Info("updatepro user monthly integral success")
}
}
}
func (s *Service) loadUnicomFlow() {
var (
list map[string]*unicom.UnicomUserFlow
err error
)
if list, err = s.dao.UserFlowListCache(context.TODO()); err != nil {
log.Error("load unicom s.dao.UserFlowListCache error(%v)", err)
return
}
log.Info("load unicom flow total len(%v)", len(list))
for key, u := range list {
var (
c = context.TODO()
requestNo int64
orderstatus string
msg string
)
if err = s.dao.UserFlowCache(c, key); err != nil {
if err == memcache.ErrNotFound {
if err = s.returnPoints(c, u); err != nil {
if err != ecode.NothingFound {
log.Error("load unicom s.returnPoints error(%v)", err)
continue
}
err = nil
}
log.Info("load unicom userbind timeout flow(%v)", u)
} else {
log.Error("load unicom s.dao.UserFlowCache error(%v)", err)
continue
}
} else {
if requestNo, err = s.seqdao.SeqID(c); err != nil {
log.Error("load unicom s.seqdao.SeqID error(%v)", err)
continue
}
if orderstatus, msg, err = s.dao.FlowQry(c, u.Phone, requestNo, u.Outorderid, u.Orderid, time.Now()); err != nil {
log.Error("load unicom s.dao.FlowQry error(%v) msg(%s)", err, msg)
continue
}
log.Info("load unicom userbind flow(%v) orderstatus(%s)", u, orderstatus)
if orderstatus == "00" {
continue
} else if orderstatus != "01" {
if err = s.returnPoints(c, u); err != nil {
if err != ecode.NothingFound {
log.Error("load unicom s.returnPoints error(%v)", err)
continue
}
err = nil
}
}
}
delete(list, key)
if err = s.dao.DeleteUserFlowCache(c, key); err != nil {
log.Error("load unicom s.dao.DeleteUserFlowCache error(%v)", err)
continue
}
}
if err = s.dao.AddUserFlowListCache(context.TODO(), list); err != nil {
log.Error("load unicom s.dao.AddUserFlowListCache error(%v)", err)
return
}
log.Info("load unicom flow last len(%v) success", len(list))
}
// returnPoints retutn user integral and flow
func (s *Service) returnPoints(c context.Context, u *unicom.UnicomUserFlow) (err error) {
var (
userbind *unicom.UserBind
result int64
)
if userbind, err = s.unicomBindInfo(c, u.Mid); err != nil {
return
}
ub := &unicom.UserBind{}
*ub = *userbind
ub.Flow = ub.Flow + u.Flow
ub.Integral = ub.Integral + u.Integral
if err = s.dao.AddUserBindCache(c, ub.Mid, ub); err != nil {
log.Error("unicom s.dao.AddUserBindCache error(%v)", err)
return
}
if result, err = s.dao.UpUserIntegral(c, ub); err != nil || result == 0 {
log.Error("unicom s.dao.UpUserIntegral error(%v) or result==0", err)
return
}
var packInt int
if u.Integral > 0 {
packInt = u.Integral
} else {
packInt = u.Flow
}
ul := &unicom.UserPackLog{
Phone: u.Phone,
Usermob: ub.Usermob,
Mid: u.Mid,
RequestNo: u.Outorderid,
Type: 0,
Desc: u.Desc + ",领取失败并返还",
Integral: packInt,
}
s.addUserPackLog(ul)
s.addUserIntegralLog(&unicom.UserIntegralLog{Phone: u.Phone, Mid: u.Mid, UnicomDesc: "", Type: 2, Integral: u.Integral, Flow: u.Flow, Desc: u.Desc + ",领取失败并返还"})
log.Info("unicom_pack(%v) mid(%v)", u.Desc+",领取失败并返还", userbind.Mid)
s.unicomPackInfoc(userbind.Usermob, u.Desc+",领取失败并返还", u.Orderid, userbind.Phone, packInt, 0, userbind.Mid, time.Now())
return
}
// unicomBindInfo unicom bind info
func (s *Service) unicomBindInfo(c context.Context, mid int64) (res *unicom.UserBind, err error) {
if res, err = s.dao.UserBindCache(c, mid); err != nil {
if res, err = s.dao.UserBind(c, mid); err != nil {
log.Error("s.dao.UserBind error(%v)", err)
return
}
if res == nil {
err = ecode.NothingFound
return
}
if err = s.dao.AddUserBindCache(c, mid, res); err != nil {
log.Error("s.dao.AddUserBindCache mid(%d) error(%v)", mid, err)
return
}
}
return
}
// loadUnicomIPOrder load unciom ip order update
func (s *Service) loadUnicomIPOrder(now time.Time) {
var (
dbips map[string]*unicom.UnicomIP
err error
)
if dbips, err = s.loadUnicomIP(context.TODO()); err != nil {
log.Error("s.loadUnicomIP", err)
return
}
if len(dbips) == 0 {
log.Error("db cache ip len 0")
return
}
unicomIP, err := s.dao.UnicomIP(context.TODO(), now)
if err != nil {
log.Error("s.dao.UnicomIP(%v)", err)
return
}
if len(unicomIP) == 0 {
log.Info("unicom ip orders is null")
return
}
tx, err := s.dao.BeginTran(context.TODO())
if err != nil {
log.Error("s.dao.BeginTran error(%v)", err)
return
}
for _, uip := range unicomIP {
key := fmt.Sprintf(_initIPUnicomKey, uip.Ipbegin, uip.Ipend)
if _, ok := dbips[key]; ok {
delete(dbips, key)
continue
}
var (
result int64
)
if result, err = s.dao.InUnicomIPSync(tx, uip, time.Now()); err != nil || result == 0 {
tx.Rollback()
log.Error("s.dao.InUnicomIPSync error(%v)", err)
return
}
}
for _, uold := range dbips {
var (
result int64
)
if result, err = s.dao.UpUnicomIP(tx, uold.Ipbegin, uold.Ipend, 0, time.Now()); err != nil || result == 0 {
tx.Rollback()
log.Error("s.dao.UpUnicomIP error(%v)", err)
return
}
}
if err = tx.Commit(); err != nil {
log.Error("tx.Commit error(%v)", err)
return
}
log.Info("update unicom ip success")
}
// loadUnicomIP load unicom ip
func (s *Service) loadUnicomIP(c context.Context) (res map[string]*unicom.UnicomIP, err error) {
var unicomIP []*unicom.UnicomIP
unicomIP, err = s.dao.IPSync(c)
if err != nil {
log.Error("s.dao.IPSync error(%v)", err)
return
}
tmp := map[string]*unicom.UnicomIP{}
for _, u := range unicomIP {
key := fmt.Sprintf(_initIPUnicomKey, u.Ipbegin, u.Ipend)
tmp[key] = u
}
res = tmp
log.Info("loadUnicomIPCache success")
return
}
func (s *Service) addUserPackLog(u *unicom.UserPackLog) {
select {
case s.packLogCh <- u:
default:
log.Warn("user pack log buffer is full")
}
}
func (s *Service) addUserIntegralLog(u *unicom.UserIntegralLog) {
select {
case s.integralLogCh[u.Mid%s.c.ChanDBNum] <- u:
default:
log.Warn("user add integral and flow log buffer is full")
}
}
func (s *Service) addUserPackLogproc() {
for {
i, ok := <-s.packLogCh
if !ok || s.closed {
log.Warn("user pack log proc exit")
return
}
var (
c = context.TODO()
result int64
err error
)
switch v := i.(type) {
case *unicom.UserPackLog:
if result, err = s.dao.InUserPackLog(c, v); err != nil || result == 0 {
log.Error("s.dao.UpUserIntegral error(%v) or result==0", err)
continue
}
log.Info("unicom user flow or integral back mid(%d) phone(%d)", v.Mid, v.Phone)
}
}
}
func (s *Service) addUserIntegralLogproc(i int64) {
var (
dbcliChan = s.integralLogCh[i]
)
for {
i, ok := <-dbcliChan
if !ok || s.closed {
log.Warn("user pack log proc exit")
return
}
var (
logID = 91
)
switch v := i.(type) {
case *unicom.UserIntegralLog:
// if result, err = s.dao.InUserIntegralLog(c, v); err != nil || result == 0 {
// log.Error("s.dao.InUserIntegralLog error(%v) or result==0", err)
// continue
// }
report.User(&report.UserInfo{
Mid: v.Mid,
Business: logID,
Action: "unicom_userpack_add",
Ctime: time.Now(),
Content: map[string]interface{}{
"phone": v.Phone,
"pack_desc": v.Desc,
"integral": v.Integral,
},
})
}
}
}

View File

@@ -0,0 +1,62 @@
package unicom
import (
"context"
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/job/main/app-wall/conf"
"go-common/app/job/main/app-wall/model/unicom"
. "github.com/smartystreets/goconvey/convey"
)
var (
s *Service
)
func WithService(f func(s *Service)) func() {
return func() {
f(s)
}
}
func init() {
dir, _ := filepath.Abs("../../cmd/app-wall-job-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func TestAddUserPackLogproc(t *testing.T) {
Convey("Unicom addUserPackLogproc", t, WithService(func(s *Service) {
s.addUserPackLogproc()
}))
}
func TestAddUserIntegralLogproc(t *testing.T) {
Convey("Unicom addUserIntegralLogproc", t, WithService(func(s *Service) {
s.addUserIntegralLogproc(1)
}))
}
func TestAddUserIntegralLog(t *testing.T) {
Convey("Unicom addUserIntegralLog", t, WithService(func(s *Service) {
s.addUserIntegralLog(&unicom.UserIntegralLog{})
}))
}
func TestLoadUnicomIP(t *testing.T) {
Convey("Unicom loadUnicomIP", t, WithService(func(s *Service) {
s.loadUnicomIP(context.TODO())
}))
}
func TestLoadUnicomIPOrder(t *testing.T) {
Convey("Unicom loadUnicomIPOrder", t, WithService(func(s *Service) {
s.loadUnicomIPOrder(time.Now())
}))
}