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,25 @@
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/service/main/point/api:all-srcs",
"//app/service/main/point/cmd:all-srcs",
"//app/service/main/point/conf:all-srcs",
"//app/service/main/point/dao:all-srcs",
"//app/service/main/point/model:all-srcs",
"//app/service/main/point/rpc/client:all-srcs",
"//app/service/main/point/rpc/server:all-srcs",
"//app/service/main/point/server/grpc:all-srcs",
"//app/service/main/point/server/http:all-srcs",
"//app/service/main/point/service:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,35 @@
# v1.3.0
1. add grpc
# v1.2.2
1. service unit test
# v1.2.1
1. dao unit test
# v1.2.0
1. add point add by bp rpc
# v1.1.0
1. new server && new verify or auth
# v1.0.5
1. add point history rpc
# v1.0.5
1. add register
# v1.0.4
1. 增加 rpc 相关接口
# v1.0.3
1. add point by admin interface
# v1.0.2
1. add log
# v1.0.1
1. 修改point info path
# v1.0.0
1. 初始化vip积分服务

View File

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

View File

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

View File

@@ -0,0 +1,14 @@
# point
# 项目简介
1. 大会员积分服务
# 编译环境
go 1.8.4
# 依赖包
# 编译执行

View File

@@ -0,0 +1,53 @@
load(
"@io_bazel_rules_go//proto:def.bzl",
"go_proto_library",
)
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
proto_library(
name = "v1_proto",
srcs = ["api.proto"],
tags = ["automanaged"],
)
go_proto_library(
name = "v1_go_proto",
compilers = ["@io_bazel_rules_go//proto:go_grpc"],
importpath = "go-common/app/service/main/point/api",
proto = ":v1_proto",
tags = ["automanaged"],
)
go_library(
name = "go_default_library",
srcs = [],
embed = [":v1_go_proto"],
importpath = "go-common/app/service/main/point/api",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"@com_github_gogo_protobuf//proto:go_default_library",
"@org_golang_google_grpc//:go_default_library",
"@org_golang_x_net//context: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"],
)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,170 @@
syntax = "proto3";
package account.point;
option go_package = "v1";
message AddPointReply {
int32 status = 1;
}
message AddPointReq {
ModelArgPoint pc = 2;
}
message AllConfigReply {
map<string, int64> data_0 = 1;
}
message AllConfigReq {
}
message CloseReply {
}
message CloseReq {
}
message ConfigReply {
int64 point = 1;
}
message ConfigReq {
int32 change_type = 2;
int64 mid = 3;
double bp = 4;
}
message ConsumePointReply {
int32 status = 1;
}
message ConsumePointReq {
ModelArgPointConsume pc = 2;
}
message ModelArgPoint {
int64 mid = 1;
int64 change_type = 2;
int64 point = 3;
string remark = 4;
string operator = 5;
}
message ModelArgPointAdd {
int64 mid = 1;
int32 change_type = 2;
string relation_id = 3;
double bcoin = 4;
string remark = 5;
string order_id = 6;
}
message ModelArgPointConsume {
int64 mid = 1;
int64 change_type = 2;
string relation_id = 3;
int64 point = 4;
string remark = 5;
}
message ModelOldPointHistory {
int64 id = 1;
int64 mid = 2;
int64 point = 3;
string order_id = 4;
int32 change_type = 5;
int64 change_time = 6;
string relation_id = 7;
int64 point_balance = 8;
string remark = 9;
string operator = 10;
}
message ModelPointHistory {
int64 id = 1;
int64 mid = 2;
int64 point = 3;
string order_id = 4;
int32 change_type = 5;
int64 change_time = 6;
string relation_id = 7;
int64 point_balance = 8;
string remark = 9;
string operator = 10;
}
message ModelPointInfo {
int64 mid = 1;
int64 point_balance = 2;
int64 ver = 3;
}
message OldPointHistoryReply {
repeated ModelOldPointHistory phs = 1;
int32 total = 2;
}
message OldPointHistoryReq {
int64 mid = 2;
int32 pn = 3;
int32 ps = 4;
}
message PingReply {
}
message PingReq {
}
message PointAddByBpReply {
int64 p = 1;
}
message PointAddByBpReq {
ModelArgPointAdd pa = 2;
}
message PointHistoryReply {
repeated ModelPointHistory phs = 1;
int32 total = 2;
int32 ncursor = 3;
}
message PointHistoryReq {
int64 mid = 2;
int32 cursor = 3;
int32 ps = 4;
}
message PointInfoReply {
ModelPointInfo pi = 1;
}
message PointInfoReq {
int64 mid = 2;
}
service Point {
// Config get point config.
rpc Config(ConfigReq) returns(ConfigReply);
// AllConfig all point config
rpc AllConfig(AllConfigReq) returns(AllConfigReply);
// Ping Service
rpc Ping(PingReq) returns(PingReply);
// Close Service
rpc Close(CloseReq) returns(CloseReply);
// PointInfo .
rpc PointInfo(PointInfoReq) returns(PointInfoReply);
// PointHistory .
rpc PointHistory(PointHistoryReq) returns(PointHistoryReply);
// OldPointHistory old point history .
rpc OldPointHistory(OldPointHistoryReq) returns(OldPointHistoryReply);
// PointAddByBp by bp.
rpc PointAddByBp(PointAddByBpReq) returns(PointAddByBpReply);
// ConsumePoint .
rpc ConsumePoint(ConsumePointReq) returns(ConsumePointReply);
// AddPoint .
rpc AddPoint(AddPointReq) returns(AddPointReply);
}

View File

@@ -0,0 +1,45 @@
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 = ["point-service.toml"],
importpath = "go-common/app/service/main/point/cmd",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/point/conf:go_default_library",
"//app/service/main/point/rpc/server:go_default_library",
"//app/service/main/point/server/grpc:go_default_library",
"//app/service/main/point/server/http:go_default_library",
"//app/service/main/point/service:go_default_library",
"//library/ecode/tip: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,61 @@
package main
import (
"context"
"flag"
"os"
"os/signal"
"syscall"
"time"
"go-common/app/service/main/point/conf"
rpc "go-common/app/service/main/point/rpc/server"
grpc "go-common/app/service/main/point/server/grpc"
"go-common/app/service/main/point/server/http"
"go-common/app/service/main/point/service"
ecode "go-common/library/ecode/tip"
"go-common/library/log"
)
var svc *service.Service
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("point start")
// ecode init
ecode.Init(conf.Conf.Ecode)
// service init
svc = service.New(conf.Conf)
// rpc init
rpcSvr := rpc.New(conf.Conf, svc)
ws := grpc.New(conf.Conf.WardenServer, svc)
// service init
http.Init(svc)
// 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("point get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
rpcSvr.Close()
ws.Shutdown(context.Background())
time.Sleep(time.Second * 2)
log.Info("point exit")
return
case syscall.SIGHUP:
default:
return
}
}
}

View File

@@ -0,0 +1,48 @@
[bm]
addr = "0.0.0.0:7582"
maxListen = 10
timeout = "1s"
[mysql]
addr = "127.0.0.1:3306"
dsn = "root:123456@tcp(127.0.0.1:3306)/bilibili_point?timeout=200ms&readTimeout=200ms&writeTimeout=200ms&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 20
idle = 10
idleTimeout ="4h"
queryTimeout = "100ms"
execTimeout = "100ms"
tranTimeout = "200ms"
[mysql.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[memcache]
name = "point"
proto = "tcp"
addr = "172.18.33.61:11241"
idle = 5
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "24h"
[property]
pointActiveStartDate = "2018-03-21 17:55:00"
pointActiveEndDate = "2019-01-21 20:04:05"
configLoadTick = "60s"
activityAllowAppID = [3]
pointGetRule = {"2" = 0,"3" = 50}
pointWhiteAppkeys = "ad4bb9b8f5d9d4a7"
[rpcServer]
proto = "tcp"
addr = "0.0.0.0:7589"
weight = 10
group=""

View File

@@ -0,0 +1,42 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["conf.go"],
importpath = "go-common/app/service/main/point/conf",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/cache/memcache:go_default_library",
"//library/conf:go_default_library",
"//library/database/sql:go_default_library",
"//library/ecode/tip:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/middleware/auth:go_default_library",
"//library/net/http/blademaster/middleware/verify:go_default_library",
"//library/net/rpc:go_default_library",
"//library/net/rpc/warden: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,119 @@
package conf
import (
"errors"
"flag"
"go-common/library/cache/memcache"
"go-common/library/conf"
"go-common/library/database/sql"
ecode "go-common/library/ecode/tip"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/auth"
"go-common/library/net/http/blademaster/middleware/verify"
"go-common/library/net/rpc"
"go-common/library/net/rpc/warden"
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 {
// elk
Log *log.Config
// http
BM *bm.ServerConfig
// Verify
Verify *verify.Config
// Auth
Auth *auth.Config
// memcache
Memcache *Memcache
// MySQL
MySQL *sql.Config
// ecode
Ecode *ecode.Config
// property
Property *Property
// rpc server
RPCServer *rpc.ServerConfig
// grpc server
WardenServer *warden.ServerConfig
}
// Property config for biz logic.
type Property struct {
PointActiveStartDate string
PointActiveEndDate string
ActivityAllowAppID []int64
ConfigLoadTick xtime.Duration
PointGetRule map[string]int64
PointWhiteAppkeys string
}
// Memcache memcache
type Memcache struct {
*memcache.Config
Expire xtime.Duration
}
func init() {
flag.StringVar(&confPath, "conf", "", "default config path")
}
// Init init conf
func Init() error {
if confPath != "" {
return local()
}
return remote()
}
func local() (err error) {
_, err = toml.DecodeFile(confPath, &Conf)
return
}
func remote() (err error) {
if client, err = conf.New(); err != nil {
return
}
if err = load(); err != nil {
return
}
go func() {
for range client.Event() {
log.Info("config reload")
if load() != nil {
log.Error("config reload error (%v)", err)
}
}
}()
return
}
func load() (err error) {
var (
s string
ok bool
tmpConf *Config
)
if s, ok = client.Toml2(); !ok {
return errors.New("load config center error")
}
if _, err = toml.Decode(s, &tmpConf); err != nil {
return errors.New("could not decode config")
}
*Conf = *tmpConf
return
}

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 = [
"dao_test.go",
"memcache_test.go",
"mysql_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/point/conf:go_default_library",
"//app/service/main/point/model:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"memcache.go",
"mysql.go",
],
importpath = "go-common/app/service/main/point/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/point/conf:go_default_library",
"//app/service/main/point/model:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/database/sql:go_default_library",
"//library/stat/prom:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,55 @@
package dao
import (
"context"
"time"
"go-common/app/service/main/point/conf"
"go-common/library/cache/memcache"
xsql "go-common/library/database/sql"
"go-common/library/stat/prom"
)
// Dao dao
type Dao struct {
c *conf.Config
mc *memcache.Pool
db *xsql.DB
mcExpire int32
errProm *prom.Prom
}
// New init mysql db
func New(c *conf.Config) (dao *Dao) {
dao = &Dao{
c: c,
mc: memcache.NewPool(c.Memcache.Config),
mcExpire: int32(time.Duration(c.Memcache.Expire) / time.Second),
db: xsql.NewMySQL(c.MySQL),
errProm: prom.BusinessErrCount,
}
return
}
// Close close the resource.
func (dao *Dao) Close() {
dao.mc.Close()
dao.db.Close()
}
// Ping dao ping
func (dao *Dao) Ping(c context.Context) (err error) {
if err = dao.db.Ping(c); err != nil {
return
}
err = dao.pingMC(c)
return
}
// pingMc ping
func (dao *Dao) pingMC(c context.Context) (err error) {
conn := dao.mc.Get(c)
defer conn.Close()
item := memcache.Item{Key: "ping", Value: []byte{1}, Expiration: 60}
return conn.Set(&item)
}

View File

@@ -0,0 +1,36 @@
package dao
import (
"flag"
"os"
"testing"
"go-common/app/service/main/point/conf"
)
var (
d *Dao
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.account.point-service")
flag.Set("conf_token", "0b280c9b45b2a8c31463b29fa4612f4e")
flag.Set("tree_id", "21519")
flag.Set("conf_version", "docker-1")
flag.Set("deploy_env", "uat")
flag.Set("conf_host", "config.bilibili.co")
flag.Set("conf_path", "/tmp")
flag.Set("region", "sh")
flag.Set("zone", "sh001")
} else {
flag.Set("conf", "../cmd/point-service.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
m.Run()
os.Exit(0)
}

View File

@@ -0,0 +1,84 @@
package dao
import (
"context"
"fmt"
"go-common/app/service/main/point/model"
gmc "go-common/library/cache/memcache"
"github.com/pkg/errors"
)
const (
_pointInfo = "pti:%d"
)
func pointKey(mid int64) string {
return fmt.Sprintf(_pointInfo, mid)
}
//DelPointInfoCache .
func (d *Dao) DelPointInfoCache(c context.Context, mid int64) (err error) {
return d.delCache(c, pointKey(mid))
}
// PointInfoCache .
func (d *Dao) PointInfoCache(c context.Context, mid int64) (pi *model.PointInfo, err error) {
var (
item *gmc.Item
)
key := pointKey(mid)
conn := d.mc.Get(c)
defer conn.Close()
if item, err = conn.Get(key); err != nil {
if err == gmc.ErrNotFound {
err = nil
pi = nil
return
}
err = errors.Wrapf(err, "d.PointInfoCache(%d)", mid)
d.errProm.Incr("get_mc")
return
}
pi = new(model.PointInfo)
if err = conn.Scan(item, pi); err != nil {
err = errors.Wrapf(err, "conn.Scan(%d)", pi.Mid)
d.errProm.Incr("scan_mc")
}
return
}
// SetPointInfoCache .
func (d *Dao) SetPointInfoCache(c context.Context, pi *model.PointInfo) (err error) {
key := pointKey(pi.Mid)
conn := d.mc.Get(c)
defer conn.Close()
item := &gmc.Item{
Key: key,
Object: pi,
Expiration: d.mcExpire,
Flags: gmc.FlagJSON,
}
if err = conn.Set(item); err != nil {
err = errors.Wrapf(err, "d.SetPointInfoCache(%d)", pi.Mid)
d.errProm.Incr("set_mc")
return
}
return
}
// DelCache del cache.
func (d *Dao) delCache(c context.Context, key string) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
if err = conn.Delete(key); err != nil {
if err == gmc.ErrNotFound {
err = nil
} else {
err = errors.Wrapf(err, "conn.Delete(%s)", key)
d.errProm.Incr("del_mc")
}
}
return
}

View File

@@ -0,0 +1,84 @@
package dao
import (
"context"
"testing"
"go-common/app/service/main/point/model"
"github.com/smartystreets/goconvey/convey"
)
func TestDaopointKey(t *testing.T) {
convey.Convey("pointKey", t, func(ctx convey.C) {
var (
mid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := pointKey(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoDelPointInfoCache(t *testing.T) {
convey.Convey("DelPointInfoCache", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.DelPointInfoCache(c, mid)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoPointInfoCache(t *testing.T) {
convey.Convey("PointInfoCache", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.PointInfoCache(c, mid)
ctx.Convey("Then err should be nil.pi should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoSetPointInfoCache(t *testing.T) {
convey.Convey("SetPointInfoCache", t, func(ctx convey.C) {
var (
c = context.Background()
pi = &model.PointInfo{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.SetPointInfoCache(c, pi)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaodelCache(t *testing.T) {
convey.Convey("delCache", t, func(ctx convey.C) {
var (
c = context.Background()
key = "1"
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.delCache(c, key)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,211 @@
package dao
import (
"context"
xsql "database/sql"
"go-common/app/service/main/point/model"
"go-common/library/database/sql"
xtime "go-common/library/time"
"github.com/pkg/errors"
)
const (
// point sql
_pointInfoSQL = "SELECT mid,point_balance,ver FROM point_info WHERE mid=?"
_pointHistorySQL = "SELECT id,mid,point,order_id,change_type,change_time,relation_id,point_balance,remark,operator FROM point_change_history WHERE mid = ? AND id < ? ORDER BY id DESC LIMIT ?"
_pointHistoryCountSQL = "SELECT COUNT(1) FROM point_change_history WHERE mid = ?"
_updatePointSQL = "UPDATE point_info SET point_balance = ?,ver=? WHERE mid=? AND ver=?"
_insertPointSQL = "INSERT INTO point_info(mid,point_balance,ver) VALUES(?,?,?)"
_InsertPointHistorySQL = "INSERT INTO point_change_history(mid,point,order_id,change_type,change_time,relation_id,point_balance,remark,operator) VALUES(?,?,?,?,?,?,?,?,?)"
_pointHistoryCheckSQL = "SELECT id FROM point_change_history WHERE order_id=?"
_selPointHistorySQL = "SELECT id,mid,point,order_id,change_type,change_time,relation_id,point_balance,remark,operator FROM point_change_history WHERE mid = ? AND change_time>=? AND change_time <= ? "
_allPointConfig = "SELECT `id`,`app_id`,`point`,`operator`,`ctime`,`mtime` FROM `point_conf`;"
//TODO compatible vip point old gateway
_oldPointHistorySQL = "SELECT id,mid,point,order_id,change_type,change_time,relation_id,point_balance,remark,operator FROM point_change_history WHERE mid = ? ORDER BY id DESC LIMIT ?,?;"
)
// BeginTran begin transaction.
func (d *Dao) BeginTran(c context.Context) (*sql.Tx, error) {
return d.db.Begin(c)
}
// PointInfo .
func (d *Dao) PointInfo(c context.Context, mid int64) (pi *model.PointInfo, err error) {
row := d.db.QueryRow(c, _pointInfoSQL, mid)
pi = new(model.PointInfo)
if err = row.Scan(&pi.Mid, &pi.PointBalance, &pi.Ver); err != nil {
if err == sql.ErrNoRows {
err = nil
pi = nil
} else {
err = errors.WithStack(err)
}
}
return
}
//TxPointInfo .
func (d *Dao) TxPointInfo(c context.Context, tx *sql.Tx, mid int64) (pi *model.PointInfo, err error) {
row := tx.QueryRow(_pointInfoSQL, mid)
pi = new(model.PointInfo)
if err = row.Scan(&pi.Mid, &pi.PointBalance, &pi.Ver); err != nil {
if err == sql.ErrNoRows {
err = nil
pi = nil
} else {
err = errors.WithStack(err)
}
}
return
}
//PointHistory point history
func (d *Dao) PointHistory(c context.Context, mid int64, cursor int, ps int) (phs []*model.PointHistory, err error) {
var rows *sql.Rows
if rows, err = d.db.Query(c, _pointHistorySQL, mid, cursor, ps); err != nil {
err = errors.WithStack(err)
return
}
for rows.Next() {
ph := new(model.PointHistory)
if err = rows.Scan(&ph.ID, &ph.Mid, &ph.Point, &ph.OrderID, &ph.ChangeType, &ph.ChangeTime, &ph.RelationID, &ph.PointBalance, &ph.Remark, &ph.Operator); err != nil {
phs = nil
err = errors.WithStack(err)
return
}
phs = append(phs, ph)
}
return
}
//PointHistoryCount point history
func (d *Dao) PointHistoryCount(c context.Context, mid int64) (count int, err error) {
row := d.db.QueryRow(c, _pointHistoryCountSQL, mid)
if err = row.Scan(&count); err != nil {
err = errors.WithStack(err)
}
return
}
//UpdatePointInfo .
func (d *Dao) UpdatePointInfo(c context.Context, tx *sql.Tx, pi *model.PointInfo, ver int64) (a int64, err error) {
var res xsql.Result
if res, err = tx.Exec(_updatePointSQL, pi.PointBalance, pi.Ver, pi.Mid, ver); err != nil {
err = errors.WithStack(err)
return
}
if a, err = res.RowsAffected(); err != nil {
err = errors.WithStack(err)
return
}
return
}
//InsertPoint .
func (d *Dao) InsertPoint(c context.Context, tx *sql.Tx, pi *model.PointInfo) (a int64, err error) {
var res xsql.Result
if res, err = tx.Exec(_insertPointSQL, pi.Mid, pi.PointBalance, pi.Ver); err != nil {
err = errors.WithStack(err)
return
}
if a, err = res.RowsAffected(); err != nil {
err = errors.WithStack(err)
return
}
return
}
//InsertPointHistory .
func (d *Dao) InsertPointHistory(c context.Context, tx *sql.Tx, ph *model.PointHistory) (a int64, err error) {
var res xsql.Result
if res, err = tx.Exec(_InsertPointHistorySQL, ph.Mid, ph.Point, ph.OrderID, ph.ChangeType, ph.ChangeTime, ph.RelationID, ph.PointBalance, ph.Remark, ph.Operator); err != nil {
err = errors.WithStack(err)
return
}
if a, err = res.RowsAffected(); err != nil {
err = errors.WithStack(err)
}
return
}
//SelPointHistory .
func (d *Dao) SelPointHistory(c context.Context, mid int64, startDate, endDate xtime.Time) (phs []*model.PointHistory, err error) {
var rows *sql.Rows
if rows, err = d.db.Query(c, _selPointHistorySQL, mid, startDate, endDate); err != nil {
err = errors.WithStack(err)
return
}
for rows.Next() {
ph := new(model.PointHistory)
if err = rows.Scan(&ph.ID, &ph.Mid, &ph.Point, &ph.OrderID, &ph.ChangeType, &ph.ChangeTime, &ph.RelationID, &ph.PointBalance, &ph.Remark, &ph.Operator); err != nil {
phs = nil
err = errors.WithStack(err)
}
phs = append(phs, ph)
}
return
}
// ExistPointOrder check orderID is uniq or not
func (d *Dao) ExistPointOrder(c context.Context, orID string) (id int, err error) {
row := d.db.QueryRow(c, _pointHistoryCheckSQL, orID)
if err = row.Scan(&id); err != nil {
if err == sql.ErrNoRows {
err = nil
return
}
err = errors.WithStack(err)
return
}
return
}
// AllPointConfig all point config.
func (d *Dao) AllPointConfig(c context.Context) (res []*model.VipPointConf, err error) {
var rows *sql.Rows
if rows, err = d.db.Query(c, _allPointConfig); err != nil {
err = errors.WithStack(err)
return
}
for rows.Next() {
vf := new(model.VipPointConf)
if err = rows.Scan(&vf.ID, &vf.AppID, &vf.Point, &vf.Operator, &vf.Ctime, &vf.Mtime); err != nil {
res = nil
err = errors.WithStack(err)
}
res = append(res, vf)
}
return
}
//OldPointHistory point history.
func (d *Dao) OldPointHistory(c context.Context, mid int64, start int, ps int) (phs []*model.OldPointHistory, err error) {
var rows *sql.Rows
if rows, err = d.db.Query(c, _oldPointHistorySQL, mid, start, ps); err != nil {
err = errors.WithStack(err)
return
}
for rows.Next() {
ph := new(model.PointHistory)
if err = rows.Scan(&ph.ID, &ph.Mid, &ph.Point, &ph.OrderID, &ph.ChangeType, &ph.ChangeTime, &ph.RelationID, &ph.PointBalance, &ph.Remark, &ph.Operator); err != nil {
phs = nil
err = errors.WithStack(err)
return
}
oph := new(model.OldPointHistory)
oph.ID = ph.ID
oph.Mid = ph.Mid
oph.Point = ph.Point
oph.OrderID = ph.OrderID
oph.ChangeType = ph.ChangeType
oph.ChangeTime = ph.ChangeTime.Time().Unix()
oph.RelationID = ph.RelationID
oph.PointBalance = ph.PointBalance
oph.Remark = ph.Remark
oph.Operator = ph.Operator
phs = append(phs, oph)
}
return
}

View File

@@ -0,0 +1,214 @@
package dao
import (
"context"
"testing"
"time"
"go-common/app/service/main/point/model"
xtime "go-common/library/time"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoBeginTran(t *testing.T) {
convey.Convey("BeginTran", t, func(ctx convey.C) {
var c = context.Background()
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1, err := d.BeginTran(c)
ctx.Convey("Then err should be nil.p1 should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoPointInfo(t *testing.T) {
convey.Convey("PointInfo", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.PointInfo(c, mid)
ctx.Convey("Then err should be nil.pi should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoTxPointInfo(t *testing.T) {
convey.Convey("TxPointInfo", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
tx, err := d.BeginTran(c)
ctx.So(err, convey.ShouldBeNil)
_, err = d.TxPointInfo(c, tx, mid)
ctx.Convey("Then err should be nil.pi should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoPointHistory(t *testing.T) {
convey.Convey("PointHistory", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
cursor = int(1)
ps = int(2)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.PointHistory(c, mid, cursor, ps)
ctx.Convey("Then err should be nil.phs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoPointHistoryCount(t *testing.T) {
convey.Convey("PointHistoryCount", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.PointHistoryCount(c, mid)
ctx.Convey("Then err should be nil.count should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoUpdatePointInfo(t *testing.T) {
convey.Convey("UpdatePointInfo", t, func(ctx convey.C) {
var (
c = context.Background()
pi = &model.PointInfo{}
ver = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
tx, err := d.BeginTran(c)
ctx.So(err, convey.ShouldBeNil)
a, err := d.UpdatePointInfo(c, tx, pi, ver)
ctx.Convey("Then err should be nil.a should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(a, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoInsertPoint(t *testing.T) {
convey.Convey("InsertPoint", t, func(ctx convey.C) {
var (
c = context.Background()
pi = &model.PointInfo{
Mid: time.Now().Unix(),
}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
tx, err := d.BeginTran(c)
ctx.So(err, convey.ShouldBeNil)
a, err := d.InsertPoint(c, tx, pi)
ctx.Convey("Then err should be nil.a should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(a, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoInsertPointHistory(t *testing.T) {
convey.Convey("InsertPointHistory", t, func(ctx convey.C) {
var (
c = context.Background()
ph = &model.PointHistory{
Mid: 1,
ChangeTime: xtime.Time(time.Now().Unix()),
}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
tx, err := d.BeginTran(c)
ctx.So(err, convey.ShouldBeNil)
a, err := d.InsertPointHistory(c, tx, ph)
ctx.Convey("Then err should be nil.a should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(a, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoSelPointHistory(t *testing.T) {
convey.Convey("SelPointHistory", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
startDate xtime.Time
endDate xtime.Time
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.SelPointHistory(c, mid, startDate, endDate)
ctx.Convey("Then err should be nil.phs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoExistPointOrder(t *testing.T) {
convey.Convey("ExistPointOrder", t, func(ctx convey.C) {
var (
c = context.Background()
orID = "1"
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
id, err := d.ExistPointOrder(c, orID)
ctx.Convey("Then err should be nil.id should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(id, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoAllPointConfig(t *testing.T) {
convey.Convey("AllPointConfig", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.AllPointConfig(c)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoOldPointHistory(t *testing.T) {
convey.Convey("OldPointHistory", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
start = int(0)
ps = int(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.OldPointHistory(c, mid, start, ps)
ctx.Convey("Then err should be nil.phs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,39 @@
load(
"@io_bazel_rules_go//proto:def.bzl",
"go_proto_library",
)
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"model.go",
"params.go",
"point.go",
"rpc.go",
],
importpath = "go-common/app/service/main/point/model",
tags = ["automanaged"],
visibility = ["//visibility:public"],
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,24 @@
package model
// point change type
const (
ExchangeVip = iota + 1
Charge //充电
Contract //承包
PointSystem //系统发放
FYMReward //分院帽奖励
ExchangePendant //兑换挂件
MJActive //萌节活动
ReAcquirePointDedution //重复领取
)
// system.
const (
ActivityGiveRemark = "承包额外赠送"
ActivitySendTimes1 = 1
ActivitySendTimes2 = 2
ActivityMixBuyBp = 1
ActivityOutOfBuyBp = 100
ActivityGivePoint = 1000
SUCCESS = 1
)

View File

@@ -0,0 +1,55 @@
package model
// ArgPointAdd .
type ArgPointAdd struct {
Mid int64 `json:"mid" form:"mid" validate:"required,min=1,gte=1"`
ChangeType int `json:"change_type" form:"change_type" validate:"required"`
RelationID string `json:"relation_id" form:"relation_id"`
Bcoin float64 `json:"bcoin" form:"bcoin" validate:"required"`
Remark string `json:"remark" form:"remark"`
OrderID string `json:"order_id" form:"order_id" validate:"required"`
}
// ArgMid .
type ArgMid struct {
Mid int64 `form:"mid" validate:"required,min=1,gte=1"`
}
//ArgPointHistory .
type ArgPointHistory struct {
Cursor int `form:"cursor"`
PS int `form:"ps"`
PN int `form:"pn"`
}
//ArgOldPointHistory .
type ArgOldPointHistory struct {
Mid int64 `form:"mid"`
PS int `form:"ps"`
PN int `form:"pn"`
}
// ArgConfig biz config.
type ArgConfig struct {
Mid int64 `form:"mid" validate:"required,min=1,gte=1"`
Bp float64 `form:"bp"`
ChangeType int8 `form:"change_type"`
}
// ArgPointConsume .
type ArgPointConsume struct {
Mid int64 `form:"mid" validate:"required,min=1,gte=1"`
ChangeType int64 `form:"change_type" validate:"required,min=1,gte=1"`
RelationID string `form:"relation_id"`
Point int64 `form:"point"`
Remark string `form:"remark"`
}
// ArgPoint .
type ArgPoint struct {
Mid int64 `form:"mid" validate:"required,min=1,gte=1"`
ChangeType int64 `form:"change_type" validate:"required,min=1,gte=1"`
Point int64 `form:"point"`
Remark string `form:"remark"`
Operator string `form:"operator"`
}

View File

@@ -0,0 +1,69 @@
package model
import (
"go-common/library/time"
)
// PointInfo .
type PointInfo struct {
Mid int64 `json:"mid"`
PointBalance int64 `json:"pointBalance"`
Ver int64 `json:"ver"`
}
//PointHistory point history
type PointHistory struct {
ID int64 `json:"id"`
Mid int64 `json:"mid"`
Point int64 `json:"point"`
OrderID string `json:"orderID"`
ChangeType int `json:"changeType"`
ChangeTime time.Time `json:"changeTime"`
RelationID string `json:"relationID"`
PointBalance int64 `json:"pointBalance"`
Remark string `json:"remark"`
Operator string `json:"operator"`
}
//OldPointHistory point history
type OldPointHistory struct {
ID int64 `json:"id"`
Mid int64 `json:"mid"`
Point int64 `json:"point"`
OrderID string `json:"orderID"`
ChangeType int `json:"changeType"`
ChangeTime int64 `json:"changeTime"`
RelationID string `json:"relationID"`
PointBalance int64 `json:"pointBalance"`
Remark string `json:"remark"`
Operator string `json:"operator"`
}
//PointExchangePrice .
type PointExchangePrice struct {
ID int `json:"id"`
OriginPoint int `json:"originPoint"`
CurrentPoint int `json:"currentPoint"`
Month int `json:"month"`
PromotionTip string `json:"promotionTip"`
PromotionColor string `json:"promotionColor"`
OperatorID string `json:"operatorId"`
}
//HandlerVip vip handler
type HandlerVip struct {
Days int
Months int
Mid int
Type int
}
// VipPointConf vip point conf.
type VipPointConf struct {
ID int64 `json:"id"`
AppID int64 `json:"app_id"`
Point int64 `json:"point"`
Operator string `json:"operator"`
Ctime time.Time `json:"ctime"`
Mtime time.Time `json:"mtime"`
}

View File

@@ -0,0 +1,19 @@
package model
// ArgRPCMid def.
type ArgRPCMid struct {
Mid int64
}
// PointHistoryResp point history resp.
type PointHistoryResp struct {
Phs []*OldPointHistory
Total int
}
//ArgRPCPointHistory def .
type ArgRPCPointHistory struct {
Mid int64
PS int `form:"ps"`
PN int `form:"pn"`
}

View File

@@ -0,0 +1,41 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["rpc_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
)
go_library(
name = "go_default_library",
srcs = ["rpc.go"],
importpath = "go-common/app/service/main/point/rpc/client",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/point/model:go_default_library",
"//library/net/rpc: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 client
import (
"context"
"go-common/app/service/main/point/model"
"go-common/library/net/rpc"
)
const (
_pointInfo = "RPC.PointInfo"
_pointConsume = "RPC.ConsumePoint"
_pointAdd = "RPC.PointAdd"
_pointHistory = "RPC.PointHistory"
_pointAddByBp = "RPC.PointAddByBp"
)
const (
_appid = "account.service.point"
)
// Service is a question service.
type Service struct {
client *rpc.Client2
}
// New new rpc service.
func New(c *rpc.ClientConfig) (s *Service) {
s = &Service{}
s.client = rpc.NewDiscoveryCli(_appid, c)
return
}
// Ping rpc ping.
func (s *Service) Ping(c context.Context, arg *struct{}) (res *int, err error) {
err = s.client.Call(c, "RPC.Ping", arg, res)
return
}
//PointInfo point info.
func (s *Service) PointInfo(c context.Context, arg *model.ArgRPCMid) (res *model.PointInfo, err error) {
res = new(model.PointInfo)
err = s.client.Call(c, _pointInfo, arg, res)
return
}
//ConsumePoint consume point.
func (s *Service) ConsumePoint(c context.Context, arg *model.ArgPointConsume) (status int8, err error) {
err = s.client.Call(c, _pointConsume, arg, &status)
return
}
//AddPoint add point.
func (s *Service) AddPoint(c context.Context, arg *model.ArgPoint) (status int8, err error) {
err = s.client.Call(c, _pointAdd, arg, &status)
return
}
// PointHistory point history.
func (s *Service) PointHistory(c context.Context, arg *model.ArgRPCPointHistory) (res *model.PointHistoryResp, err error) {
res = new(model.PointHistoryResp)
err = s.client.Call(c, _pointHistory, arg, res)
return
}
// PointAddByBp point add by bp.
func (s *Service) PointAddByBp(c context.Context, arg *model.ArgPointAdd) (res *int64, err error) {
err = s.client.Call(c, _pointAddByBp, arg, &res)
return
}

View File

@@ -0,0 +1 @@
package client

View File

@@ -0,0 +1,44 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["rpc_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
)
go_library(
name = "go_default_library",
srcs = ["rpc.go"],
importpath = "go-common/app/service/main/point/rpc/server",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/point/conf:go_default_library",
"//app/service/main/point/model:go_default_library",
"//app/service/main/point/service:go_default_library",
"//library/net/rpc:go_default_library",
"//library/net/rpc/context: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,77 @@
package server
import (
"go-common/app/service/main/point/conf"
"go-common/app/service/main/point/model"
"go-common/app/service/main/point/service"
"go-common/library/net/rpc"
"go-common/library/net/rpc/context"
)
// RPC represent rpc server
type RPC struct {
s *service.Service
}
// New init rpc.
func New(c *conf.Config, s *service.Service) (svr *rpc.Server) {
r := &RPC{s: s}
svr = rpc.NewServer(c.RPCServer)
if err := svr.Register(r); err != nil {
panic(err)
}
return
}
// Ping check connection success.
func (r *RPC) Ping(c context.Context, arg *struct{}, res *struct{}) (err error) {
return
}
// Auth check connection success.
func (r *RPC) Auth(c context.Context, arg *rpc.Auth, res *struct{}) (err error) {
return
}
// PointInfo point info.
func (r *RPC) PointInfo(c context.Context, a *model.ArgRPCMid, res *model.PointInfo) (err error) {
var p *model.PointInfo
if p, err = r.s.PointInfo(c, a.Mid); err == nil && p != nil {
*res = *p
}
return
}
// ConsumePoint point consume.
func (r *RPC) ConsumePoint(c context.Context, a *model.ArgPointConsume, status *int8) (err error) {
*status, err = r.s.ConsumePoint(c, a)
return
}
// PointAddByBp point add by bp.
func (r *RPC) PointAddByBp(c context.Context, arg *model.ArgPointAdd, res *int64) (err error) {
*res, err = r.s.PointAddByBp(c, arg)
return
}
// PointAdd point add.
func (r *RPC) PointAdd(c context.Context, a *model.ArgPoint, status *int8) (err error) {
*status, err = r.s.AddPoint(c, a)
return
}
// PointHistory point history.
func (r *RPC) PointHistory(c context.Context, arg *model.ArgRPCPointHistory, res *model.PointHistoryResp) (err error) {
var (
phs []*model.OldPointHistory
total int
)
if phs, total, err = r.s.OldPointHistory(c, arg.Mid, arg.PN, arg.PS); err == nil && len(phs) > 0 {
p := &model.PointHistoryResp{
Phs: phs,
Total: total,
}
*res = *p
}
return
}

View File

@@ -0,0 +1 @@
package server

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 = ["server.go"],
importpath = "go-common/app/service/main/point/server/grpc",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/point/api:go_default_library",
"//app/service/main/point/model:go_default_library",
"//app/service/main/point/service:go_default_library",
"//library/net/rpc/warden: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,169 @@
// Package server generate by warden_gen
package server
import (
"context"
pb "go-common/app/service/main/point/api"
"go-common/app/service/main/point/model"
service "go-common/app/service/main/point/service"
"go-common/library/net/rpc/warden"
)
// New Point warden rpc server
func New(c *warden.ServerConfig, svr *service.Service) *warden.Server {
ws := warden.NewServer(c)
pb.RegisterPointServer(ws.Server(), &server{svr})
ws, err := ws.Start()
if err != nil {
panic(err)
}
return ws
}
type server struct {
svr *service.Service
}
var _ pb.PointServer = &server{}
// Config get point config.
func (s *server) Config(ctx context.Context, req *pb.ConfigReq) (*pb.ConfigReply, error) {
p, err := s.svr.Config(ctx, int(req.ChangeType), req.Mid, req.Bp)
if err != nil {
return nil, err
}
return &pb.ConfigReply{Point: p}, err
}
// AllConfig all point config
func (s *server) AllConfig(ctx context.Context, req *pb.AllConfigReq) (*pb.AllConfigReply, error) {
ac := s.svr.AllConfig(ctx)
return &pb.AllConfigReply{Data_0: ac}, nil
}
// Ping Service
func (s *server) Ping(ctx context.Context, req *pb.PingReq) (*pb.PingReply, error) {
return &pb.PingReply{}, nil
}
// Close Service
func (s *server) Close(ctx context.Context, req *pb.CloseReq) (*pb.CloseReply, error) {
return &pb.CloseReply{}, nil
}
// PointInfo .
func (s *server) PointInfo(ctx context.Context, req *pb.PointInfoReq) (*pb.PointInfoReply, error) {
p, err := s.svr.PointInfo(ctx, req.Mid)
if err != nil {
return nil, err
}
return &pb.PointInfoReply{Pi: &pb.ModelPointInfo{
Mid: p.Mid,
PointBalance: p.PointBalance,
Ver: p.Ver,
}}, err
}
// PointHistory .
func (s *server) PointHistory(ctx context.Context, req *pb.PointHistoryReq) (*pb.PointHistoryReply, error) {
phs, t, nc, err := s.svr.PointHistory(ctx, req.Mid, int(req.Cursor), int(req.Ps))
if err != nil {
return nil, err
}
var mph []*pb.ModelPointHistory
for _, v := range phs {
p := &pb.ModelPointHistory{
Id: v.ID,
Mid: v.Mid,
Point: v.Point,
OrderId: v.OrderID,
ChangeType: int32(v.ChangeType),
ChangeTime: v.ChangeTime.Time().Unix(),
RelationId: v.RelationID,
PointBalance: v.PointBalance,
Remark: v.Remark,
Operator: v.Operator,
}
mph = append(mph, p)
}
return &pb.PointHistoryReply{
Phs: mph,
Total: int32(t),
Ncursor: int32(nc),
}, err
}
// OldPointHistory old point history .
func (s *server) OldPointHistory(ctx context.Context, req *pb.OldPointHistoryReq) (*pb.OldPointHistoryReply, error) {
phs, t, err := s.svr.OldPointHistory(ctx, req.Mid, int(req.Pn), int(req.Ps))
if err != nil {
return nil, err
}
var mop []*pb.ModelOldPointHistory
for _, v := range phs {
p := &pb.ModelOldPointHistory{
Id: v.ID,
Mid: v.Mid,
Point: v.Point,
OrderId: v.OrderID,
ChangeType: int32(v.ChangeType),
ChangeTime: v.ChangeTime,
RelationId: v.RelationID,
PointBalance: v.PointBalance,
Remark: v.Remark,
Operator: v.Operator,
}
mop = append(mop, p)
}
return &pb.OldPointHistoryReply{Phs: mop, Total: int32(t)}, err
}
// PointAddByBp by bp.
func (s *server) PointAddByBp(ctx context.Context, req *pb.PointAddByBpReq) (*pb.PointAddByBpReply, error) {
arg := &model.ArgPointAdd{
Mid: req.Pa.Mid,
ChangeType: int(req.Pa.ChangeType),
RelationID: req.Pa.RelationId,
Bcoin: req.Pa.Bcoin,
Remark: req.Pa.Remark,
OrderID: req.Pa.OrderId,
}
p, err := s.svr.PointAddByBp(ctx, arg)
if err != nil {
return nil, err
}
return &pb.PointAddByBpReply{P: p}, err
}
// ConsumePoint .
func (s *server) ConsumePoint(ctx context.Context, req *pb.ConsumePointReq) (*pb.ConsumePointReply, error) {
arg := &model.ArgPointConsume{
Mid: req.Pc.Mid,
ChangeType: req.Pc.ChangeType,
RelationID: req.Pc.RelationId,
Point: req.Pc.Point,
Remark: req.Pc.Remark,
}
status, err := s.svr.ConsumePoint(ctx, arg)
if err != nil {
return nil, err
}
return &pb.ConsumePointReply{Status: int32(status)}, err
}
// AddPoint .
func (s *server) AddPoint(ctx context.Context, req *pb.AddPointReq) (*pb.AddPointReply, error) {
pc := &model.ArgPoint{
Mid: req.Pc.Mid,
ChangeType: req.Pc.ChangeType,
Point: req.Pc.Point,
Remark: req.Pc.Remark,
Operator: req.Pc.Operator,
}
status, err := s.svr.AddPoint(ctx, pc)
if err != nil {
return nil, err
}
return &pb.AddPointReply{Status: int32(status)}, err
}

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 = [
"http.go",
"inner.go",
"outer.go",
"point.go",
],
importpath = "go-common/app/service/main/point/server/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/point/conf:go_default_library",
"//app/service/main/point/model:go_default_library",
"//app/service/main/point/service:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/middleware/auth:go_default_library",
"//library/net/http/blademaster/middleware/verify:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,52 @@
package http
import (
"net/http"
"go-common/app/service/main/point/conf"
"go-common/app/service/main/point/service"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/auth"
"go-common/library/net/http/blademaster/middleware/verify"
)
var (
svc *service.Service
verSvc *verify.Verify
authSvc *auth.Auth
whiteAppkeys string
)
// Init init.
func Init(s *service.Service) {
initService(s)
// init router.
engineInner := bm.DefaultServer(conf.Conf.BM)
innerRouter(engineInner)
outerRouter(engineInner)
if err := engineInner.Start(); err != nil {
log.Error("engineInner.Start() error(%v)", err)
panic(err)
}
whiteAppkeys = conf.Conf.Property.PointWhiteAppkeys
}
func initService(s *service.Service) {
svc = s
verSvc = verify.New(conf.Conf.Verify)
authSvc = auth.New(conf.Conf.Auth)
}
// ping check server ok.
func ping(c *bm.Context) {
if err := svc.Ping(c); err != nil {
log.Error("point http service ping error(%v)", err)
c.AbortWithStatus(http.StatusServiceUnavailable)
}
}
// register check server ok.
func register(c *bm.Context) {
c.JSON(map[string]interface{}{}, nil)
}

View File

@@ -0,0 +1,20 @@
package http
import bm "go-common/library/net/http/blademaster"
// innerRouter init local router api path.
func innerRouter(e *bm.Engine) {
e.Ping(ping)
e.Register(register)
ig := e.Group("/x/internal/point", verSvc.Verify)
{
ig.GET("/info", pointInfoInner)
ig.POST("/consume", pointConsume)
ig.POST("/add", pointAddByBp)
ig.GET("/configs", configs)
ig.GET("/config", config)
ig.GET("/old/history", oldPointHistory)
ig.POST("/addbyadmin", pointAdd)
}
}

View File

@@ -0,0 +1,16 @@
package http
import (
bm "go-common/library/net/http/blademaster"
)
// outerRouter init outer router api path.
func outerRouter(e *bm.Engine) {
// api v1
g := e.Group("/x/point", bm.CORS())
{
g.GET("/info", authSvc.User, pointInfo)
g.GET("/history", authSvc.User, pointHistory)
}
}

View File

@@ -0,0 +1,154 @@
package http
import (
"strings"
"go-common/app/service/main/point/model"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
)
func pointInfo(c *bm.Context) {
var (
mid, _ = c.Get("mid")
)
c.JSON(svc.PointInfo(c, mid.(int64)))
}
func pointInfoInner(c *bm.Context) {
m := new(model.ArgMid)
if err := c.Bind(m); err != nil {
return
}
c.JSON(svc.PointInfo(c, m.Mid))
}
func pointAddByBp(c *bm.Context) {
var (
err error
p int64
)
if err = checkAuth(c); err != nil {
c.JSON(nil, err)
}
pa := new(model.ArgPointAdd)
if err = c.Bind(pa); err != nil {
log.Error("point add by bp bind %+v", err)
return
}
if p, err = svc.PointAddByBp(c, pa); err != nil {
log.Error("point add by bp(%+v) faild(%+v)", pa, err)
c.JSON(nil, err)
return
}
c.JSON(map[string]interface{}{
"point": p,
}, nil)
}
func pointConsume(c *bm.Context) {
var (
err error
status int8
)
if err = checkAuth(c); err != nil {
c.JSON(nil, err)
}
arg := new(model.ArgPointConsume)
if err = c.Bind(arg); err != nil {
log.Error("point consume bind %+v", err)
return
}
if arg.Point <= 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if status, err = svc.ConsumePoint(c, arg); err != nil {
log.Error("point consume(%+v) faild(%+v)", arg, err)
}
c.JSON(map[string]interface{}{
"status": status,
}, nil)
}
func pointHistory(c *bm.Context) {
var (
mid, _ = c.Get("mid")
m = new(model.ArgPointHistory)
)
if err := c.Bind(m); err != nil {
return
}
phs, total, cursor, err := svc.PointHistory(c, mid.(int64), m.Cursor, m.PS)
data := make(map[string]interface{})
data["total"] = total
data["phs"] = phs
data["cursor"] = cursor
c.JSON(data, err)
}
func oldPointHistory(c *bm.Context) {
var (
m = new(model.ArgOldPointHistory)
)
if err := c.Bind(m); err != nil {
return
}
phs, total, err := svc.OldPointHistory(c, m.Mid, m.PN, m.PS)
data := make(map[string]interface{})
data["total"] = total
data["phs"] = phs
c.JSON(data, err)
}
func configs(c *bm.Context) {
c.JSON(svc.AllConfig(c), nil)
}
func config(c *bm.Context) {
arg := new(model.ArgConfig)
if err := c.Bind(arg); err != nil {
return
}
if arg.ChangeType == 0 {
arg.ChangeType = model.Contract
}
c.JSON(svc.Config(c, int(arg.ChangeType), arg.Mid, arg.Bp))
}
func checkAuth(c *bm.Context) (err error) {
req := c.Request
params := req.Form
sappkey := params.Get("appkey")
if len(sappkey) == 0 || !strings.Contains(whiteAppkeys, sappkey) {
err = ecode.AccessDenied
return
}
return
}
func pointAdd(c *bm.Context) {
var (
err error
status int8
)
if err = checkAuth(c); err != nil {
c.JSON(nil, err)
}
arg := new(model.ArgPoint)
if err = c.Bind(arg); err != nil {
log.Error("point add bind %+v", err)
return
}
if arg.Point <= 0 {
c.JSON(nil, ecode.RequestErr)
return
}
if status, err = svc.AddPoint(c, arg); err != nil {
log.Error("point add(%+v) faild(%+v)", arg, err)
}
c.JSON(map[string]interface{}{
"status": status,
}, nil)
}

View File

@@ -0,0 +1,65 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"activity_test.go",
"config_test.go",
"point_test.go",
"service_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/main/point/conf:go_default_library",
"//app/service/main/point/dao:go_default_library",
"//app/service/main/point/model:go_default_library",
"//library/database/sql:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/bouk/monkey:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"activity.go",
"config.go",
"point.go",
"service.go",
],
importpath = "go-common/app/service/main/point/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/point/conf:go_default_library",
"//app/service/main/point/dao:go_default_library",
"//app/service/main/point/model:go_default_library",
"//library/database/sql:go_default_library",
"//library/log:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,96 @@
package service
import (
"context"
"strconv"
"time"
"go-common/app/service/main/point/model"
xsql "go-common/library/database/sql"
"go-common/library/log"
xtime "go-common/library/time"
)
func (s *Service) activityGiveTimes(c context.Context, mid int64, changeType int, point int64) (sendTime int64, err error) {
var (
startDate time.Time
endDate time.Time
obtain int64
buyPoint int64
amount int64
alreadySend int64
phs []*model.PointHistory
now = time.Now()
ok bool
)
if changeType != model.Contract {
return
}
if startDate, err = time.ParseInLocation(_timeFormat, s.c.Property.PointActiveStartDate, time.Local); err != nil {
log.Error("time.ParseInLocation %+v", err)
return
}
if endDate, err = time.ParseInLocation(_timeFormat, s.c.Property.PointActiveEndDate, time.Local); err != nil {
log.Error("time.ParseInLocation %+v", err)
return
}
if now.Before(startDate) || now.After(endDate) {
return
}
if obtain, ok = s.c.Property.PointGetRule[strconv.Itoa(changeType)]; !ok || obtain == 0 {
log.Info("not found rete by changeType %+v", changeType)
return
}
if phs, err = s.dao.SelPointHistory(c, mid, xtime.Time(startDate.Unix()), xtime.Time(endDate.Unix())); err != nil {
log.Error("%+v", err)
return
}
for _, v := range phs {
if v.ChangeType == model.Contract {
buyPoint += v.Point
// old system pgc remark TNT.
if model.ActivityGiveRemark == v.Remark {
alreadySend += v.Point
}
}
}
buyPoint += point
amount = buyPoint / obtain
if alreadySend == 0 {
if amount >= model.ActivityMixBuyBp && amount < model.ActivityOutOfBuyBp {
sendTime = model.ActivitySendTimes1
} else if amount >= model.ActivityOutOfBuyBp {
sendTime = model.ActivitySendTimes2
}
} else if alreadySend == model.ActivityGivePoint && amount >= model.ActivityOutOfBuyBp {
sendTime = model.ActivitySendTimes1
}
return
}
func (s *Service) activeSendPoint(c context.Context, tx *xsql.Tx, ph *model.PointHistory) (activePoint int64, err error) {
var (
sendTime int64
pointBalance int64
)
sendTime, err = s.activityGiveTimes(c, ph.Mid, ph.ChangeType, ph.Point)
for i := 0; i < int(sendTime); i++ {
activePoint += model.ActivityGivePoint
phAdd := new(model.PointHistory)
if pointBalance, err = s.updatePoint(c, tx, ph.Mid, model.ActivityGivePoint); err != nil {
log.Error("%+v", err)
activePoint = 0
return
}
phAdd.Point = model.ActivityGivePoint
phAdd.PointBalance = pointBalance
phAdd.ChangeType = model.PointSystem
phAdd.RelationID = ph.OrderID
phAdd.Remark = model.ActivityGiveRemark
phAdd.Mid = ph.Mid
phAdd.ChangeTime = xtime.Time(time.Now().Unix())
s.dao.InsertPointHistory(c, tx, phAdd)
}
log.Info("send point total->%v mid:%v orderID:%v", activePoint, ph.Mid, ph.OrderID)
return
}

View File

@@ -0,0 +1,103 @@
package service
import (
"context"
"fmt"
"reflect"
"testing"
"go-common/app/service/main/point/dao"
"go-common/app/service/main/point/model"
xsql "go-common/library/database/sql"
xtime "go-common/library/time"
"github.com/bouk/monkey"
"github.com/smartystreets/goconvey/convey"
)
//以service层activityGiveTimes方法为例
func TestServiceactivityGiveTimes(t *testing.T) {
convey.Convey("activityGiveTimes", t, func(ctx convey.C) {
//被测方法与桩方法的变量及参数初始化
var (
c = context.Background()
mid = int64(4780461)
changeType = int(3)
point = int64(0)
phs []*model.PointHistory
ph = &model.PointHistory{
ID: 13,
Mid: 4780461,
Point: 60,
ChangeType: 1,
PointBalance: 418,
}
)
phs = append(phs, ph)
//convey包裹调用service测试方法及断言部分
ctx.Convey("When everything goes positive", func(ctx convey.C) {
//使用monkey包构造此service方法下所有依赖的dao层方法
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "SelPointHistory", func(_ *dao.Dao, _ context.Context, _ int64, _, _ xtime.Time) ([]*model.PointHistory, error) {
return phs, nil
})
sendTime, err := s.activityGiveTimes(c, mid, changeType, point)
ctx.Convey("Then err should be nil.sendTime should not be nil.", func(ctx convey.C) {
t.Logf("sendTime:%+v", sendTime)
ctx.So(err, convey.ShouldBeNil)
ctx.So(sendTime, convey.ShouldNotBeNil)
})
})
ctx.Convey("When dao return err", func(ctx convey.C) {
//使用monkey包构造此service方法下调dao层失败的情况
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "SelPointHistory", func(_ *dao.Dao, _ context.Context, _ int64, _, _ xtime.Time) ([]*model.PointHistory, error) {
return nil, fmt.Errorf("get history err")
})
_, err := s.activityGiveTimes(c, mid, changeType, point)
ctx.Convey("Then err should not be nil", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
//convey teardown部分(此处UnpatchAll解除所有Patch打桩绑定确保后续测试流程不被打桩影响)
ctx.Reset(func() {
monkey.UnpatchAll()
})
})
}
func TestServiceactiveSendPoint(t *testing.T) {
convey.Convey("activeSendPoint", t, func(ctx convey.C) {
var (
c = context.Background()
tx *xsql.Tx
phs []*model.PointHistory
ph = &model.PointHistory{
ID: 13,
Mid: 4780461,
Point: 60,
ChangeType: 1,
PointBalance: 418,
}
)
phs = append(phs, ph)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
//activeSendPoint方法中因调用了内部私有activityGiveTimes和updatePoint方法无法运用monkey反射机制报panic
// 可以采用给私有方法的下一级打桩或将私有方法转为公有
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "SelPointHistory", func(_ *dao.Dao, _ context.Context, _ int64, _, _ xtime.Time) ([]*model.PointHistory, error) {
return phs, nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "InsertPointHistory", func(_ *dao.Dao, _ context.Context, _ *xsql.Tx, ph *model.PointHistory) (int64, error) {
return 0, nil
})
activePoint, err := s.activeSendPoint(c, tx, ph)
ctx.Convey("Then err should be nil.activePoint should not be nil.", func(ctx convey.C) {
t.Logf("activepoint:%+v", activePoint)
ctx.So(err, convey.ShouldBeNil)
ctx.So(activePoint, convey.ShouldNotBeNil)
})
})
ctx.Reset(func() {
monkey.UnpatchAll()
})
})
}

View File

@@ -0,0 +1,44 @@
package service
import (
"context"
"math"
"strconv"
"go-common/app/service/main/point/model"
"go-common/library/log"
)
const (
_defcursor = int(^uint(0) >> 1)
_defps = 20
_defpn = 1
_timeFormat = "2006-01-02 15:04:05"
)
// Config get point config.
func (s *Service) Config(c context.Context, changeType int, mid int64, bp float64) (point int64, err error) {
var (
rate int64
times int64
ok bool
)
if bp == 0 {
return
}
if rate, ok = s.c.Property.PointGetRule[strconv.Itoa(changeType)]; !ok {
return
}
point = int64(math.Ceil(float64(rate) * bp))
if times, err = s.activityGiveTimes(c, mid, changeType, point); err != nil {
log.Error("%+v", err)
return
}
point += times * model.ActivityGivePoint
return
}
//AllConfig all point config
func (s *Service) AllConfig(c context.Context) map[string]int64 {
return s.c.Property.PointGetRule
}

View File

@@ -0,0 +1,58 @@
package service
import (
"context"
"reflect"
"testing"
"go-common/app/service/main/point/dao"
"go-common/app/service/main/point/model"
xtime "go-common/library/time"
"github.com/bouk/monkey"
"github.com/smartystreets/goconvey/convey"
)
func TestServiceConfig(t *testing.T) {
convey.Convey("Config", t, func(ctx convey.C) {
var (
c = context.Background()
changeType = int(3)
mid = int64(4780461)
bp = float64(1)
phs []*model.PointHistory
ph = &model.PointHistory{
ID: 13,
Mid: 4780461,
Point: 60,
ChangeType: 1,
PointBalance: 418,
}
)
phs = append(phs, ph)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "SelPointHistory", func(_ *dao.Dao, _ context.Context, _ int64, _, _ xtime.Time) ([]*model.PointHistory, error) {
return phs, nil
})
point, err := s.Config(c, changeType, mid, bp)
ctx.Convey("Then err should be nil.point should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(point, convey.ShouldNotBeNil)
})
})
})
}
func TestServiceAllConfig(t *testing.T) {
convey.Convey("AllConfig", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := s.AllConfig(c)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,260 @@
package service
import (
"context"
"fmt"
"math"
"strconv"
"time"
"github.com/pkg/errors"
"go-common/app/service/main/point/model"
xsql "go-common/library/database/sql"
"go-common/library/log"
xtime "go-common/library/time"
)
//PointInfo .
func (s *Service) PointInfo(c context.Context, mid int64) (pi *model.PointInfo, err error) {
var (
cache = true
)
if pi, err = s.dao.PointInfoCache(c, mid); err != nil {
log.Error("%+v", err)
cache = false
}
if pi != nil {
return
}
if pi, err = s.dao.PointInfo(c, mid); err != nil {
log.Error("%+v", err)
return
}
if pi == nil {
pi = new(model.PointInfo)
pi.Mid = mid
}
if cache {
s.dao.SetPointInfoCache(c, pi)
}
return
}
//PointHistory .
func (s *Service) PointHistory(c context.Context, mid int64, cursor, ps int) (phs []*model.PointHistory, total int, ncursor int, err error) {
if total, err = s.dao.PointHistoryCount(c, mid); err != nil {
log.Error("%+v", err)
return
}
if total <= 0 {
return
}
if cursor <= 0 {
cursor = _defcursor
}
if ps <= 0 {
ps = _defps
}
if phs, err = s.dao.PointHistory(c, mid, cursor, ps); err != nil {
log.Error("%+v", err)
return
}
if len(phs) != 0 {
ncursor = int(phs[len(phs)-1].ID)
}
return
}
//OldPointHistory old point history .
func (s *Service) OldPointHistory(c context.Context, mid int64, pn, ps int) (phs []*model.OldPointHistory, total int, err error) {
if total, err = s.dao.PointHistoryCount(c, mid); err != nil {
log.Error("%+v", err)
return
}
if total <= 0 {
return
}
if pn <= 0 {
pn = _defpn
}
if ps <= 0 {
ps = _defps
}
if phs, err = s.dao.OldPointHistory(c, mid, (pn-1)*ps, ps); err != nil {
log.Error("%+v", err)
return
}
return
}
//PointAddByBp by bp.
func (s *Service) PointAddByBp(c context.Context, pa *model.ArgPointAdd) (p int64, err error) {
var (
hid int
activePoint int64
ph = new(model.PointHistory)
rate int64
ok bool
)
if hid, err = s.dao.ExistPointOrder(c, pa.OrderID); err != nil {
log.Error("point add %+v", err)
return
}
if hid > 0 {
log.Error("point add repeated consumption %+v", pa)
return
}
if rate, ok = s.c.Property.PointGetRule[strconv.Itoa(pa.ChangeType)]; !ok || rate == 0 {
log.Info("point add not found rete %+v", pa.ChangeType)
return
}
p = int64(math.Ceil(pa.Bcoin * float64(rate)))
if p == 0 {
return
}
ph.ChangeType = int(pa.ChangeType)
ph.OrderID = pa.OrderID
ph.Point = p
ph.Remark = pa.Remark
ph.Mid = pa.Mid
ph.RelationID = pa.RelationID
ph.ChangeTime = xtime.Time(time.Now().Unix())
if _, activePoint, err = s.updatePointWithHistory(c, ph); err != nil {
log.Error("add point mid(%d) ph(%v) %+v", ph.Mid, ph, err)
return
}
p += activePoint
s.dao.DelPointInfoCache(c, pa.Mid)
return
}
func (s *Service) updatePointWithHistory(c context.Context, ph *model.PointHistory) (pointBalance int64, activePoint int64, err error) {
var (
tx *xsql.Tx
)
if tx, err = s.dao.BeginTran(c); err != nil {
err = errors.WithStack(err)
return
}
defer func() {
if err == nil {
if err = tx.Commit(); err != nil {
err = errors.WithStack(err)
tx.Rollback()
}
} else {
tx.Rollback()
}
}()
if pointBalance, err = s.updatePoint(c, tx, ph.Mid, ph.Point); err != nil {
err = errors.WithStack(err)
return
}
ph.PointBalance = pointBalance
if _, err = s.dao.InsertPointHistory(c, tx, ph); err != nil {
err = errors.WithStack(err)
return
}
if ph.ChangeType == model.Contract && ph.Point >= 0 {
if activePoint, err = s.activeSendPoint(c, tx, ph); err != nil {
err = errors.WithStack(err)
return
}
}
return
}
func (s *Service) updatePoint(c context.Context, tx *xsql.Tx, mid, point int64) (pb int64, err error) {
var (
pi *model.PointInfo
ver int64
a int64
)
if pi, err = s.dao.TxPointInfo(c, tx, mid); err != nil {
err = errors.WithStack(err)
return
}
if point == 0 {
return
}
if pi == nil {
if point < 0 {
err = fmt.Errorf("point not enough")
return
}
pb = point
pi = new(model.PointInfo)
pi.Ver = 1
pi.PointBalance = point
pi.Mid = mid
if a, err = s.dao.InsertPoint(c, tx, pi); err != nil {
err = errors.WithStack(err)
return
}
if a != 1 {
err = fmt.Errorf("operation failed")
return
}
} else {
pb = pi.PointBalance + point
if pb < 0 {
err = fmt.Errorf("point not enough")
return
}
pi.PointBalance = pb
ver = pi.Ver
pi.Ver++
if a, err = s.dao.UpdatePointInfo(c, tx, pi, ver); err != nil {
err = errors.WithStack(err)
return
}
if a != 1 {
err = fmt.Errorf("operation failed")
return
}
}
return
}
//ConsumePoint .
func (s *Service) ConsumePoint(c context.Context, pc *model.ArgPointConsume) (status int8, err error) {
var (
ph *model.PointHistory
)
pc.Point = ^pc.Point + 1
ph = new(model.PointHistory)
ph.ChangeType = int(pc.ChangeType)
ph.ChangeTime = xtime.Time(time.Now().Unix())
ph.Mid = pc.Mid
ph.RelationID = pc.RelationID
ph.Remark = pc.Remark
ph.Point = pc.Point
if _, _, err = s.updatePointWithHistory(c, ph); err != nil {
log.Error("consume point mid(%d) ph(%v) %+v", ph.Mid, ph, err)
return
}
s.dao.DelPointInfoCache(c, pc.Mid)
status = model.SUCCESS
return
}
// AddPoint .
func (s *Service) AddPoint(c context.Context, pc *model.ArgPoint) (status int8, err error) {
ph := new(model.PointHistory)
ph.ChangeType = int(pc.ChangeType)
ph.ChangeTime = xtime.Time(time.Now().Unix())
ph.Mid = pc.Mid
ph.Remark = pc.Remark
ph.Point = pc.Point
ph.Operator = pc.Operator
if _, _, err = s.updatePointWithHistory(c, ph); err != nil {
err = errors.WithStack(err)
return
}
s.dao.DelPointInfoCache(c, pc.Mid)
status = model.SUCCESS
return
}

View File

@@ -0,0 +1,357 @@
package service
import (
"context"
"reflect"
"testing"
"go-common/app/service/main/point/dao"
"go-common/app/service/main/point/model"
xsql "go-common/library/database/sql"
"github.com/bouk/monkey"
"github.com/smartystreets/goconvey/convey"
)
func TestServicePointInfo(t *testing.T) {
convey.Convey("PointInfo", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(1)
pm = &model.PointInfo{
Mid: 1,
PointBalance: 2,
Ver: 1,
}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "PointInfoCache", func(_ *dao.Dao, _ context.Context, _ int64) (*model.PointInfo, error) {
return nil, nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "PointInfo", func(_ *dao.Dao, _ context.Context, _ int64) (*model.PointInfo, error) {
return pm, nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "SetPointInfoCache", func(_ *dao.Dao, _ context.Context, _ *model.PointInfo) error {
return nil
})
pi, err := s.PointInfo(c, mid)
ctx.Convey("Then err should be nil.pi should not be nil.", func(ctx convey.C) {
t.Logf("pi:%+v", pi)
ctx.So(err, convey.ShouldBeNil)
ctx.So(pi, convey.ShouldNotBeNil)
})
ctx.Reset(func() {
monkey.UnpatchAll()
})
})
})
}
func TestServicePointHistory(t *testing.T) {
convey.Convey("PointHistory", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(4780461)
cursor = int(0)
ps = int(20)
total = int(2)
pms []*model.PointHistory
pm = &model.PointHistory{
ID: 13,
Mid: 4780461,
Point: 60,
ChangeType: 1,
PointBalance: 418,
}
)
pms = append(pms, pm)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "PointHistoryCount", func(_ *dao.Dao, _ context.Context, _ int64) (int, error) {
return total, nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "PointHistory", func(_ *dao.Dao, _ context.Context, _ int64, _, _ int) ([]*model.PointHistory, error) {
return pms, nil
})
phs, total, ncursor, err := s.PointHistory(c, mid, cursor, ps)
ctx.Convey("Then err should be nil.phs,total,ncursor should not be nil.", func(ctx convey.C) {
t.Logf("phs:%+v", phs)
t.Logf("total:%+v", total)
ctx.So(err, convey.ShouldBeNil)
ctx.So(ncursor, convey.ShouldNotBeNil)
ctx.So(total, convey.ShouldNotBeNil)
ctx.So(phs, convey.ShouldNotBeNil)
})
ctx.Reset(func() {
monkey.UnpatchAll()
})
})
})
}
func TestServiceOldPointHistory(t *testing.T) {
convey.Convey("OldPointHistory", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(4780461)
pn = int(1)
ps = int(20)
total = int(2)
pms []*model.OldPointHistory
pm = &model.OldPointHistory{
ID: 13,
Mid: 4780461,
Point: 60,
ChangeType: 1,
PointBalance: 418,
}
)
pms = append(pms, pm)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "PointHistoryCount", func(_ *dao.Dao, _ context.Context, _ int64) (int, error) {
return total, nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "OldPointHistory", func(_ *dao.Dao, _ context.Context, _ int64, _, _ int) ([]*model.OldPointHistory, error) {
return pms, nil
})
phs, total, err := s.OldPointHistory(c, mid, pn, ps)
ctx.Convey("Then err should be nil.phs,total should not be nil.", func(ctx convey.C) {
t.Logf("phs:%+v", phs)
t.Logf("total:%+v", total)
ctx.So(err, convey.ShouldBeNil)
ctx.So(total, convey.ShouldNotBeNil)
ctx.So(phs, convey.ShouldNotBeNil)
})
})
ctx.Reset(func() {
monkey.UnpatchAll()
})
})
}
func TestServicePointAddByBp(t *testing.T) {
convey.Convey("PointAddByBp", t, func(ctx convey.C) {
var (
c = context.Background()
pa = &model.ArgPointAdd{
Mid: 1,
ChangeType: 3,
RelationID: "121",
Bcoin: 10,
Remark: "test",
OrderID: "31",
}
hid = int(1)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "ExistPointOrder", func(_ *dao.Dao, _ context.Context, _ string) (int, error) {
return hid, nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "DelPointInfoCache", func(_ *dao.Dao, _ context.Context, _ int64) error {
return nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "DelPointInfoCache", func(_ *dao.Dao, _ context.Context, _ int64) error {
return nil
})
p, err := s.PointAddByBp(c, pa)
ctx.Convey("Then err should be nil.p should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(p, convey.ShouldNotBeNil)
})
})
})
}
func TestServiceupdatePointWithHistory(t *testing.T) {
convey.Convey("updatePointWithHistory", t, func(ctx convey.C) {
var (
c = context.Background()
ph = &model.PointHistory{
ID: 13,
Mid: 4780461,
Point: 60,
ChangeType: 1,
PointBalance: 418,
}
tx = &xsql.Tx{}
pm = &model.PointInfo{
Mid: 1,
PointBalance: 2,
Ver: 1,
}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "BeginTran", func(_ *dao.Dao, _ context.Context) (*xsql.Tx, error) {
return nil, nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(tx), "Commit", func(_ *xsql.Tx) error {
return nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "InsertPointHistory", func(_ *dao.Dao, _ context.Context, _ *xsql.Tx, _ *model.PointHistory) (int64, error) {
return 0, nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "TxPointInfo", func(_ *dao.Dao, _ context.Context, _ *xsql.Tx, _ int64) (*model.PointInfo, error) {
return pm, nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "InsertPoint", func(_ *dao.Dao, _ context.Context, _ *xsql.Tx, _ *model.PointInfo) (int64, error) {
return 1, nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "UpdatePointInfo", func(_ *dao.Dao, _ context.Context, _ *xsql.Tx, _ *model.PointInfo, _ int64) (int64, error) {
return 1, nil
})
pointBalance, activePoint, err := s.updatePointWithHistory(c, ph)
ctx.Convey("Then err should be nil.pointBalance,activePoint should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(activePoint, convey.ShouldNotBeNil)
ctx.So(pointBalance, convey.ShouldNotBeNil)
})
})
ctx.Reset(func() {
monkey.UnpatchAll()
})
})
}
func TestServiceupdatePoint(t *testing.T) {
convey.Convey("updatePoint", t, func(ctx convey.C) {
var (
c = context.Background()
tx = &xsql.Tx{}
mid = int64(1)
point = int64(10)
pm = &model.PointInfo{
Mid: 1,
PointBalance: 2,
Ver: 1,
}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "TxPointInfo", func(_ *dao.Dao, _ context.Context, _ *xsql.Tx, _ int64) (*model.PointInfo, error) {
return pm, nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "InsertPoint", func(_ *dao.Dao, _ context.Context, _ *xsql.Tx, _ *model.PointInfo) (int64, error) {
return 1, nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "UpdatePointInfo", func(_ *dao.Dao, _ context.Context, _ *xsql.Tx, _ *model.PointInfo, _ int64) (int64, error) {
return 1, nil
})
pb, err := s.updatePoint(c, tx, mid, point)
ctx.Convey("Then err should be nil.pb should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(pb, convey.ShouldNotBeNil)
})
})
ctx.Reset(func() {
monkey.UnpatchAll()
})
})
}
func TestServiceConsumePoint(t *testing.T) {
convey.Convey("ConsumePoint", t, func(ctx convey.C) {
var (
tx = &xsql.Tx{}
c = context.Background()
pc = &model.ArgPointConsume{
Mid: 2,
ChangeType: 4,
RelationID: "1",
Point: 1,
Remark: "测试消费",
}
pm = &model.PointInfo{
Mid: 2,
PointBalance: 2000,
Ver: 1,
}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "BeginTran", func(_ *dao.Dao, _ context.Context) (*xsql.Tx, error) {
return nil, nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(tx), "Commit", func(_ *xsql.Tx) error {
return nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(tx), "Rollback", func(_ *xsql.Tx) error {
return nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "InsertPointHistory", func(_ *dao.Dao, _ context.Context, _ *xsql.Tx, _ *model.PointHistory) (int64, error) {
return 0, nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "TxPointInfo", func(_ *dao.Dao, _ context.Context, _ *xsql.Tx, _ int64) (*model.PointInfo, error) {
return pm, nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "InsertPoint", func(_ *dao.Dao, _ context.Context, _ *xsql.Tx, _ *model.PointInfo) (int64, error) {
return 1, nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "UpdatePointInfo", func(_ *dao.Dao, _ context.Context, _ *xsql.Tx, _ *model.PointInfo, _ int64) (int64, error) {
return 1, nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "DelPointInfoCache", func(_ *dao.Dao, _ context.Context, _ int64) error {
return nil
})
status, err := s.ConsumePoint(c, pc)
ctx.Convey("Then err should be nil.status should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(status, convey.ShouldNotBeNil)
})
})
ctx.Reset(func() {
monkey.UnpatchAll()
})
})
}
func TestServiceAddPoint(t *testing.T) {
convey.Convey("AddPoint", t, func(ctx convey.C) {
var (
tx = &xsql.Tx{}
c = context.Background()
pc = &model.ArgPoint{
Mid: 52,
ChangeType: 3,
Remark: "测试增加",
Point: 300,
Operator: "yubaihai",
}
pm = &model.PointInfo{
Mid: 52,
PointBalance: 2,
Ver: 1,
}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "BeginTran", func(_ *dao.Dao, _ context.Context) (*xsql.Tx, error) {
return nil, nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(tx), "Commit", func(_ *xsql.Tx) error {
return nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "InsertPointHistory", func(_ *dao.Dao, _ context.Context, _ *xsql.Tx, _ *model.PointHistory) (int64, error) {
return 0, nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "TxPointInfo", func(_ *dao.Dao, _ context.Context, _ *xsql.Tx, _ int64) (*model.PointInfo, error) {
return pm, nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "InsertPoint", func(_ *dao.Dao, _ context.Context, _ *xsql.Tx, _ *model.PointInfo) (int64, error) {
return 1, nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "UpdatePointInfo", func(_ *dao.Dao, _ context.Context, _ *xsql.Tx, _ *model.PointInfo, _ int64) (int64, error) {
return 1, nil
})
monkey.PatchInstanceMethod(reflect.TypeOf(s.dao), "DelPointInfoCache", func(_ *dao.Dao, _ context.Context, _ int64) error {
return nil
})
status, err := s.AddPoint(c, pc)
ctx.Convey("Then err should be nil.status should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(status, convey.ShouldNotBeNil)
})
})
ctx.Reset(func() {
monkey.UnpatchAll()
})
})
}

View File

@@ -0,0 +1,79 @@
package service
import (
"context"
"sync/atomic"
"time"
"unsafe"
"go-common/app/service/main/point/conf"
"go-common/app/service/main/point/dao"
"go-common/app/service/main/point/model"
"go-common/library/log"
)
// Service struct
type Service struct {
c *conf.Config
dao *dao.Dao
pointConf map[int64]int64
configLoadTick time.Duration
}
// New init
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
dao: dao.New(c),
pointConf: make(map[int64]int64),
configLoadTick: time.Duration(c.Property.ConfigLoadTick),
}
if err := s.loadallpointconf(); err != nil {
panic(err)
}
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) loadallpointconf() (err error) {
var (
c = context.Background()
es []*model.VipPointConf
)
es, err = s.dao.AllPointConfig(c)
if err != nil {
log.Error("loadallpointconf allpoint conf error(%v)", err)
return
}
tmp := make(map[int64]int64, len(es))
for _, e := range es {
tmp[e.AppID] = e.Point
}
p := unsafe.Pointer(&s.pointConf)
atomic.SwapPointer(&p, unsafe.Pointer(&tmp))
log.Info("loadallpointconf (%v) load success", tmp)
return
}
func (s *Service) loadconfigproc() {
defer func() {
if x := recover(); x != nil {
log.Error("s.loadconfigproc panic(%v)", x)
go s.loadconfigproc()
log.Info("s.loadconfigproc recover")
}
}()
for {
time.Sleep(s.configLoadTick)
s.loadallpointconf()
}
}

View File

@@ -0,0 +1,23 @@
package service
import (
"flag"
"os"
"testing"
"go-common/app/service/main/point/conf"
)
var (
s *Service
)
func TestMain(m *testing.M) {
flag.Set("conf", "../cmd/point-service.toml")
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
s = New(conf.Conf)
os.Exit(m.Run())
}