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,21 @@
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/job/live/xlottery/cmd:all-srcs",
"//app/job/live/xlottery/internal/conf:all-srcs",
"//app/job/live/xlottery/internal/dao:all-srcs",
"//app/job/live/xlottery/internal/model:all-srcs",
"//app/job/live/xlottery/internal/server/http:all-srcs",
"//app/job/live/xlottery/internal/service:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,5 @@
### v1.0.0
1. 上线功能xxx
2. 添加redis日志
3. 修改redis错误
4. 修改获取扭蛋无新增错误

View File

@@ -0,0 +1,15 @@
# Owner
zhaohailin
longsifan
libaolin
hongshengjie
# Author
baojuntao
longsifan
# Reviewer
longsifan
libaolin
zhaohailin
hongshengjie

View File

@@ -0,0 +1,20 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- baojuntao
- hongshengjie
- libaolin
- longsifan
- zhaohailin
labels:
- job
- job/live/xlottery
- live
options:
no_parent_owners: true
reviewers:
- baojuntao
- hongshengjie
- libaolin
- longsifan
- zhaohailin

View File

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

View File

@@ -0,0 +1 @@
# HTTP API文档

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/job/live/xlottery/cmd",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/live/xlottery/internal/conf:go_default_library",
"//app/job/live/xlottery/internal/server/http:go_default_library",
"//app/job/live/xlottery/internal/service:go_default_library",
"//library/ecode/tip: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,47 @@
package main
import (
"flag"
"os"
"os/signal"
"syscall"
"time"
"go-common/app/job/live/xlottery/internal/conf"
"go-common/app/job/live/xlottery/internal/server/http"
"go-common/app/job/live/xlottery/internal/service"
ecode "go-common/library/ecode/tip"
"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("xlottery-job start")
trace.Init(conf.Conf.Tracer)
defer trace.Close()
ecode.Init(conf.Conf.Ecode)
svc := service.New(conf.Conf)
http.Init(conf.Conf, 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()
log.Info("xlottery-job exit")
time.Sleep(time.Second)
return
case syscall.SIGHUP:
default:
return
}
}
}

View File

@@ -0,0 +1,62 @@
[database]
[database.lottery]
addr = "127.0.0.1:3306"
dsn = "test:test@tcp(127.0.0.1:3306)/test?timeout=200ms&readTimeout=200ms&writeTimeout=200ms&parseTime=true&loc=Local&charset=utf8,utf8mb4"
readDSN = ["test:test@tcp(127.0.0.2:3306)/test? timeout=200ms&readTimeout=200ms&writeTimeout=200ms&parseTime=true&loc=Local&charset=utf8,utf8mb4","test:test@tcp(127.0.0.3:3306)/test?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"
[redis]
[redis.lottery]
name = "xlottery-job"
proto = "tcp"
addr = ""
idle = 10
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "1m"
[Cfg]
ExpireCountFrequency = "*/1 * * * * ?"
[giftPaySub]
key = "ec4c0820d525d67b"
secret = "e20f8f664bf10722efeb6aac0cc16011"
group = "LiveGiftSendByPayLiveLive-Xlottery-S"
topic = "LiveGiftSendByPay-T"
action = "sub"
offset = "new"
name = "xlottery/xlottery-pay-sub"
proto = "tcp"
addr = "172.18.33.50:6205"
idle = 100
active = 100
dialTimeout = "1s"
readTimeout = "60s"
writeTimeout = "1s"
idleTimeout = "10s"
[giftFreeSub]
key = "ec4c0820d525d67b"
secret = "e20f8f664bf10722efeb6aac0cc16011"
group = "LiveGiftSendByFree-LiveLive-Xlottery-S"
topic = "LiveGiftSendByFree-T"
action = "sub"
offset = "new"
name = "xlottery/xlottery-free-sub"
proto = "tcp"
addr = "172.18.33.50:6205"
idle = 100
active = 100
dialTimeout = "1s"
readTimeout = "60s"
writeTimeout = "1s"
idleTimeout = "10s"

View File

@@ -0,0 +1,41 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["conf.go"],
importpath = "go-common/app/job/live/xlottery/internal/conf",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/cache/redis:go_default_library",
"//library/conf:go_default_library",
"//library/database/sql:go_default_library",
"//library/ecode/tip:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/middleware/verify:go_default_library",
"//library/net/rpc/liverpc:go_default_library",
"//library/net/trace:go_default_library",
"//library/queue/databus: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,124 @@
package conf
import (
"errors"
"flag"
"go-common/library/net/rpc/liverpc"
"go-common/library/database/sql"
"go-common/library/queue/databus"
"go-common/library/cache/redis"
"go-common/library/conf"
ecode "go-common/library/ecode/tip"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/verify"
"go-common/library/net/trace"
"github.com/BurntSushi/toml"
)
var (
confPath string
client *conf.Client
// Conf config
Conf = &Config{}
)
// Config .
type Config struct {
Log *log.Config
BM *bm.ServerConfig
Verify *verify.Config
Tracer *trace.Config
Redis *Redis
Database *Database
Ecode *ecode.Config
Cfg *Cfg
// databus
GiftPaySub *databus.Config
GiftFreeSub *databus.Config
AddCapsuleSub *databus.Config
UserReport *databus.Config
LiveRpc map[string]*liverpc.ClientConfig
HTTPClient *bm.ClientConfig
CouponConf *CouponConfig
}
// CouponConfig .
type CouponConfig struct {
Url string
Coupon map[string]string
}
// Database mysql
type Database struct {
Lottery *sql.Config
}
// Redis redis
type Redis struct {
Lottery *redis.Config
}
// Cfg def
type Cfg struct {
// ExpireCountFrequency crontab frequency
ExpireCountFrequency string
CouponRetryFrequency string
ConsumerProcNum int64
}
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,45 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"api.go",
"cache.go",
"capsule.go",
"dao.go",
],
importpath = "go-common/app/job/live/xlottery/internal/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/live/xlottery/internal/conf:go_default_library",
"//app/job/live/xlottery/internal/model:go_default_library",
"//app/service/live/rc/api/liverpc:go_default_library",
"//app/service/live/rc/api/liverpc/v1:go_default_library",
"//library/cache/redis:go_default_library",
"//library/database/sql:go_default_library",
"//library/log:go_default_library",
"//library/net/rpc/liverpc:go_default_library",
"//library/queue/databus/report:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,23 @@
package dao
import (
"go-common/app/job/live/xlottery/internal/conf"
rcApi "go-common/app/service/live/rc/api/liverpc"
"go-common/library/net/rpc/liverpc"
)
// RcApi liverpc reward-service api
var RcApi *rcApi.Client
// InitAPI init all service APIs
func InitAPI() {
RcApi = rcApi.New(getConf("rc"))
}
func getConf(appName string) *liverpc.ClientConfig {
c := conf.Conf.LiveRpc
if c != nil {
return c[appName]
}
return nil
}

View File

@@ -0,0 +1,70 @@
package dao
import (
"context"
"math/rand"
"time"
"go-common/library/cache/redis"
"go-common/library/log"
)
func randomString(l int) string {
str := "0123456789abcdefghijklmnopqrstuvwxyz"
bytes := []byte(str)
result := []byte{}
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for i := 0; i < l; i++ {
result = append(result, bytes[r.Intn(len(bytes))])
}
return string(result)
}
// Lock .
func (d *Dao) Lock(ctx context.Context, realKey string, ttl int, retry int, retryDelay int) (gotLock bool, lockValue string, err error) {
if retry <= 0 {
retry = 1
}
lockValue = "locked:" + randomString(5)
retryTimes := 0
conn := d.redis.Get(ctx)
defer conn.Close()
for ; retryTimes < retry; retryTimes++ {
var res interface{}
res, err = conn.Do("SET", realKey, lockValue, "PX", ttl, "NX")
if err != nil {
log.Error("redis_lock failed:%s:%s", realKey, err.Error())
break
}
if res != nil {
gotLock = true
break
}
time.Sleep(time.Duration(retryDelay * 1000))
}
return
}
// UnLock .
func (d *Dao) UnLock(ctx context.Context, realKey string, lockValue string) (err error) {
conn := d.redis.Get(ctx)
defer conn.Close()
res, err := redis.String(conn.Do("GET", realKey))
if err != nil {
log.Error("redis_unlock get error:%s:%v", realKey, err)
return
}
if res != lockValue {
err = ErrUnLockGet
return
}
_, err = conn.Do("DEL", realKey)
if err != nil {
log.Error("redis_unlock del error:%s:%v", realKey, err)
}
return
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,49 @@
package dao
import (
"context"
"go-common/library/log"
"go-common/app/job/live/xlottery/internal/conf"
"go-common/library/cache/redis"
xsql "go-common/library/database/sql"
)
// Dao dao
type Dao struct {
c *conf.Config
redis *redis.Pool
db *xsql.DB
}
// New init mysql db
func New(c *conf.Config) (dao *Dao) {
dao = &Dao{
c: c,
redis: redis.NewPool(c.Redis.Lottery),
db: xsql.NewMySQL(c.Database.Lottery),
}
return
}
// Close close the resource.
func (d *Dao) Close() {
d.redis.Close()
d.db.Close()
}
// Ping dao ping
func (d *Dao) Ping(ctx context.Context) error {
// TODO: add mc,redis... if you use
return d.db.Ping(ctx)
}
func (d *Dao) execSqlWithBindParams(c context.Context, sql *string, bindParams ...interface{}) (affect int64, err error) {
res, err := d.db.Exec(c, *sql, bindParams...)
if err != nil {
log.Error("db.Exec(%s) error(%v)", *sql, err)
return
}
return res.RowsAffected()
}

View File

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

View File

@@ -0,0 +1,85 @@
package model
// Pool .
type Pool struct {
Id int64 `json:"id"`
CoinId int64 `json:"coin_id"`
Title string `json:"title"`
Description string `json:"description"`
StartTime int64 `json:"start_time"`
EndTime int64 `json:"end_time"`
Status int64 `json:"status"`
IsBottom int64 `json:"is_bottom"`
}
// Coin .
type Coin struct {
Id int64 `json:"id"`
Title string `json:"title"`
GiftType int64 `json:"gift_type"`
ChangeNum int64 `json:"change_num"`
StartTime int64 `json:"start_time"`
EndTime int64 `json:"end_time"`
Status int64 `json:"status"`
}
// UserInfo .
type UserInfo struct {
Uid int64 `json:"uid"`
NormalScore int64 `json:"normal_score"`
ColorfulScore int64 `json:"colorful_score"`
}
// GiftMsg .
type GiftMsg struct {
// by notify
MsgContent string `form:"msg_content"`
}
// CoinConfig .
type CoinConfig struct {
CoinId int64 `json:"coin_id"`
Type int64 `json:"type"`
AreaV2ParentId int64 `json:"area_v2_parent_id"`
AreaV2Id int64 `json:"area_v2_id"`
GiftId int64 `json:"gift_id"`
IsAll int64 `json:"is_all"`
}
// PoolPrize .
type PoolPrize struct {
Id int64 `json:"id"`
PoolId int64 `json:"pool_id"`
Type int64 `json:"type"`
Num int64 `json:"num"`
ObjectId int64 `json:"object_id"`
Expire int64 `json:"expire"`
WebUrl string `json:"web_url"`
MobileUrl string `json:"mobile_url"`
Description string `json:"description"`
JumpUrl string `json:"jump_url"`
ProType int64 `json:"pro_type"`
Chance int64 `json:"chance"`
LoopNum int64 `json:"loop_num"`
LimitNum int64 `json:"limit_num"`
Weight int64 `json:"weight"`
}
// AddCapsule AddCapsule
type AddCapsule struct {
Uid int64 `json:"uid"`
Type string `json:"type"`
CoinId int64 `json:"coin_id"`
Num int64 `json:"num"`
Source string `json:"source"`
MsgId string `json:"msg_id"`
}
// ExtraData .
type ExtraData struct {
Id int64 `json:"id"`
Uid int64 `json:"uid"`
Type string `json:"type"`
ItemValue int64 `json:"item_value"`
ItemExtra string `json:"item_extra"`
}

View File

@@ -0,0 +1,35 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["http.go"],
importpath = "go-common/app/job/live/xlottery/internal/server/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/live/xlottery/internal/conf:go_default_library",
"//app/job/live/xlottery/internal/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,53 @@
package http
import (
"net/http"
"go-common/app/job/live/xlottery/internal/conf"
"go-common/app/job/live/xlottery/internal/service"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/verify"
)
var (
vfy *verify.Verify
svc *service.Service
)
// Init init
func Init(c *conf.Config, s *service.Service) {
svc = s
vfy = verify.New(c.Verify)
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/xlottery")
{
g.GET("/start", vfy.Verify, howToStart)
}
}
func ping(ctx *bm.Context) {
if err := svc.Ping(ctx); err != nil {
log.Error("ping error(%v)", err)
ctx.AbortWithStatus(http.StatusServiceUnavailable)
}
}
func register(c *bm.Context) {
c.JSON(map[string]interface{}{}, nil)
}
// example for http request handler
func howToStart(c *bm.Context) {
c.String(0, "Golang 大法好 !!!")
}

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 = ["service.go"],
importpath = "go-common/app/job/live/xlottery/internal/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/live/xlottery/internal/conf:go_default_library",
"//app/job/live/xlottery/internal/dao:go_default_library",
"//app/job/live/xlottery/internal/model:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/queue/databus:go_default_library",
"//library/queue/databus/report:go_default_library",
"//vendor/github.com/robfig/cron: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,462 @@
package service
import (
"bytes"
"context"
"encoding/json"
"fmt"
"go-common/app/job/live/xlottery/internal/model"
"go-common/library/ecode"
"go-common/library/queue/databus/report"
"net/http"
"strconv"
"sync"
"time"
"github.com/robfig/cron"
"go-common/app/job/live/xlottery/internal/conf"
"go-common/app/job/live/xlottery/internal/dao"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/queue/databus"
)
// Service struct
type Service struct {
c *conf.Config
dao *dao.Dao
cron *cron.Cron
giftPaySub *databus.Databus
giftFreeSub *databus.Databus
capsuleSub *databus.Databus
ExpireCountFrequency string
CouponRetryFrequency string
httpClient *bm.Client
wg *sync.WaitGroup
}
const _sendGiftKey = "lottery:gift:msgid:%s"
const _addCapsuleKey = "lottery:gift:msgid:%s"
type info struct {
MsgContent string `json:"msg_content"`
}
type msgContent struct {
Body *body `json:"body"`
}
type body struct {
GiftId int64 `json:"giftid"`
RoomId int64 `json:"roomid"`
Num int64 `json:"num"`
Uid int64 `json:"uid"`
Ruid int64 `json:"ruid"`
TotalCoin int64 `json:"totalCoin"`
CoinType string `json:"coinType"`
Tid string `json:"tid"`
Platform string `json:"platform"`
RoomInfo *roomInfo `json:"roomInfo"`
}
type roomInfo struct {
AreaV2Id int64 `json:"area_v2_id"`
AreaV2ParentId int64 `json:"area_v2_parent_id"`
}
// New init
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
dao: dao.New(c),
cron: cron.New(),
giftPaySub: databus.New(c.GiftPaySub),
giftFreeSub: databus.New(c.GiftFreeSub),
capsuleSub: databus.New(c.AddCapsuleSub),
wg: new(sync.WaitGroup),
ExpireCountFrequency: c.Cfg.ExpireCountFrequency,
CouponRetryFrequency: c.Cfg.CouponRetryFrequency,
httpClient: bm.NewClient(c.HTTPClient),
}
report.InitUser(conf.Conf.UserReport)
dao.InitAPI()
s.addCrontab()
s.cron.Start()
s.tickerReloadCapsuleConf(context.TODO())
log.Info("[service.lottery| 11start")
var i int64
for i = 0; i < c.Cfg.ConsumerProcNum; i++ {
s.wg.Add(1)
go s.giftConsumeProc()
}
s.wg.Add(1)
go s.capsuleConsumeProc()
return s
}
// Ping Service
func (s *Service) Ping(ctx context.Context) (err error) {
return s.dao.Ping(ctx)
}
// Close Service
func (s *Service) Close() {
s.subClose()
s.wg.Wait()
s.dao.Close()
}
// subClose Close all sub channels
func (s *Service) subClose() {
s.giftPaySub.Close()
s.giftFreeSub.Close()
s.capsuleSub.Close()
}
func (s *Service) addCrontab() (err error) {
//spew.Dump(s.ExpireCountFrequency)
err = s.cron.AddFunc(s.ExpireCountFrequency, s.TransCapsule)
if err != nil {
log.Error("cron job transCapsule error(%v)", err)
}
err = s.cron.AddFunc(s.CouponRetryFrequency, s.CouponRetry)
if err != nil {
log.Error("cron job couponRetry error(%v)", err)
}
return
}
// CouponRetry 抽奖券重试
func (s *Service) CouponRetry() {
var ctx = context.Background()
if s.c.CouponConf == nil || s.c.CouponConf.Url == "" || len(s.c.CouponConf.Coupon) == 0 {
log.Error("[service.capsule | sendAward] couponConf is empty")
return
}
nowTime := time.Now()
log.Info("[service.service | couponRetry]couponRetry %s", nowTime.Format("2006-01-02 15:04:05"))
extraData, _ := s.dao.GetCouponData(ctx)
if len(extraData) == 0 {
return
}
for _, extra := range extraData {
s.dao.UpdateExtraMtimeById(ctx, extra.Id, nowTime.Format("2006-01-02 15:04:05"))
awardType := extra.ItemExtra
if _, ok := s.c.CouponConf.Coupon[awardType]; !ok {
log.Error("[service.capsule | sendAward] couponConf.coupon is empty %s", awardType)
continue
}
uid := extra.Uid
var res struct {
Code int `json:"code"`
Msg string `json:"message"`
}
endPoint := s.c.CouponConf.Url
postJson := make(map[string]interface{})
postJson["mid"] = uid
postJson["couponId"] = s.c.CouponConf.Coupon[awardType]
bytesData, err := json.Marshal(postJson)
if err != nil {
log.Error("[service.capsule | sendAward] json.Marshal(%v) error(%v)", postJson, err)
continue
}
req, err := http.NewRequest("POST", endPoint, bytes.NewReader(bytesData))
if err != nil {
log.Error("[service.capsule | sendAward] http.NewRequest(%v) url(%v) error(%v)", postJson, endPoint, err)
continue
}
req.Header.Add("Content-Type", "application/json;charset=UTF-8")
log.Info("coupon vip mid(%d) couponID(%s)", uid, s.c.CouponConf.Coupon[awardType])
if err = s.httpClient.Do(ctx, req, &res); err != nil {
log.Error("[service.capsule | sendAward] s.client.Do error(%v)", err)
continue
}
if res.Code != 0 && res.Code != 83110005 {
err = ecode.Int(res.Code)
log.Error("coupon vip url(%v) res code(%d)", endPoint, res.Code)
continue
}
log.Info("[service.capsule | sendAward] s.client.Do endpoint (%v) req (%v)", endPoint, postJson)
s.dao.UpdateExtraValueById(ctx, extra.Id, 1)
}
}
// TransCapsule 转换扭蛋币
func (s *Service) TransCapsule() {
var ctx = context.Background()
pools, err := s.dao.GetActiveColorPool(ctx)
if err != nil {
log.Error("[service.service | TransCapsule]CronJob TransCapsule GetActiveColorPool error(%v)", err)
return
}
nowTime := time.Now().Add(-(60 * time.Second)).Format("2006-01-02 15:04")
log.Info("[service.service | TransCapsule]TranCapsule %s", nowTime)
flag := 0
coinId := int64(0)
for _, pool := range pools {
if pool.EndTime == 0 {
continue
} else {
endTimeUnix := time.Unix(pool.EndTime, 0)
endTime := endTimeUnix.Format("2006-01-02 15:04")
if endTime == nowTime {
flag = 1
coinId = pool.CoinId
}
}
}
if flag == 1 {
colorChangeNum, err := s.dao.GetTransNum(ctx, coinId)
if err != nil || colorChangeNum == 0 {
log.Error("[service.service | TransCapsule] GetTransNum colorChangeNum: %d, err: %v", colorChangeNum, err)
return
}
normalChangeNum, err := s.dao.GetTransNum(ctx, dao.NormalCoinId)
if err != nil || normalChangeNum == 0 {
log.Error("[service.service | TransCapsule] GetTransNum normalChangeNum: %d, err: %v", normalChangeNum, err)
return
}
for i := int64(0); i < 10; i++ {
err := s.dao.TransCapsule(ctx, strconv.FormatInt(i, 10), colorChangeNum, normalChangeNum)
if err != nil {
log.Error("[service.service | TransCapsule]TranCapsule error %v", err)
return
}
log.Info("[service.service | TransCapsule]TranCapsule %s", strconv.FormatInt(i, 10))
}
}
}
// expCanalConsumeproc consumer archive
func (s *Service) giftConsumeProc() {
defer func() {
log.Warn("giftConsumeProc exited.")
s.wg.Done()
}()
var (
payMsgs = s.giftPaySub.Messages()
freeMsgs = s.giftFreeSub.Messages()
)
log.Info("[service.lottery|giftConsumeProc")
for {
select {
case msg, ok := <-payMsgs:
if !ok {
log.Warn("[service.lottery|giftConsumeProc] giftPaySub has been closed.")
return
}
var value *info
var subValue *msgContent
err := json.Unmarshal([]byte(msg.Value), &value)
if err != nil {
log.Error("[service.lottery|giftConsumeProc] giftPaySub json decode error:%v", err)
continue
}
err = json.Unmarshal([]byte(value.MsgContent), &subValue)
if err != nil {
log.Error("[service.lottery|giftConsumeProc] giftPaySub json decode error:%v", err)
continue
}
areaV2Id := subValue.Body.RoomInfo.AreaV2Id
areaV2ParentId := subValue.Body.RoomInfo.AreaV2ParentId
giftId := subValue.Body.GiftId
roomId := subValue.Body.RoomId
num := subValue.Body.Num
uid := subValue.Body.Uid
ruid := subValue.Body.Ruid
totalCoin := subValue.Body.TotalCoin
coinType := subValue.Body.CoinType
platform := subValue.Body.Platform
key := fmt.Sprintf(_sendGiftKey, subValue.Body.Tid)
isGetLock, _, err := s.dao.Lock(context.Background(), key, 86400000, 0, 0)
if err != nil || !isGetLock {
log.Error("[service.lottery|giftConsumeProc Lock Error msgKey(%s) uid(%d) ruid(%d) roomId(%d) giftId(%d) num(%d) totalCoin(%d) coinType(%s) tid(%s) key(%s) offset(%d) err(%v)", msg.Key, uid, ruid, roomId, giftId, num, totalCoin, coinType, subValue.Body.Tid, msg.Key, msg.Offset, err)
continue
}
msg.Commit()
log.Info("[service.lottery|giftConsumeProc] pay-msgKey(%s) uid(%d) ruid(%d) roomId(%d) giftId(%d) num(%d) totalCoin(%d) coinType(%s) tid(%s) key(%s) offset(%d)", msg.Key, uid, ruid, roomId, giftId, num, totalCoin, coinType, subValue.Body.Tid, msg.Key, msg.Offset)
s.sendGift(context.Background(), uid, giftId, num, totalCoin, coinType, areaV2ParentId, areaV2Id, platform)
case msg, ok := <-freeMsgs:
if !ok {
log.Warn("[service.lottery|giftConsumeProc] giftFreeSub has been closed.")
return
}
var value *info
var subValue *msgContent
err := json.Unmarshal([]byte(msg.Value), &value)
if err != nil {
log.Error("[service.lottery|giftConsumeProc] giftFreeSub message:%s json decode error:%v", msg.Value, err)
continue
}
err = json.Unmarshal([]byte(value.MsgContent), &subValue)
if err != nil {
log.Error("[service.lottery|giftConsumeProc] giftFreeSub message:%s json decode error:%v", msg.Value, err)
continue
}
areaV2Id := subValue.Body.RoomInfo.AreaV2Id
areaV2ParentId := subValue.Body.RoomInfo.AreaV2ParentId
giftId := subValue.Body.GiftId
roomId := subValue.Body.RoomId
num := subValue.Body.Num
uid := subValue.Body.Uid
ruid := subValue.Body.Ruid
totalCoin := subValue.Body.TotalCoin
coinType := subValue.Body.CoinType
platform := subValue.Body.Platform
key := fmt.Sprintf(_sendGiftKey, subValue.Body.Tid)
isGetLock, _, err := s.dao.Lock(context.Background(), key, 86400000, 0, 0)
if err != nil || !isGetLock {
log.Error("[service.lottery|giftConsumeProc Lock Error msgKey(%s) uid(%d) ruid(%d) roomId(%d) giftId(%d) num(%d) totalCoin(%d) coinType(%s) tid(%s) key(%s) offset(%d) err(%v)", msg.Key, uid, ruid, roomId, giftId, num, totalCoin, coinType, subValue.Body.Tid, msg.Key, msg.Offset, err)
continue
}
msg.Commit()
log.Info("[service.lottery|giftConsumeProc] pay-msgKey(%s) uid(%d) ruid(%d) roomId(%d) giftId(%d) num(%d) totalCoin(%d) coinType(%s) tid(%s) key(%s) offset(%d)", msg.Key, uid, ruid, roomId, giftId, num, totalCoin, coinType, subValue.Body.Tid, msg.Key, msg.Offset)
s.sendGift(context.Background(), uid, giftId, num, totalCoin, coinType, areaV2ParentId, areaV2Id, platform)
default:
time.Sleep(time.Second * 3)
continue
}
}
}
func (s *Service) capsuleConsumeProc() {
defer func() {
log.Warn("capsuleConsumeProc exited.")
s.wg.Done()
}()
var (
capsuleMsgs = s.capsuleSub.Messages()
)
log.Info("[service.lottery|capsuleConsumeProc")
for {
select {
case msg, ok := <-capsuleMsgs:
if !ok {
log.Warn("[service.lottery|capsuleConsumeProc] giftPaySub has been closed.")
return
}
var msgContent *info
var value *model.AddCapsule
err := json.Unmarshal([]byte(msg.Value), &msgContent)
if err != nil {
log.Error("[service.lottery|capsuleConsumeProc] json decode error:%v", err)
continue
}
err = json.Unmarshal([]byte(msgContent.MsgContent), &value)
if err != nil {
log.Error("[service.lottery|giftConsumeProc] giftFreeSub message:%s json decode error:%v", msg.Value, err)
continue
}
uid := value.Uid
cType := value.Type
coinId := value.CoinId
num := value.Num
key := fmt.Sprintf(_addCapsuleKey, value.MsgId)
isGetLock, _, err := s.dao.Lock(context.Background(), key, 86400000, 0, 0)
if err != nil || !isGetLock {
log.Error("[service.lottery|capsuleConsumeProc Lock Error msgKey(%s) uid(%d) num(%d) type(%s) coinId(%d) tid(%s) offset(%d) err(%v)", msg.Key, uid, num, cType, coinId, value.MsgId, msg.Offset, err)
continue
}
msg.Commit()
log.Info("[service.lottery|capsuleConsumeProc] msgKey(%s) uid(%d) num(%d) type(%s) coinId(%s) tid(%s) offset(%d)", msg.Key, uid, num, cType, coinId, value.MsgId, msg.Offset)
s.addCapsule(context.Background(), uid, coinId, num)
default:
time.Sleep(time.Second * 3)
continue
}
}
}
// SendGift 送礼增加扭蛋积分
func (s *Service) sendGift(ctx context.Context, uid, giftId, num, totalCoin int64, coinType string, areaV2ParentId, areaV2Id int64, platform string) {
if totalCoin <= 0 {
return
}
coinConfMap, err := s.dao.GetCapsuleConf(ctx)
if err != nil || len(coinConfMap) == 0 {
return
}
var addCoinId = int64(dao.NormalCoinId)
var coinIds = []int64{dao.BlessCoinId, dao.LplCoinId, dao.WeekCoinId, dao.ColorfulCoinId, dao.NormalCoinId}
for _, coinId := range coinIds {
if _, ok := coinConfMap[coinId]; ok {
if coinConfMap[coinId].AreaMap != nil {
_, v2ID := coinConfMap[coinId].AreaMap[areaV2Id]
_, v2ParentID := coinConfMap[coinId].AreaMap[areaV2ParentId]
if v2ID || v2ParentID {
if coinConfMap[coinId].GiftType == dao.CapsuleGiftTypeAll {
addCoinId = coinId
} else if coinConfMap[coinId].GiftType == dao.CapsuleGiftTypeGold {
if coinType == "gold" {
addCoinId = coinId
}
} else if coinConfMap[coinId].GiftType == dao.CapsuleGiftTypeSelected {
if coinConfMap[coinId].GiftMap != nil {
if _, ok := coinConfMap[coinId].GiftMap[giftId]; ok {
addCoinId = coinId
}
}
}
}
}
}
if addCoinId != dao.NormalCoinId {
break
}
}
// 首次赠送
if addCoinId == dao.LplCoinId {
if s.dao.CheckLplFirstGift(ctx, uid, giftId) {
totalCoin = totalCoin + coinConfMap[addCoinId].ChangeNum
}
}
if addCoinId <= dao.ColorfulCoinId {
_, err = s.dao.UpdateScore(ctx, uid, addCoinId, totalCoin, "sendGift", platform, nil, coinConfMap[addCoinId])
} else {
_, err = s.dao.UpdateCapsule(ctx, uid, addCoinId, totalCoin, "sendGift", platform, coinConfMap[addCoinId])
}
if err != nil {
log.Error("[service.lottery|sendGift] UpdateScore type:%d error:%v", addCoinId, err)
return
}
}
func (s *Service) addCapsule(ctx context.Context, uid, coinId, num int64) {
coinConfMap, err := s.dao.GetCapsuleConf(ctx)
if err != nil || len(coinConfMap) == 0 {
return
}
addCoinId := coinId
if _, ok := coinConfMap[addCoinId]; !ok {
return
}
totalCoin := coinConfMap[addCoinId].ChangeNum * num
if addCoinId <= dao.ColorfulCoinId {
_, err = s.dao.UpdateScore(ctx, uid, addCoinId, totalCoin, "sendGift", "", nil, coinConfMap[addCoinId])
} else {
_, err = s.dao.UpdateCapsule(ctx, uid, addCoinId, totalCoin, "sendGift", "", coinConfMap[addCoinId])
}
if err != nil {
log.Error("[service.lottery|addCapsule] UpdateScore type:%d error:%v", addCoinId, err)
return
}
}
//定时重置Capusule
func (s *Service) tickerReloadCapsuleConf(ctx context.Context) {
changeFlag, _ := s.dao.GetCapsuleChangeFlag(ctx)
s.dao.RelaodCapsuleConfig(ctx, changeFlag)
ticker := time.NewTicker(time.Second)
go func() {
for range ticker.C {
redisChangeFlag, _ := s.dao.GetCapsuleChangeFlag(ctx)
capsuleCacheTime, capsuleChangeFlag := s.dao.GetCapsuleChangeInfo(ctx)
if redisChangeFlag != capsuleChangeFlag || time.Now().Unix()-capsuleCacheTime > 60 {
s.dao.RelaodCapsuleConfig(ctx, redisChangeFlag)
}
}
}()
}