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

View File

@@ -0,0 +1,6 @@
# v1.0.2
1. refined grpc struct and remove http api package
# v1.0.1
1. 批量冻结信息获取
# v1.0.0
1. 大会员信息一期

View File

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

View File

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

View File

@@ -0,0 +1,12 @@
# vipinfo-service
# 项目简介
1.大会员信息
# 编译环境
# 依赖包
# 编译执行

View File

@@ -0,0 +1,57 @@
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"],
deps = ["@gogo_special_proto//github.com/gogo/protobuf/gogoproto"],
)
go_proto_library(
name = "v1_go_proto",
compilers = ["@io_bazel_rules_go//proto:gogofast_grpc"],
importpath = "go-common/app/service/main/vipinfo/api",
proto = ":v1_proto",
tags = ["automanaged"],
deps = ["@com_github_gogo_protobuf//gogoproto:go_default_library"],
)
go_library(
name = "go_default_library",
srcs = ["client.go"],
embed = [":v1_go_proto"],
importpath = "go-common/app/service/main/vipinfo/api",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/net/rpc/warden:go_default_library",
"@com_github_gogo_protobuf//gogoproto:go_default_library",
"@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,38 @@
syntax = "proto3";
// use {app_id}.{version} as package name
package vipinfo.service.v1;
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
option go_package = "v1";
message InfoReply {
ModelInfo res = 1;
}
message InfoReq {
int64 mid = 2;
}
message InfosReply {
map<int64, ModelInfo> res = 1;
}
message InfosReq {
repeated int64 mids = 2;
}
message ModelInfo {
int32 type = 1 [(gogoproto.jsontag) = "type"];
int32 status = 2 [(gogoproto.jsontag) = "status"];
int64 due_date = 3 [(gogoproto.jsontag) = "due_date"];
int32 vip_pay_type = 4 [(gogoproto.jsontag) = "vip_pay_type"];
}
service VipInfo {
// Info get vipinfo by mid.
rpc Info(InfoReq) returns(InfoReply);
// Infos get vipinfos by mids
rpc Infos(InfosReq) returns(InfosReply);
}

View File

@@ -0,0 +1,25 @@
package v1
import (
"fmt"
"go-common/library/net/rpc/warden"
context "golang.org/x/net/context"
grpc "google.golang.org/grpc"
)
// AppID .
const AppID = "vipinfo.service"
// NewClient new grpc client
func NewClient(cfg *warden.ClientConfig, opts ...grpc.DialOption) (VipInfoClient, error) {
client := warden.NewClient(cfg, opts...)
cc, err := client.Dial(context.Background(), fmt.Sprintf("discovery://default/%s", AppID))
if err != nil {
return nil, err
}
return NewVipInfoClient(cc), nil
}
// ${GOPATH}/bin/warden -name=VipInfo -proto-package=account.vipinfo -dir service

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 = ["test.toml"],
importpath = "go-common/app/service/main/vipinfo/cmd",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/vipinfo/conf:go_default_library",
"//app/service/main/vipinfo/server/grpc:go_default_library",
"//app/service/main/vipinfo/server/http:go_default_library",
"//app/service/main/vipinfo/service:go_default_library",
"//library/log:go_default_library",
"//library/net/trace:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,49 @@
package main
import (
"context"
"flag"
"os"
"os/signal"
"syscall"
"time"
"go-common/app/service/main/vipinfo/conf"
grpc "go-common/app/service/main/vipinfo/server/grpc"
"go-common/app/service/main/vipinfo/server/http"
"go-common/app/service/main/vipinfo/service"
"go-common/library/log"
"go-common/library/net/trace"
)
func main() {
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
log.Init(conf.Conf.Log)
defer log.Close()
log.Info("vipinfo-service start")
trace.Init(conf.Conf.Tracer)
defer trace.Close()
svc := service.New(conf.Conf)
http.Init(conf.Conf, svc)
ws := grpc.New(conf.Conf.WardenServer, svc)
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
s := <-c
log.Info("get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
svc.Close()
ws.Shutdown(context.Background())
log.Info("vipinfo-service exit")
time.Sleep(time.Second)
return
case syscall.SIGHUP:
default:
return
}
}
}

View File

@@ -0,0 +1,42 @@
version = "3.0.0"
user = "nobody"
pid = "/tmp/vipinfo-service.pid"
dir = "./"
perf = "127.0.0.1:7910"
[bm]
addr = "0.0.0.0:7911"
maxListen = 1000
timeout = "1s"
[mysql]
addr = "172.16.33.205"
dsn = "zhaozhihao:MN9havOfnzY3kd6L78IVucRxgywe0p2P@tcp(172.16.33.205:3308)/bilibili_vip?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 5
idle = 5
IdleTimeout ="4h"
QueryTimeout = "5s"
ExecTimeout = "5s"
TranTimeout = "5s"
[mysql.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[memcache]
name = "vip-service"
proto = "tcp"
addr = "172.18.33.60:11234"
idle = 5
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "24h"
[wardenServer]
addr = "0.0.0.0:6077"
timeout = "1s"

View File

@@ -0,0 +1,39 @@
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/vipinfo/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/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/rpc/warden:go_default_library",
"//library/net/trace: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,92 @@
package conf
import (
"errors"
"flag"
"go-common/library/cache/memcache"
"go-common/library/conf"
"go-common/library/database/sql"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/rpc/warden"
"go-common/library/net/trace"
xtime "go-common/library/time"
"github.com/BurntSushi/toml"
)
var (
confPath string
client *conf.Client
// Conf config
Conf = &Config{}
)
// Config .
type Config struct {
Log *log.Config
BM *bm.ServerConfig
Tracer *trace.Config
Memcache *Memcache
MySQL *sql.Config
// grpc server
WardenServer *warden.ServerConfig
}
// Memcache config
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,64 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"cache.go",
"dao.cache.go",
"dao.go",
"mc.go",
"mysql.go",
],
importpath = "go-common/app/service/main/vipinfo/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/vipinfo/conf:go_default_library",
"//app/service/main/vipinfo/model:go_default_library",
"//library/cache:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/database/sql:go_default_library",
"//library/net/metadata:go_default_library",
"//library/stat/prom:go_default_library",
"//library/sync/errgroup:go_default_library",
"//library/xstr: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"],
)
go_test(
name = "go_default_test",
srcs = [
"dao.cache_test.go",
"dao_test.go",
"mc_test.go",
"mysql_test.go",
],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//app/service/main/vipinfo/conf:go_default_library",
"//app/service/main/vipinfo/model:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,16 @@
package dao
import (
"context"
"go-common/app/service/main/vipinfo/model"
)
// 注意 -check_null_code=$!=nil 生成的代码内容要去掉!
//go:generate $GOPATH/src/go-common/app/tool/cache/gen
type _cache interface {
// cache: -batch=50 -max_group=10 -batch_err=continue -nullcache=&model.VipUserInfo{VipType:0} -check_null_code=$!=nil
Infos(c context.Context, keys []int64) (map[int64]*model.VipUserInfo, error)
// cache: -nullcache=&model.VipUserInfo{VipType:0} -check_null_code=$!=nil
Info(c context.Context, key int64) (*model.VipUserInfo, error)
}

View File

@@ -0,0 +1,143 @@
// Code generated by $GOPATH/src/go-common/app/tool/cache/gen. DO NOT EDIT.
/*
Package dao is a generated cache proxy package.
It is generated from:
type _cache interface {
// cache: -batch=50 -max_group=10 -batch_err=continue -nullcache=&model.VipInfoDB{VipType:0} -check_null_code=$!=nil
Infos(c context.Context, keys []int64) (map[int64]*model.VipInfoDB, error)
// cache: -nullcache=&model.VipInfoDB{VipType:0} -check_null_code=$!=nil
Info(c context.Context, key int64) (*model.VipInfoDB, error)
}
*/
package dao
import (
"context"
"sync"
"go-common/app/service/main/vipinfo/model"
"go-common/library/net/metadata"
"go-common/library/stat/prom"
"go-common/library/sync/errgroup"
)
var _ _cache
// Infos get data from cache if miss will call source method, then add to cache.
func (d *Dao) Infos(c context.Context, keys []int64) (res map[int64]*model.VipUserInfo, err error) {
if len(keys) == 0 {
return
}
addCache := true
res, err = d.CacheInfos(c, keys)
if err != nil {
addCache = false
res = nil
err = nil
}
var miss []int64
for _, key := range keys {
if (res == nil) || (res[key] == nil) {
miss = append(miss, key)
}
}
prom.CacheHit.Add("Infos", int64(len(keys)-len(miss)))
if len(miss) == 0 {
return
}
var missData map[int64]*model.VipUserInfo
missLen := len(miss)
prom.CacheMiss.Add("Infos", int64(missLen))
mutex := sync.Mutex{}
for i := 0; i < missLen; i += 50 * 10 {
var subKeys []int64
group := &errgroup.Group{}
ctx := c
if (i + 50*10) > missLen {
subKeys = miss[i:]
} else {
subKeys = miss[i : i+50*10]
}
missSubLen := len(subKeys)
for j := 0; j < missSubLen; j += 50 {
var ks []int64
if (j + 50) > missSubLen {
ks = subKeys[j:]
} else {
ks = subKeys[j : j+50]
}
group.Go(func() (err error) {
data, err := d.RawInfos(ctx, ks)
mutex.Lock()
for k, v := range data {
if missData == nil {
missData = make(map[int64]*model.VipUserInfo, len(keys))
}
missData[k] = v
}
mutex.Unlock()
return
})
}
err1 := group.Wait()
if err1 != nil {
err = err1
}
}
if res == nil {
res = make(map[int64]*model.VipUserInfo)
}
for k, v := range missData {
res[k] = v
}
if err != nil {
return
}
for _, key := range keys {
if res[key] == nil {
if missData == nil {
missData = make(map[int64]*model.VipUserInfo, len(keys))
}
missData[key] = &model.VipUserInfo{VipType: 0, VipStatus: 0}
res[key] = missData[key]
}
}
if !addCache {
return
}
d.cache.Save(func() {
d.AddCacheInfos(metadata.WithContext(c), missData)
})
return
}
// Info get data from cache if miss will call source method, then add to cache.
func (d *Dao) Info(c context.Context, id int64) (res *model.VipUserInfo, err error) {
addCache := true
res, err = d.CacheInfo(c, id)
if err != nil {
addCache = false
err = nil
}
if res != nil {
prom.CacheHit.Incr("Info")
return
}
prom.CacheMiss.Incr("Info")
res, err = d.RawInfo(c, id)
if err != nil {
return
}
if res == nil {
res = &model.VipUserInfo{VipType: 0, VipStatus: 0}
}
if !addCache {
return
}
d.cache.Save(func() {
d.AddCacheInfo(metadata.WithContext(c), id, res)
})
return
}

View File

@@ -0,0 +1,56 @@
package dao
import (
"context"
"fmt"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoInfos(t *testing.T) {
convey.Convey("Infos", t, func(ctx convey.C) {
var (
c = context.Background()
keys = _testMids
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
for _, v := range keys {
err := d.DelInfoCache(c, v)
ctx.So(err, convey.ShouldBeNil)
}
res, err := d.Infos(c, keys)
fmt.Println("res", res)
time.Sleep(100 * time.Millisecond)
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)
})
_, err = d.Infos(c, keys)
ctx.So(err, convey.ShouldBeNil)
})
})
}
func TestDaoInfo(t *testing.T) {
convey.Convey("Info", t, func(ctx convey.C) {
var (
c = context.Background()
id = _testMid
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.DelInfoCache(c, _testMid)
ctx.So(err, convey.ShouldBeNil)
res, err := d.Info(c, id)
time.Sleep(100 * time.Millisecond)
fmt.Println("res", res.VipType, res.VipStatus)
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)
})
res, err = d.Info(c, id)
ctx.So(err, convey.ShouldBeNil)
})
})
}

View File

@@ -0,0 +1,50 @@
package dao
import (
"context"
"time"
"go-common/app/service/main/vipinfo/conf"
"go-common/library/cache"
"go-common/library/cache/memcache"
xsql "go-common/library/database/sql"
)
// Dao dao
type Dao struct {
c *conf.Config
// mc
mc *memcache.Pool
mcExpire int32
db *xsql.DB
// cache async save
cache *cache.Cache
}
// New init mysql db
func New(c *conf.Config) (dao *Dao) {
dao = &Dao{
c: c,
// mc
mc: memcache.NewPool(c.Memcache.Config),
mcExpire: int32(time.Duration(c.Memcache.Expire) / time.Second),
db: xsql.NewMySQL(c.MySQL),
// cache chan
cache: cache.New(1, 1024),
}
return
}
// Close close the resource.
func (d *Dao) Close() {
d.mc.Close()
d.db.Close()
}
// Ping dao ping
func (d *Dao) Ping(c context.Context) (err error) {
if err = d.pingMC(c); err != nil {
return
}
return d.db.Ping(c)
}

View File

@@ -0,0 +1,49 @@
package dao
import (
"context"
"flag"
"os"
"testing"
"go-common/app/service/main/vipinfo/conf"
"github.com/smartystreets/goconvey/convey"
)
var (
d *Dao
_testMid int64 = 1540883324
_testMids = []int64{1540883324, 1540883325, 1540883326}
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.account.vipinfo")
flag.Set("conf_token", "36fc5030a1e70fcac07edce2e941c506")
flag.Set("tree_id", "66732")
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/test.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
code := m.Run()
d.Close()
os.Exit(code)
}
func TestDaoPing(t *testing.T) {
convey.Convey("Ping", t, func(ctx convey.C) {
err := d.Ping(context.Background())
ctx.So(err, convey.ShouldBeNil)
})
}

View File

@@ -0,0 +1,213 @@
package dao
import (
"context"
"strconv"
"go-common/app/service/main/vipinfo/model"
mc "go-common/library/cache/memcache"
"github.com/pkg/errors"
)
const (
_prefixInfo = "i:"
_prefixFrozen = "vipfrozen:"
)
func keyInfo(mid int64) string {
return _prefixInfo + strconv.FormatInt(mid, 10)
}
func keyFrozen(mid int64) string {
return _prefixFrozen + strconv.FormatInt(mid, 10)
}
// pingMC ping memcache.
func (d *Dao) pingMC(c context.Context) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
err = conn.Set(&mc.Item{
Key: "ping",
Value: []byte("pong"),
})
return
}
// CacheInfo get vip info cache.
func (d *Dao) CacheInfo(c context.Context, mid int64) (v *model.VipUserInfo, err error) {
key := keyInfo(mid)
conn := d.mc.Get(c)
defer conn.Close()
r, err := conn.Get(key)
if err != nil {
if err == mc.ErrNotFound {
err = nil
return
}
err = errors.Wrapf(err, "dao cache info")
return
}
v = new(model.VipUserInfo)
if err = conn.Scan(r, v); err != nil {
err = errors.Wrapf(err, "dao cache scan info")
}
return
}
// AddCacheInfo add vip info cache.
func (d *Dao) AddCacheInfo(c context.Context, mid int64, v *model.VipUserInfo) (err error) {
item := &mc.Item{
Key: keyInfo(mid),
Object: v,
Expiration: d.mcExpire,
Flags: mc.FlagProtobuf,
}
conn := d.mc.Get(c)
err = conn.Set(item)
conn.Close()
if err != nil {
err = errors.Wrapf(err, "dao add cache info")
}
return
}
// CacheInfos multi get account info from cache.
func (d *Dao) CacheInfos(c context.Context, mids []int64) (res map[int64]*model.VipUserInfo, err error) {
keys := make([]string, 0, len(mids))
keyMidMap := make(map[string]int64, len(mids))
for _, mid := range mids {
key := keyInfo(mid)
if _, ok := keyMidMap[key]; !ok {
// duplicate mid
keyMidMap[key] = mid
keys = append(keys, key)
}
}
conn := d.mc.Get(c)
defer conn.Close()
rs, err := conn.GetMulti(keys)
if err != nil {
if err == mc.ErrNotFound {
err = nil
return
}
err = errors.Wrap(err, "dao infos cache")
return
}
res = make(map[int64]*model.VipUserInfo, len(mids))
for _, r := range rs {
ai := &model.VipUserInfo{}
conn.Scan(r, ai)
res[keyMidMap[r.Key]] = ai
}
return
}
// AddCacheInfos set account infos cache.
func (d *Dao) AddCacheInfos(c context.Context, vs map[int64]*model.VipUserInfo) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
for mid, i := range vs {
item := &mc.Item{
Key: keyInfo(mid),
Object: i,
Flags: mc.FlagProtobuf,
Expiration: d.mcExpire,
}
err = conn.Set(item)
if err != nil {
err = errors.Wrap(err, "dao add infos cache")
}
}
return
}
// CacheVipFrozens multi get vip frozens from cache.
func (d *Dao) CacheVipFrozens(c context.Context, mids []int64) (res map[int64]int, err error) {
keys := make([]string, 0, len(mids))
keyMidMap := make(map[string]int64, len(mids))
for _, mid := range mids {
key := keyFrozen(mid)
if _, ok := keyMidMap[key]; !ok {
// duplicate mid
keyMidMap[key] = mid
keys = append(keys, key)
}
}
conn := d.mc.Get(c)
defer conn.Close()
rs, err := conn.GetMulti(keys)
if err != nil {
if err == mc.ErrNotFound {
err = nil
return
}
err = errors.Wrap(err, "dao frozens cache")
return
}
res = make(map[int64]int, len(mids))
for _, r := range rs {
ai := 0
conn.Scan(r, &ai)
res[keyMidMap[r.Key]] = ai
}
return
}
//CacheVipFrozen get vip frozen flag.
func (d *Dao) CacheVipFrozen(c context.Context, mid int64) (val int, err error) {
key := keyFrozen(mid)
conn := d.mc.Get(c)
defer conn.Close()
item, err := conn.Get(key)
if err != nil {
if err == mc.ErrNotFound {
err = nil
return
}
err = errors.Wrapf(err, "dao cache frozen")
return
}
if err = conn.Scan(item, &val); err != nil {
err = errors.Wrapf(err, "dao cache scan frozen")
return
}
return
}
// AddCacheFrozen add cache frozen.
func (d *Dao) AddCacheFrozen(c context.Context, mid int64, vipFrozenFlag int) (err error) {
item := &mc.Item{
Key: keyFrozen(mid),
Object: vipFrozenFlag,
Expiration: d.mcExpire,
Flags: mc.FlagJSON,
}
conn := d.mc.Get(c)
err = conn.Set(item)
conn.Close()
if err != nil {
err = errors.Wrapf(err, "dao add cache frozen")
}
return
}
// DelInfoCache del vip info cache.
func (d *Dao) DelInfoCache(c context.Context, mid int64) (err error) {
d.delCache(c, keyInfo(mid))
return
}
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 == mc.ErrNotFound {
err = nil
} else {
err = errors.Wrapf(err, "del cache")
}
}
return
}

View File

@@ -0,0 +1,175 @@
package dao
import (
"context"
"fmt"
"testing"
"go-common/app/service/main/vipinfo/model"
"github.com/smartystreets/goconvey/convey"
)
func TestDaokeyInfo(t *testing.T) {
convey.Convey("keyInfo", t, func(ctx convey.C) {
var (
mid = _testMid
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := keyInfo(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaokeyFrozen(t *testing.T) {
convey.Convey("keyFrozen", t, func(ctx convey.C) {
var (
mid = _testMid
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := keyFrozen(mid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDaopingMC(t *testing.T) {
convey.Convey("pingMC", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.pingMC(c)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoCacheInfo(t *testing.T) {
convey.Convey("CacheInfo", t, func(ctx convey.C) {
var (
c = context.Background()
mid = _testMid
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
_, err := d.CacheInfo(c, mid)
ctx.Convey("Then err should be nil.v should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoAddCacheInfo(t *testing.T) {
convey.Convey("AddCacheInfo", t, func(ctx convey.C) {
var (
c = context.Background()
mid = _testMid
v = &model.VipUserInfo{Mid: _testMid, VipType: 1, VipStatus: 1}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.AddCacheInfo(c, mid, v)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoCacheInfos(t *testing.T) {
convey.Convey("CacheInfos", t, func(ctx convey.C) {
var (
c = context.Background()
mids = _testMids
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
for _, v := range mids {
err := d.DelInfoCache(c, v)
ctx.So(err, convey.ShouldBeNil)
}
res, err := d.CacheInfos(c, mids)
fmt.Println("item", res)
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 TestDaoAddCacheInfos(t *testing.T) {
convey.Convey("AddCacheInfos", t, func(ctx convey.C) {
var (
c = context.Background()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
vs := make(map[int64]*model.VipUserInfo)
vs[_testMid] = &model.VipUserInfo{Mid: _testMid, VipStatus: 1}
err := d.AddCacheInfos(c, vs)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoCacheVipFrozen(t *testing.T) {
convey.Convey("CacheVipFrozen", t, func(ctx convey.C) {
var (
c = context.Background()
mid = _testMid
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
val, err := d.CacheVipFrozen(c, mid)
fmt.Println("TestDaoCacheVipFrozen", val)
ctx.Convey("Then err should be nil.val should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(val, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoCacheVipFrozens(t *testing.T) {
convey.Convey("CacheVipFrozens", t, func(ctx convey.C) {
ctx.Convey("When everything goes positive", func(ctx convey.C) {
val, err := d.CacheVipFrozens(context.Background(), _testMids)
fmt.Println("TestDaoCacheVipFrozens", val)
ctx.Convey("Then err should be nil.val should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(val, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoAddCacheFrozen(t *testing.T) {
convey.Convey("AddCacheFrozen", t, func(ctx convey.C) {
var c = context.Background()
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.AddCacheFrozen(c, 1540883325, 1)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoDelInfoCache(t *testing.T) {
convey.Convey("DelInfoCache", t, func(ctx convey.C) {
var c = context.Background()
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.DelInfoCache(c, _testMid)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,58 @@
package dao
import (
"context"
"database/sql"
"fmt"
"go-common/app/service/main/vipinfo/model"
xsql "go-common/library/database/sql"
"go-common/library/xstr"
"github.com/pkg/errors"
)
const (
_byMidSQL = "SELECT id,mid,vip_type,vip_pay_type,vip_status,pay_channel_id,vip_start_time,vip_overdue_time,annual_vip_overdue_time,ctime,mtime,vip_recent_time,ios_overdue_time,ver FROM vip_user_info WHERE mid = ?;"
_byMidsSQL = "SELECT id,mid,vip_type,vip_pay_type,vip_status,pay_channel_id,vip_start_time,vip_overdue_time,annual_vip_overdue_time,ctime,mtime,vip_recent_time,ios_overdue_time,ver FROM vip_user_info WHERE mid IN (%s);"
)
//RawInfo select user info by mid.
func (d *Dao) RawInfo(c context.Context, mid int64) (r *model.VipUserInfo, err error) {
var row = d.db.QueryRow(c, _byMidSQL, mid)
r = new(model.VipUserInfo)
if err = row.Scan(&r.ID, &r.Mid, &r.VipType, &r.VipPayType, &r.VipStatus, &r.PayChannelID, &r.VipStartTime, &r.VipOverdueTime, &r.AnnualVipOverdueTime,
&r.Ctime, &r.Mtime, &r.VipRecentTime, &r.IosOverdueTime, &r.Ver); err != nil {
if err == sql.ErrNoRows {
r = nil
err = nil
return
}
err = errors.Wrapf(err, "dao info bymid(%d)", mid)
}
return
}
// RawInfos get user infos.
func (d *Dao) RawInfos(c context.Context, mids []int64) (res map[int64]*model.VipUserInfo, err error) {
var rows *xsql.Rows
res = make(map[int64]*model.VipUserInfo, len(mids))
midStr := xstr.JoinInts(mids)
if rows, err = d.db.Query(c, fmt.Sprintf(_byMidsSQL, midStr)); err != nil {
err = errors.Wrapf(err, "dao infos mids(%s)", midStr)
return
}
defer rows.Close()
for rows.Next() {
r := new(model.VipUserInfo)
if err = rows.Scan(&r.ID, &r.Mid, &r.VipType, &r.VipPayType, &r.VipStatus, &r.PayChannelID, &r.VipStartTime, &r.VipOverdueTime, &r.AnnualVipOverdueTime,
&r.Ctime, &r.Mtime, &r.VipRecentTime, &r.IosOverdueTime, &r.Ver); err != nil {
err = errors.Wrapf(err, "dao infos scan mids(%s)", midStr)
res = nil
return
}
res[r.Mid] = r
}
err = rows.Err()
return
}

View File

@@ -0,0 +1,40 @@
package dao
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoRawInfo(t *testing.T) {
convey.Convey("RawInfo", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(2089809)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
r, err := d.RawInfo(c, mid)
ctx.Convey("Then err should be nil.r should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(r, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoRawInfos(t *testing.T) {
convey.Convey("RawInfos", t, func(ctx convey.C) {
var (
c = context.Background()
mids = []int64{2089809, 1540883324, 1540818280}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.RawInfos(c, mids)
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)
})
})
})
}

View File

@@ -0,0 +1,61 @@
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 = "model_proto",
srcs = ["model.proto"],
tags = ["automanaged"],
deps = ["@gogo_special_proto//github.com/gogo/protobuf/gogoproto"],
)
go_proto_library(
name = "model_go_proto",
compilers = ["@io_bazel_rules_go//proto:gogofast_proto"],
importpath = "go-common/app/service/main/vipinfo/model",
proto = ":model_proto",
tags = ["automanaged"],
deps = [
"//library/time:go_default_library",
"@com_github_gogo_protobuf//gogoproto:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"model.go",
"param.go",
],
embed = [":model_go_proto"],
importpath = "go-common/app/service/main/vipinfo/model",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/time:go_default_library",
"@com_github_gogo_protobuf//gogoproto:go_default_library",
"@com_github_gogo_protobuf//proto: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,27 @@
package model
// 大会员类型
const (
NotVip = 0 //非大会员
Vip = 1 //月度大会员
AnnualVip = 2 //年度会员
)
// 大会员状态
const (
VipStatusOverTime = 0 //过期
VipStatusNotOverTime = 1 //未过期
VipStatusFrozen = 2 //冻结
VipStatusBan = 3 //封禁
)
// vip pay type.
const (
NormalPay int32 = iota
AutoRenewPay
)
// pay channel id
const (
IapPayChannelID = 100
)

View File

@@ -0,0 +1,676 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: app/service/main/vipinfo/model/model.proto
/*
Package model is a generated protocol buffer package.
It is generated from these files:
app/service/main/vipinfo/model/model.proto
It has these top-level messages:
VipUserInfo
*/
package model
import proto "github.com/gogo/protobuf/proto"
import fmt "fmt"
import math "math"
import _ "github.com/gogo/protobuf/gogoproto"
import go_common_library_time "go-common/library/time"
import io "io"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
type VipUserInfo struct {
ID int64 `protobuf:"varint,1,opt,name=ID,proto3" json:"id"`
Mid int64 `protobuf:"varint,2,opt,name=Mid,proto3" json:"mid"`
VipType int32 `protobuf:"varint,3,opt,name=VipType,proto3" json:"vip_type"`
VipPayType int32 `protobuf:"varint,4,opt,name=VipPayType,proto3" json:"vip_pay_type"`
PayChannelID int32 `protobuf:"varint,5,opt,name=PayChannelID,proto3" json:"pay_channel_id"`
VipStatus int32 `protobuf:"varint,6,opt,name=VipStatus,proto3" json:"vip_status"`
VipStartTime go_common_library_time.Time `protobuf:"varint,7,opt,name=VipStartTime,proto3,casttype=go-common/library/time.Time" json:"vip_start_time"`
VipRecentTime go_common_library_time.Time `protobuf:"varint,8,opt,name=VipRecentTime,proto3,casttype=go-common/library/time.Time" json:"vip_recent_time"`
VipOverdueTime go_common_library_time.Time `protobuf:"varint,9,opt,name=VipOverdueTime,proto3,casttype=go-common/library/time.Time" json:"vip_overdue_time"`
AnnualVipOverdueTime go_common_library_time.Time `protobuf:"varint,10,opt,name=AnnualVipOverdueTime,proto3,casttype=go-common/library/time.Time" json:"annual_vip_overdue_time"`
Ctime go_common_library_time.Time `protobuf:"varint,11,opt,name=Ctime,proto3,casttype=go-common/library/time.Time" json:"ctime"`
Mtime go_common_library_time.Time `protobuf:"varint,12,opt,name=Mtime,proto3,casttype=go-common/library/time.Time" json:"mtime"`
IosOverdueTime go_common_library_time.Time `protobuf:"varint,13,opt,name=IosOverdueTime,proto3,casttype=go-common/library/time.Time" json:"ios_overdue_time"`
Ver int64 `protobuf:"varint,14,opt,name=Ver,proto3" json:"ver"`
}
func (m *VipUserInfo) Reset() { *m = VipUserInfo{} }
func (m *VipUserInfo) String() string { return proto.CompactTextString(m) }
func (*VipUserInfo) ProtoMessage() {}
func (*VipUserInfo) Descriptor() ([]byte, []int) { return fileDescriptorModel, []int{0} }
func init() {
proto.RegisterType((*VipUserInfo)(nil), "account.service.vipinfo.VipUserInfo")
}
func (m *VipUserInfo) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalTo(dAtA)
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *VipUserInfo) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if m.ID != 0 {
dAtA[i] = 0x8
i++
i = encodeVarintModel(dAtA, i, uint64(m.ID))
}
if m.Mid != 0 {
dAtA[i] = 0x10
i++
i = encodeVarintModel(dAtA, i, uint64(m.Mid))
}
if m.VipType != 0 {
dAtA[i] = 0x18
i++
i = encodeVarintModel(dAtA, i, uint64(m.VipType))
}
if m.VipPayType != 0 {
dAtA[i] = 0x20
i++
i = encodeVarintModel(dAtA, i, uint64(m.VipPayType))
}
if m.PayChannelID != 0 {
dAtA[i] = 0x28
i++
i = encodeVarintModel(dAtA, i, uint64(m.PayChannelID))
}
if m.VipStatus != 0 {
dAtA[i] = 0x30
i++
i = encodeVarintModel(dAtA, i, uint64(m.VipStatus))
}
if m.VipStartTime != 0 {
dAtA[i] = 0x38
i++
i = encodeVarintModel(dAtA, i, uint64(m.VipStartTime))
}
if m.VipRecentTime != 0 {
dAtA[i] = 0x40
i++
i = encodeVarintModel(dAtA, i, uint64(m.VipRecentTime))
}
if m.VipOverdueTime != 0 {
dAtA[i] = 0x48
i++
i = encodeVarintModel(dAtA, i, uint64(m.VipOverdueTime))
}
if m.AnnualVipOverdueTime != 0 {
dAtA[i] = 0x50
i++
i = encodeVarintModel(dAtA, i, uint64(m.AnnualVipOverdueTime))
}
if m.Ctime != 0 {
dAtA[i] = 0x58
i++
i = encodeVarintModel(dAtA, i, uint64(m.Ctime))
}
if m.Mtime != 0 {
dAtA[i] = 0x60
i++
i = encodeVarintModel(dAtA, i, uint64(m.Mtime))
}
if m.IosOverdueTime != 0 {
dAtA[i] = 0x68
i++
i = encodeVarintModel(dAtA, i, uint64(m.IosOverdueTime))
}
if m.Ver != 0 {
dAtA[i] = 0x70
i++
i = encodeVarintModel(dAtA, i, uint64(m.Ver))
}
return i, nil
}
func encodeVarintModel(dAtA []byte, offset int, v uint64) int {
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return offset + 1
}
func (m *VipUserInfo) Size() (n int) {
var l int
_ = l
if m.ID != 0 {
n += 1 + sovModel(uint64(m.ID))
}
if m.Mid != 0 {
n += 1 + sovModel(uint64(m.Mid))
}
if m.VipType != 0 {
n += 1 + sovModel(uint64(m.VipType))
}
if m.VipPayType != 0 {
n += 1 + sovModel(uint64(m.VipPayType))
}
if m.PayChannelID != 0 {
n += 1 + sovModel(uint64(m.PayChannelID))
}
if m.VipStatus != 0 {
n += 1 + sovModel(uint64(m.VipStatus))
}
if m.VipStartTime != 0 {
n += 1 + sovModel(uint64(m.VipStartTime))
}
if m.VipRecentTime != 0 {
n += 1 + sovModel(uint64(m.VipRecentTime))
}
if m.VipOverdueTime != 0 {
n += 1 + sovModel(uint64(m.VipOverdueTime))
}
if m.AnnualVipOverdueTime != 0 {
n += 1 + sovModel(uint64(m.AnnualVipOverdueTime))
}
if m.Ctime != 0 {
n += 1 + sovModel(uint64(m.Ctime))
}
if m.Mtime != 0 {
n += 1 + sovModel(uint64(m.Mtime))
}
if m.IosOverdueTime != 0 {
n += 1 + sovModel(uint64(m.IosOverdueTime))
}
if m.Ver != 0 {
n += 1 + sovModel(uint64(m.Ver))
}
return n
}
func sovModel(x uint64) (n int) {
for {
n++
x >>= 7
if x == 0 {
break
}
}
return n
}
func sozModel(x uint64) (n int) {
return sovModel(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *VipUserInfo) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModel
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: VipUserInfo: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: VipUserInfo: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
}
m.ID = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModel
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.ID |= (int64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 2:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Mid", wireType)
}
m.Mid = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModel
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Mid |= (int64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field VipType", wireType)
}
m.VipType = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModel
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.VipType |= (int32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 4:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field VipPayType", wireType)
}
m.VipPayType = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModel
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.VipPayType |= (int32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 5:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field PayChannelID", wireType)
}
m.PayChannelID = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModel
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.PayChannelID |= (int32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 6:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field VipStatus", wireType)
}
m.VipStatus = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModel
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.VipStatus |= (int32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 7:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field VipStartTime", wireType)
}
m.VipStartTime = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModel
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.VipStartTime |= (go_common_library_time.Time(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 8:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field VipRecentTime", wireType)
}
m.VipRecentTime = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModel
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.VipRecentTime |= (go_common_library_time.Time(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 9:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field VipOverdueTime", wireType)
}
m.VipOverdueTime = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModel
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.VipOverdueTime |= (go_common_library_time.Time(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 10:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field AnnualVipOverdueTime", wireType)
}
m.AnnualVipOverdueTime = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModel
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.AnnualVipOverdueTime |= (go_common_library_time.Time(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 11:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Ctime", wireType)
}
m.Ctime = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModel
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Ctime |= (go_common_library_time.Time(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 12:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Mtime", wireType)
}
m.Mtime = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModel
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Mtime |= (go_common_library_time.Time(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 13:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field IosOverdueTime", wireType)
}
m.IosOverdueTime = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModel
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.IosOverdueTime |= (go_common_library_time.Time(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 14:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Ver", wireType)
}
m.Ver = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowModel
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Ver |= (int64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skipModel(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthModel
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipModel(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowModel
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowModel
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
return iNdEx, nil
case 1:
iNdEx += 8
return iNdEx, nil
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowModel
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
iNdEx += length
if length < 0 {
return 0, ErrInvalidLengthModel
}
return iNdEx, nil
case 3:
for {
var innerWire uint64
var start int = iNdEx
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowModel
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
innerWire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
innerWireType := int(innerWire & 0x7)
if innerWireType == 4 {
break
}
next, err := skipModel(dAtA[start:])
if err != nil {
return 0, err
}
iNdEx = start + next
}
return iNdEx, nil
case 4:
return iNdEx, nil
case 5:
iNdEx += 4
return iNdEx, nil
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
}
panic("unreachable")
}
var (
ErrInvalidLengthModel = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowModel = fmt.Errorf("proto: integer overflow")
)
func init() { proto.RegisterFile("app/service/main/vipinfo/model/model.proto", fileDescriptorModel) }
var fileDescriptorModel = []byte{
// 518 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x93, 0x41, 0x6b, 0xdb, 0x30,
0x1c, 0xc5, 0xeb, 0x64, 0x49, 0x5b, 0x35, 0xcd, 0x8a, 0x18, 0xab, 0xb7, 0x42, 0x54, 0x76, 0x18,
0x61, 0xac, 0xf1, 0xb6, 0xc2, 0x0e, 0x3b, 0x0c, 0x96, 0xe6, 0x92, 0x43, 0x59, 0xf1, 0x5a, 0x33,
0xb6, 0x43, 0x50, 0x6c, 0x25, 0x15, 0xc4, 0x92, 0x90, 0xed, 0x80, 0xbf, 0x61, 0x8f, 0xfd, 0x04,
0x62, 0xcd, 0x51, 0x1f, 0x60, 0x87, 0x9d, 0x86, 0xfe, 0xce, 0x48, 0x53, 0x76, 0x48, 0x2f, 0xc6,
0xd2, 0x7b, 0xef, 0xf7, 0xd0, 0x1f, 0xfe, 0xe8, 0x0d, 0x55, 0x2a, 0xc8, 0x98, 0x9e, 0xf3, 0x98,
0x05, 0x29, 0xe5, 0x22, 0x98, 0x73, 0xc5, 0xc5, 0x44, 0x06, 0xa9, 0x4c, 0xd8, 0xac, 0xfa, 0xf6,
0x94, 0x96, 0xb9, 0xc4, 0x87, 0x34, 0x8e, 0x65, 0x21, 0xf2, 0xde, 0xd2, 0xdf, 0x5b, 0x5a, 0x5f,
0x9e, 0x4c, 0x79, 0x7e, 0x5d, 0x8c, 0x7b, 0xb1, 0x4c, 0x83, 0xa9, 0x9c, 0xca, 0x00, 0xfc, 0xe3,
0x62, 0x02, 0x27, 0x38, 0xc0, 0x5f, 0xc5, 0x79, 0xf5, 0xbb, 0x89, 0xf6, 0x22, 0xae, 0xae, 0x32,
0xa6, 0x87, 0x62, 0x22, 0xf1, 0x73, 0x54, 0x1b, 0x0e, 0x7c, 0xef, 0xd8, 0xeb, 0xd6, 0xfb, 0x4d,
0x6b, 0x48, 0x8d, 0x27, 0x61, 0x6d, 0x38, 0xc0, 0x2f, 0x50, 0xfd, 0x9c, 0x27, 0x7e, 0x0d, 0x84,
0x6d, 0x6b, 0x48, 0x3d, 0xe5, 0x49, 0xe8, 0xee, 0xf0, 0x6b, 0xb4, 0x1d, 0x71, 0x75, 0x59, 0x2a,
0xe6, 0xd7, 0x8f, 0xbd, 0x6e, 0xa3, 0xdf, 0xb2, 0x86, 0xec, 0xcc, 0xb9, 0x1a, 0xe5, 0xa5, 0x62,
0xe1, 0x3f, 0x11, 0xbf, 0x43, 0x28, 0xe2, 0xea, 0x82, 0x96, 0x60, 0x7d, 0x02, 0xd6, 0x03, 0x6b,
0x48, 0xcb, 0x59, 0x15, 0x2d, 0x2b, 0xfb, 0x3d, 0x0f, 0xfe, 0x88, 0x5a, 0x17, 0xb4, 0x3c, 0xbb,
0xa6, 0x42, 0xb0, 0xd9, 0x70, 0xe0, 0x37, 0x20, 0x83, 0xad, 0x21, 0x6d, 0xe7, 0x8f, 0x2b, 0x61,
0xc4, 0x93, 0x70, 0xcd, 0x87, 0xdf, 0xa2, 0xdd, 0x88, 0xab, 0x6f, 0x39, 0xcd, 0x8b, 0xcc, 0x6f,
0x42, 0xa8, 0x6d, 0x0d, 0x41, 0xae, 0x28, 0x83, 0xdb, 0x70, 0x65, 0xc0, 0x57, 0xa8, 0x55, 0x1d,
0x74, 0x7e, 0xc9, 0x53, 0xe6, 0x6f, 0xc3, 0x1b, 0xdf, 0xbb, 0x96, 0x65, 0x40, 0xe7, 0xa3, 0x9c,
0xa7, 0xec, 0x8f, 0x21, 0x47, 0x53, 0x79, 0x12, 0xcb, 0x34, 0x95, 0x22, 0x98, 0xf1, 0xb1, 0xa6,
0xba, 0x0c, 0x9c, 0xd2, 0x73, 0xc1, 0x70, 0x0d, 0x83, 0xbf, 0xa3, 0xfd, 0x88, 0xab, 0x90, 0xc5,
0x4c, 0x54, 0xdc, 0x1d, 0xe0, 0x7e, 0xb0, 0x86, 0x3c, 0x75, 0x5c, 0x0d, 0xca, 0x46, 0xe0, 0x75,
0x10, 0xfe, 0x89, 0xda, 0x11, 0x57, 0x5f, 0xe7, 0x4c, 0x27, 0x05, 0x03, 0xf4, 0x2e, 0xa0, 0x4f,
0xad, 0x21, 0x07, 0x0e, 0x2d, 0x2b, 0x69, 0x23, 0xf6, 0x03, 0x14, 0x16, 0xe8, 0xd9, 0x17, 0x21,
0x0a, 0x3a, 0x7b, 0x50, 0x81, 0xa0, 0xe2, 0x93, 0x35, 0xe4, 0x90, 0x82, 0x3e, 0x7a, 0x6c, 0xd3,
0x7f, 0xb9, 0xf8, 0x33, 0x6a, 0x9c, 0x39, 0x8f, 0xbf, 0x07, 0x05, 0x5d, 0x6b, 0x48, 0x23, 0xde,
0x04, 0x57, 0xc5, 0x5c, 0xfe, 0x1c, 0xf2, 0xad, 0x55, 0x3e, 0xdd, 0x28, 0x0f, 0x31, 0x37, 0xcc,
0xa1, 0xcc, 0xee, 0xbf, 0x74, 0x7f, 0x35, 0x4c, 0x2e, 0xb3, 0xc7, 0x0d, 0x73, 0x1d, 0xe5, 0xb6,
0x26, 0x62, 0xda, 0x6f, 0xaf, 0xb6, 0x66, 0xce, 0x74, 0xe8, 0xee, 0xfa, 0x47, 0x37, 0x77, 0x9d,
0xad, 0xdb, 0xbb, 0xce, 0xd6, 0xcd, 0xa2, 0xe3, 0xdd, 0x2e, 0x3a, 0xde, 0xaf, 0x45, 0xc7, 0xfb,
0xd1, 0x80, 0x1d, 0x1f, 0x37, 0x61, 0x39, 0x4f, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x66, 0x63,
0x27, 0x4e, 0x12, 0x04, 0x00, 0x00,
}

View File

@@ -0,0 +1,29 @@
syntax = "proto3";
package account.service.vipinfo;
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
option go_package = "model";
option (gogoproto.goproto_enum_prefix_all) = false;
option (gogoproto.goproto_getters_all) = false;
option (gogoproto.unmarshaler_all) = true;
option (gogoproto.marshaler_all) = true;
option (gogoproto.sizer_all) = true;
message VipUserInfo {
int64 ID = 1 [(gogoproto.jsontag) = "id"];
int64 Mid = 2 [(gogoproto.jsontag) = "mid"];
int32 VipType = 3 [(gogoproto.jsontag) = "vip_type"];
int32 VipPayType = 4 [(gogoproto.jsontag) = "vip_pay_type"];
int32 PayChannelID = 5 [(gogoproto.jsontag) = "pay_channel_id"];
int32 VipStatus = 6 [(gogoproto.jsontag) = "vip_status"];
int64 VipStartTime = 7 [(gogoproto.jsontag) = "vip_start_time", (gogoproto.casttype) = "go-common/library/time.Time"];
int64 VipRecentTime = 8 [(gogoproto.jsontag) = "vip_recent_time", (gogoproto.casttype) = "go-common/library/time.Time"];
int64 VipOverdueTime = 9 [(gogoproto.jsontag) = "vip_overdue_time", (gogoproto.casttype) = "go-common/library/time.Time"];
int64 AnnualVipOverdueTime = 10 [(gogoproto.jsontag) = "annual_vip_overdue_time", (gogoproto.casttype) = "go-common/library/time.Time"];
int64 Ctime = 11 [(gogoproto.jsontag) = "ctime", (gogoproto.casttype) = "go-common/library/time.Time"];
int64 Mtime = 12 [(gogoproto.jsontag) = "mtime", (gogoproto.casttype) = "go-common/library/time.Time"];
int64 IosOverdueTime = 13 [(gogoproto.jsontag) = "ios_overdue_time", (gogoproto.casttype) = "go-common/library/time.Time"];
int64 Ver = 14 [(gogoproto.jsontag) = "ver"];
}

View File

@@ -0,0 +1,11 @@
package model
// ArgMid arg mid.
type ArgMid struct {
Mid int64 `form:"mid" validate:"required,min=1,gte=1"`
}
// ArgMids card mids arg.
type ArgMids struct {
Mids []int64 `form:"mids,split" validate:"min=1,max=100"`
}

View File

@@ -0,0 +1,33 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["server.go"],
importpath = "go-common/app/service/main/vipinfo/server/grpc",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/vipinfo/api:go_default_library",
"//app/service/main/vipinfo/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,45 @@
// Package server generate by warden_gen
package server
import (
"context"
v1 "go-common/app/service/main/vipinfo/api"
service "go-common/app/service/main/vipinfo/service"
"go-common/library/net/rpc/warden"
)
// New VipInfo warden rpc server
func New(c *warden.ServerConfig, svr *service.Service) *warden.Server {
ws := warden.NewServer(c)
v1.RegisterVipInfoServer(ws.Server(), &server{svr})
ws, err := ws.Start()
if err != nil {
panic(err)
}
return ws
}
type server struct {
svr *service.Service
}
var _ v1.VipInfoServer = &server{}
// Info get vipinfo by mid.
func (s *server) Info(ctx context.Context, req *v1.InfoReq) (res *v1.InfoReply, err error) {
var info *v1.ModelInfo
if info, err = s.svr.Info(ctx, req.Mid); err != nil {
return
}
return &v1.InfoReply{Res: info}, nil
}
// Infos get vipinfos by mids
func (s *server) Infos(ctx context.Context, req *v1.InfosReq) (res *v1.InfosReply, err error) {
var infos map[int64]*v1.ModelInfo
if infos, err = s.svr.Infos(ctx, req.Mids); err != nil {
return
}
return &v1.InfosReply{Res: infos}, nil
}

View File

@@ -0,0 +1,39 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"http.go",
"info.go",
],
importpath = "go-common/app/service/main/vipinfo/server/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/vipinfo/conf:go_default_library",
"//app/service/main/vipinfo/model:go_default_library",
"//app/service/main/vipinfo/service:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/middleware/verify:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,49 @@
package http
import (
"net/http"
"go-common/app/service/main/vipinfo/conf"
"go-common/app/service/main/vipinfo/service"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/verify"
)
var (
srv *service.Service
verifySvc *verify.Verify
)
// Init init
func Init(c *conf.Config, s *service.Service) {
srv = s
verifySvc = verify.New(nil)
engine := bm.DefaultServer(c.BM)
route(engine)
if err := engine.Start(); err != nil {
log.Error("bm Start error(%v)", err)
panic(err)
}
}
func route(e *bm.Engine) {
e.Ping(ping)
e.Register(register)
g := e.Group("/x/internal/vipinfo", verifySvc.Verify)
{
g.GET("/info", info)
g.GET("/infos", infos)
}
}
func ping(c *bm.Context) {
if err := srv.Ping(c); err != nil {
log.Error("ping error(%v)", err)
c.AbortWithStatus(http.StatusServiceUnavailable)
}
}
func register(c *bm.Context) {
c.JSON(map[string]interface{}{}, nil)
}

View File

@@ -0,0 +1,24 @@
package http
import (
"go-common/app/service/main/vipinfo/model"
bm "go-common/library/net/http/blademaster"
)
func info(c *bm.Context) {
var err error
arg := new(model.ArgMid)
if err = c.Bind(arg); err != nil {
return
}
c.JSON(srv.Info(c, arg.Mid))
}
func infos(c *bm.Context) {
var err error
arg := new(model.ArgMids)
if err = c.Bind(arg); err != nil {
return
}
c.JSON(srv.Infos(c, arg.Mids))
}

View File

@@ -0,0 +1,52 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"info.go",
"service.go",
"utils.go",
],
importpath = "go-common/app/service/main/vipinfo/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/main/vipinfo/api:go_default_library",
"//app/service/main/vipinfo/conf:go_default_library",
"//app/service/main/vipinfo/dao:go_default_library",
"//app/service/main/vipinfo/model:go_default_library",
"//library/ecode: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"],
)
go_test(
name = "go_default_test",
srcs = ["info_test.go"],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//app/service/main/vipinfo/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,136 @@
package service
import (
"context"
"time"
v1 "go-common/app/service/main/vipinfo/api"
"go-common/app/service/main/vipinfo/model"
"go-common/library/ecode"
"go-common/library/log"
)
// Info get vipinfo by mid.
func (s *Service) Info(c context.Context, mid int64) (res *v1.ModelInfo, err error) {
res = new(v1.ModelInfo)
if mid <= 0 {
return
}
var vdb *model.VipUserInfo
if vdb, err = s.dao.Info(c, mid); err != nil {
return
}
if vdb == nil {
return
}
s.logicVipInfo(c, vdb, time.Now())
s.logicFrozen(c, vdb)
res = s.convertInfo(vdb)
return
}
// Infos get vipinfos by mids
func (s *Service) Infos(c context.Context, mids []int64) (res map[int64]*v1.ModelInfo, err error) {
res = make(map[int64]*v1.ModelInfo, len(mids))
if len(mids) <= 0 {
return
}
if len(mids) > 100 {
err = ecode.RequestErr
return
}
var vs map[int64]*model.VipUserInfo
if vs, err = s.dao.Infos(c, mids); err != nil {
return
}
var now = time.Now()
for _, v := range vs {
if v == nil {
continue
}
s.logicVipInfo(c, v, now)
}
s.logicFrozens(c, vs)
for mid, v := range vs {
res[mid] = s.convertInfo(v)
}
return
}
func (s *Service) logicVipInfo(c context.Context, v *model.VipUserInfo, now time.Time) {
if v.VipType != model.Vip && v.VipType != model.AnnualVip {
return
}
if !v.AnnualVipOverdueTime.Time().IsZero() && v.AnnualVipOverdueTime.Time().Before(now) {
v.VipType = model.Vip
}
if !v.VipOverdueTime.Time().IsZero() && v.VipOverdueTime.Time().Before(now) {
v.VipStatus = model.VipStatusOverTime
}
/**
* 因目前无法获取iap实际的签约状态
* 超过下次扣费时间+48h的那一天的24点即is_auto_renew=0
*/
if v.PayChannelID == model.IapPayChannelID &&
v.VipPayType == model.AutoRenewPay &&
!v.IosOverdueTime.Time().IsZero() &&
endOfDay(v.IosOverdueTime.Time().AddDate(0, 0, 2)).Before(time.Now()) {
v.VipPayType = model.NormalPay
}
}
//TODO 冻结逻辑 二期会再次进行改造(依赖增加vip-cache-job及冻结状态落库)
func (s *Service) logicFrozen(c context.Context, v *model.VipUserInfo) (err error) {
var flag int
if v.VipStatus == model.VipStatusNotOverTime {
if flag, err = s.dao.CacheVipFrozen(c, v.Mid); err != nil {
log.Error("get vip frozen err(%+v)", err)
err = nil
}
if flag == 1 {
v.VipStatus = model.VipStatusFrozen
}
}
return
}
//TODO 冻结逻辑 二期会再次进行改造(依赖增加vip-cache-job及冻结状态落库)
func (s *Service) logicFrozens(c context.Context, vs map[int64]*model.VipUserInfo) (err error) {
var (
frozenFmap map[int64]int
mids = []int64{}
flag int
)
for _, v := range vs {
if v.VipStatus == model.VipStatusNotOverTime {
mids = append(mids, v.Mid)
}
}
if len(mids) > 0 {
if frozenFmap, err = s.dao.CacheVipFrozens(c, mids); err != nil {
log.Error("get vip frozens err(%+v)", err)
err = nil
}
if len(frozenFmap) == 0 {
return
}
for mid, v := range vs {
if flag = frozenFmap[mid]; flag == 1 {
v.VipStatus = model.VipStatusFrozen
}
}
}
return
}
func (s *Service) convertInfo(v *model.VipUserInfo) (res *v1.ModelInfo) {
res = new(v1.ModelInfo)
res.VipPayType = v.VipPayType
res.Type = v.VipType
res.Status = v.VipStatus
if !v.VipOverdueTime.Time().IsZero() {
// 返回的过期时间戳与以前保持一致,单位:毫秒
res.DueDate = v.VipOverdueTime.Time().Unix() * 1000
}
return
}

View File

@@ -0,0 +1,53 @@
package service
import (
"context"
"flag"
"fmt"
"testing"
"time"
"go-common/app/service/main/vipinfo/conf"
. "github.com/smartystreets/goconvey/convey"
)
var (
c = context.TODO()
s *Service
)
func init() {
var (
err error
)
flag.Set("conf", "../cmd/test.toml")
if err = conf.Init(); err != nil {
panic(err)
}
c = context.Background()
if s == nil {
s = New(conf.Conf)
}
time.Sleep(time.Second)
}
// go test -test.v -test.run TestInfo
func TestInfo(t *testing.T) {
Convey("TestInfo ", t, func() {
info, err := s.Info(c, 27515795)
fmt.Println("info:", info)
fmt.Println("err:", err)
So(err, ShouldBeNil)
})
}
// go test -test.v -test.run TestInfos
func TestInfos(t *testing.T) {
Convey("TestInfos ", t, func() {
info, err := s.Infos(c, []int64{27515795, 1})
fmt.Println("info:", info)
fmt.Println("err:", err)
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,33 @@
package service
import (
"context"
"go-common/app/service/main/vipinfo/conf"
"go-common/app/service/main/vipinfo/dao"
)
// Service struct
type Service struct {
c *conf.Config
dao *dao.Dao
}
// New init
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
dao: dao.New(c),
}
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()
}

View File

@@ -0,0 +1,9 @@
package service
import "time"
// endOfDay end of day
func endOfDay(t time.Time) time.Time {
y, m, d := t.Date()
return time.Date(y, m, d, 23, 59, 59, int(time.Second-time.Nanosecond), t.Location())
}