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,80 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"match_test.go",
"service_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/activity/conf:go_default_library",
"//app/job/main/activity/model/like:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"action.go",
"archive.go",
"bnj.go",
"kfc.go",
"like.go",
"match.go",
"service.go",
"subject.go",
],
importpath = "go-common/app/job/main/activity/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/activity/model:go_default_library",
"//app/interface/main/activity/model/like:go_default_library",
"//app/interface/main/activity/rpc/client:go_default_library",
"//app/interface/openplatform/article/model:go_default_library",
"//app/interface/openplatform/article/rpc/client:go_default_library",
"//app/job/main/activity/conf:go_default_library",
"//app/job/main/activity/dao/bnj:go_default_library",
"//app/job/main/activity/dao/dm:go_default_library",
"//app/job/main/activity/dao/kfc:go_default_library",
"//app/job/main/activity/dao/like:go_default_library",
"//app/job/main/activity/model/bnj:go_default_library",
"//app/job/main/activity/model/kfc:go_default_library",
"//app/job/main/activity/model/like:go_default_library",
"//app/job/main/activity/model/match:go_default_library",
"//app/service/main/account/api:go_default_library",
"//app/service/main/archive/api:go_default_library",
"//app/service/main/archive/api/gorpc:go_default_library",
"//app/service/main/archive/model/archive:go_default_library",
"//app/service/main/coin/api/gorpc:go_default_library",
"//app/service/main/coin/model:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/queue/databus: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,137 @@
package service
import (
"bytes"
"context"
"encoding/json"
"strconv"
"time"
"go-common/app/job/main/activity/model/like"
"go-common/library/log"
)
// actionDealProc .
func (s *Service) actionDealProc(i int) {
defer s.waiter.Done()
var (
ch = s.subActionCh[i]
sm = s.actionSM[i]
ls *like.LastTmStat
)
for {
ms, ok := <-ch
if !ok {
s.multiUpActDB(i, sm)
log.Warn("s.actionDealProc(%d) quit", i)
return
}
if ls, ok = sm[ms.Lid]; !ok {
ls = &like.LastTmStat{Last: time.Now().Unix()}
sm[ms.Lid] = ls
// the first time update db.
s.updateActDB([]int64{ms.Lid})
}
if time.Now().Unix()-ls.Last > 60 {
s.updateActDB([]int64{ms.Lid})
delete(sm, ms.Lid)
}
log.Info("s.actionDealProc(%d) lid:%d time:%d", i, ms.Lid, ls.Last)
}
}
// updateActDB batch to deal like_extend.
func (s *Service) updateActDB(lids []int64) {
var (
c = context.Background()
insertExt []*like.Extend
)
if len(lids) == 0 {
return
}
lidLike, err := s.dao.BatchLikeActSum(c, lids)
if err != nil {
log.Error("s.dao.BatchLikeActSum(%v) error(%+v)", lids, err)
return
}
insertExt = make([]*like.Extend, 0, len(lids))
for _, v := range lids {
if _, ok := lidLike[v]; ok {
insertExt = append(insertExt, &like.Extend{Lid: v, Like: lidLike[v]})
} else {
log.Warn("s.updateActDB() data has not found")
}
}
if len(insertExt) == 0 {
return
}
s.BatchInsertLikeExtend(c, insertExt)
}
// multiUpActDB division sm data .
func (s *Service) multiUpActDB(yu int, sm map[int64]*like.LastTmStat) {
var (
i int
startLids = [1000]int64{}
lids = startLids[:0]
)
log.Info("start close(%d) multiUpActDB start", yu)
for lid := range sm {
lids = append(lids, lid)
i++
if i%1000 == 0 {
s.updateActDB(lids)
lids = startLids[:0]
}
}
if len(lids) > 0 {
s.updateActDB(lids)
}
log.Info("start close(%d) multiUpActDB end", yu)
}
// BatchInsertLikeExtend batch insert like_extend table.
func (s *Service) BatchInsertLikeExtend(c context.Context, extends []*like.Extend) (res int64, err error) {
var buf bytes.Buffer
cnt := 0
rows := int64(0)
for _, v := range extends {
buf.WriteString("(")
buf.WriteString(strconv.FormatInt(v.Lid, 10))
buf.WriteString(",")
buf.WriteString(strconv.FormatInt(v.Like, 10))
buf.WriteString("),")
cnt++
if cnt%500 == 0 {
buf.Truncate(buf.Len() - 1)
if rows, err = s.dao.AddExtend(c, buf.String()); err != nil {
log.Error("s.dao.dealAddExtend() error(%+v)", err)
return
}
res += rows
buf.Reset()
}
}
if buf.Len() > 0 {
buf.Truncate(buf.Len() - 1)
if rows, err = s.dao.AddExtend(c, buf.String()); err != nil {
log.Error("s.dao.dealAddExtend() error(%+v)", err)
return
}
res += rows
}
return
}
// actionProc .
func (s *Service) actionProc(c context.Context, msg json.RawMessage) (err error) {
var (
act = new(like.Action)
)
if err = json.Unmarshal(msg, act); err != nil {
log.Error("actionProc json.Unmarshal(%s) error(%v)", msg, err)
return
}
s.subActionCh[act.Lid%_sharding] <- act
return
}

View File

@@ -0,0 +1,124 @@
package service
import (
"context"
"sort"
"time"
likemdl "go-common/app/interface/main/activity/model/like"
"go-common/app/job/main/activity/model/like"
"go-common/app/service/main/archive/api"
"go-common/app/service/main/archive/model/archive"
"go-common/library/log"
)
const (
_rankViewPieceSize = 100
_rankCount = 50
)
func (s *Service) subsRankproc() {
for {
if s.closed {
return
}
var (
subs []*like.Subject
err error
)
now := time.Now()
if subs, err = s.dao.SubjectList(context.Background(), []int64{likemdl.PHONEVIDEO, likemdl.SMALLVIDEO}, now); err != nil {
log.Error("viewRankproc s.dao.SubjectList error(%+v)", err)
time.Sleep(100 * time.Millisecond)
continue
}
if len(subs) == 0 {
log.Warn("viewRankproc no subjects time(%d)", now.Unix())
time.Sleep(time.Duration(s.c.Interval.ViewRankInterval))
continue
}
for _, v := range subs {
s.viewRankproc(v.ID)
time.Sleep(100 * time.Millisecond)
}
time.Sleep(time.Duration(s.c.Interval.ViewRankInterval))
}
}
func (s *Service) viewRankproc(sid int64) {
var (
likeCnt int
likes []*like.Like
rankArcs []*api.Arc
err error
)
if likeCnt, err = s.dao.LikeCnt(context.Background(), sid); err != nil {
log.Error("viewRankproc s.dao.LikeCnt(sid:%d) error(%v)", sid, err)
return
}
if likeCnt == 0 {
log.Warn("viewRankproc s.dao.LikeCnt(sid:%d) likeCnt == 0", sid)
return
}
for i := 0; i < likeCnt; i += _rankViewPieceSize {
if likes, err = s.likeList(context.Background(), sid, i, _objectPieceSize, _retryTimes); err != nil {
log.Error("viewRankproc s.likeList(%d,%d,%d) error(%+v)", sid, i, _objectPieceSize, err)
time.Sleep(100 * time.Millisecond)
continue
} else {
var aids []int64
for _, v := range likes {
if v.Wid > 0 {
aids = append(aids, v.Wid)
}
}
var arcs map[int64]*api.Arc
if arcs, err = s.arcs(context.Background(), aids, _retryTimes); err != nil {
log.Error("viewRankproc s.arcs(%v) error(%v)", aids, err)
time.Sleep(100 * time.Millisecond)
continue
} else {
for _, aid := range aids {
if arc, ok := arcs[aid]; ok && arc.IsNormal() {
rankArcs = append(rankArcs, arc)
}
}
sort.Slice(rankArcs, func(i, j int) bool {
return rankArcs[i].Stat.View > rankArcs[j].Stat.View
})
if len(rankArcs) > _rankCount {
rankArcs = rankArcs[:_rankCount]
}
}
}
}
if len(rankArcs) > 0 {
var rankAids []int64
for _, v := range rankArcs {
rankAids = append(rankAids, v.Aid)
}
if err = s.setViewRank(context.Background(), sid, rankAids, _retryTimes); err != nil {
log.Error("viewRankproc s.setObjectStat(%d,%v) error(%+v)", sid, rankAids, err)
}
}
}
func (s *Service) arcs(c context.Context, aids []int64, retryCnt int) (arcs map[int64]*api.Arc, err error) {
for i := 0; i < retryCnt; i++ {
if arcs, err = s.arcRPC.Archives3(c, &archive.ArgAids2{Aids: aids}); err == nil {
break
}
time.Sleep(100 * time.Millisecond)
}
return
}
func (s *Service) setViewRank(c context.Context, sid int64, aids []int64, retryTime int) (err error) {
for i := 0; i < retryTime; i++ {
if err = s.dao.SetViewRank(c, sid, aids); err == nil {
break
}
time.Sleep(100 * time.Millisecond)
}
return
}

View File

@@ -0,0 +1,434 @@
package service
import (
"context"
"encoding/json"
"fmt"
"sync/atomic"
"time"
"go-common/app/admin/main/activity/model"
"go-common/app/job/main/activity/model/bnj"
"go-common/app/service/main/account/api"
"go-common/library/log"
)
const (
_preScore = 20000
_stepOne = 1
_stepTwo = 2
_stepThree = 3
_stepFour = 4
_stepFlagValue = "1"
)
var bnjSteps = []int{_stepOne, _stepTwo, _stepThree, _stepFour}
func (s *Service) bnjproc() {
defer s.waiter.Done()
var (
c = context.Background()
lastTs int64
)
for {
if s.closed {
return
}
if s.bnjTimeFinish == 1 {
log.Warn("bnjproc bnjTimeFinish")
return
}
msg, ok := <-s.bnjSub.Messages()
if !ok {
log.Info("bnjproc: databus consumer exit!")
return
}
msg.Commit()
m := &bnj.ResetMsg{}
if err := json.Unmarshal(msg.Value, m); err != nil {
log.Error("bnjproc json.Unmarshal(%s) error(%+v)", msg.Value, err)
continue
}
if m.Mid <= 0 {
continue
}
// broadcast max every 1s
if m.Ts-lastTs < 1 {
continue
}
lastTs = m.Ts
atomic.StoreInt64(&s.bnjLessSecond, s.bnjMaxSecond)
// default name
pushMsg := &bnj.Push{Second: s.bnjLessSecond, Name: ""}
if info, err := s.accClient.Info3(c, &api.MidReq{Mid: m.Mid}); err != nil || info == nil {
log.Error("bnjproc s.accClient.Info3(%d) error(%v)", m.Mid, err)
} else {
var name []rune
runes := []rune(info.Info.Name)
nameLen := len(runes)
if nameLen == 2 {
name = append(runes[0:1], []rune("*")...)
} else if nameLen > 2 {
for i, v := range runes {
if i == 0 {
name = append(name, v)
} else if i == nameLen-1 {
name = append(name, runes[nameLen-1:]...)
} else if i == 1 {
name = append(name, []rune("*")...)
}
}
} else {
name = runes
}
pushMsg.Name = string(name)
if pushStr, err := json.Marshal(pushMsg); err != nil {
log.Error("bnjproc json.Marshal(%+v) error(%v)", pushMsg, err)
} else {
atomic.StoreInt64(&s.bnjLessSecond, s.bnjMaxSecond)
log.Info("bnjproc mid(%d) reset lessTime(%d) maxTime(%d)", m.Mid, s.bnjLessSecond, s.bnjMaxSecond)
if err := s.retryPushAll(context.Background(), string(pushStr), _retryTimes); err != nil {
log.Error("bnjproc s.bnj.PushAll(%s) error(%v)", string(pushStr), err)
}
}
}
log.Info("bnjproc key:%s partition:%d offset:%d", msg.Key, msg.Partition, msg.Offset)
}
}
func bnjWxFlagKey(lid int64, step int) string {
return fmt.Sprintf("bnj_wx_%d_%d", lid, step)
}
func bnjMsgFlagKey(lid int64, step int) string {
return fmt.Sprintf("bnj_msg_%d_%d", lid, step)
}
func (s *Service) initBnjSecond() {
for {
time.Sleep(time.Second)
if time.Now().Unix() < s.c.Bnj2019.StartTime.Unix() {
continue
}
break
}
if value, err := s.retryCacheTimeFinish(context.Background(), _retryTimes); err != nil {
log.Error("initBnjSecond s.dao.retryCacheTimeFinish error(%v)", err)
return
} else if value > 0 {
log.Warn("initBnjSecond time finish")
atomic.StoreInt64(&s.bnjTimeFinish, value)
return
}
// init step flag
for _, v := range s.c.Bnj2019.Time {
if v.Step > 0 {
if value, err := s.retryRsGet(context.Background(), bnjMsgFlagKey(s.c.Bnj2019.LID, v.Step), _retryTimes); err != nil {
log.Error("initBnjSecond msg s.dao.retryRsGet error(%v)")
} else if value != "" {
log.Info("initBnjSecond msg bnjMsgFlagMap[step:%d]", v.Step)
s.bnjMsgFlagMap[v.Step] = 1
}
if value, err := s.retryRsGet(context.Background(), bnjWxFlagKey(s.c.Bnj2019.LID, v.Step), _retryTimes); err != nil {
log.Error("initBnjSecond wx s.dao.retryRsGet error(%v)")
} else if value != "" {
log.Info("initBnjSecond wx bnjWxMsgFlagMap[step:%d]", v.Step)
s.bnjWxMsgFlagMap[v.Step] = 1
}
}
}
scores, err := s.retryBatchLikeActSum(context.Background(), []int64{s.c.Bnj2019.LID}, _retryTimes)
if err != nil {
// TODO need to restart
log.Error("initBnjSecond failed s.dao.BatchLikeActSum(%d) error(%v)", s.c.Bnj2019.LID, err)
return
}
if score, ok := scores[s.c.Bnj2019.LID]; ok {
for i, v := range s.c.Bnj2019.Time {
if score >= v.Score {
atomic.StoreInt64(&s.bnjMaxSecond, v.Second)
atomic.StoreInt64(&s.bnjLessSecond, v.Second)
break
}
if i == len(s.c.Bnj2019.Time)-1 {
atomic.StoreInt64(&s.bnjMaxSecond, v.Second)
atomic.StoreInt64(&s.bnjLessSecond, v.Second)
}
}
} else {
// max second
atomic.StoreInt64(&s.bnjMaxSecond, s.c.Bnj2019.Time[len(s.c.Bnj2019.Time)-1].Second)
atomic.StoreInt64(&s.bnjLessSecond, s.c.Bnj2019.Time[len(s.c.Bnj2019.Time)-1].Second)
}
if lessSecond, err := s.bnj.CacheLessTime(context.Background()); err != nil {
log.Error("initBnjSecond s.dao.CacheLessTime error(%v)", err)
} else if lessSecond > 0 {
atomic.StoreInt64(&s.bnjLessSecond, lessSecond)
}
log.Warn("initBnjSecond maxSecond(%d) lessSecond(%d)", s.bnjMaxSecond, s.bnjLessSecond)
go s.maxSecondproc()
go s.lessSecondproc()
s.waiter.Add(1)
go s.bnjproc()
}
func (s *Service) maxSecondproc() {
ctx := context.Background()
for {
if s.closed {
return
}
time.Sleep(time.Second)
if scores, err := s.dao.BatchLikeActSum(context.Background(), []int64{s.c.Bnj2019.LID}); err != nil {
log.Error("maxSecondproc s.dao.BatchLikeActSum(%d) error(%v)", s.c.Bnj2019.LID, err)
} else {
if score, ok := scores[s.c.Bnj2019.LID]; ok {
for _, v := range s.c.Bnj2019.Time {
if score >= v.Score {
atomic.StoreInt64(&s.bnjMaxSecond, v.Second)
if s.bnjLessSecond > s.bnjMaxSecond {
atomic.StoreInt64(&s.bnjLessSecond, s.bnjMaxSecond)
}
msg := v.Msg
mc := v.MsgMc
msgTitle := v.MsgTitle
step := v.Step
if step > 0 && s.bnjMsgFlagMap[step] == 0 {
if err = s.retryRsSet(ctx, bnjMsgFlagKey(s.c.Bnj2019.LID, step), _stepFlagValue, _retryTimes); err != nil {
log.Error("s.retryRsSet(%d,%d) error(%v)", s.c.Bnj2019.LID, step, err)
break
}
if msg != "" && msgTitle != "" && mc != "" {
go s.sendMessageToSubs(ctx, s.c.Bnj2019.LID, mc, msgTitle, msg, _retryTimes)
} else {
log.Error("bnj msg conf step(%d) error", step)
break
}
log.Info("bnj send msg step:%d finish", step)
s.bnjMsgFlagMu.Lock()
s.bnjMsgFlagMap[step] = 1
s.bnjMsgFlagMu.Unlock()
}
break
}
}
for _, v := range s.c.Bnj2019.Time {
if score+_preScore >= v.Score {
wxMsg := v.WxMsg
step := v.Step
if step > 0 && s.bnjWxMsgFlagMap[step] == 0 {
if err = s.retryRsSet(ctx, bnjWxFlagKey(s.c.Bnj2019.LID, step), _stepFlagValue, _retryTimes); err != nil {
log.Error("s.retryRsSet(%d,%d) error(%v)", s.c.Bnj2019.LID, step, err)
break
}
if wxMsg != "" && s.c.Bnj2019.WxUser != "" {
if err = s.retrySendWechat(ctx, s.c.Bnj2019.WxTitle, wxMsg, s.c.Bnj2019.WxUser, _retryTimes); err != nil {
log.Error("s.retrySendWechat(%s,%s) error(%v)", s.c.Bnj2019.WxTitle, wxMsg, err)
break
}
} else {
log.Error("bnj wx msg conf step(%d) error", step)
break
}
log.Info("bnj send wx step:%d finish", step)
s.bnjWxMsgFlagMu.Lock()
s.bnjWxMsgFlagMap[step] = 1
s.bnjWxMsgFlagMu.Unlock()
}
break
}
}
} else {
log.Warn("maxSecondproc lid not found")
}
}
}
}
func (s *Service) lessSecondproc() {
for {
if s.closed {
return
}
time.Sleep(time.Second)
atomic.AddInt64(&s.bnjLessSecond, -1)
if s.c.Bnj2019.GameCancel != 0 {
log.Warn("lessSecondproc bnj game cancel")
atomic.StoreInt64(&s.bnjLessSecond, 0)
}
if s.bnjLessSecond <= 0 {
if err := s.retryAddCacheTimeFinish(context.Background(), 1, _retryTimes); err != nil {
log.Error("lessSecondproc s.bnj.AddCacheTimeFinish error(%v)", err)
continue
}
log.Warn("lessSecondproc bnj time Finish")
atomic.StoreInt64(&s.bnjTimeFinish, 1)
pushMsg := &bnj.Push{Second: 0, Name: "", TimelinePic: s.c.Bnj2019.TimelinePic, H5TimelinePic: s.c.Bnj2019.H5TimelinePic}
if pushStr, err := json.Marshal(pushMsg); err != nil {
log.Error("lessSecondproc json.Marshal(%+v) error(%v)", pushMsg, err)
} else {
atomic.StoreInt64(&s.bnjLessSecond, s.bnjMaxSecond)
if err := s.retryPushAll(context.Background(), string(pushStr), _retryTimes); err != nil {
log.Error("lessSecondproc s.bnj.PushAll error(%v)", err)
}
}
return
}
pushMsg := &bnj.Push{Second: s.bnjLessSecond, Name: ""}
if pushStr, err := json.Marshal(pushMsg); err != nil {
log.Error("lessSecondproc json.Marshal(%+v) error(%v)", pushMsg, err)
} else {
if err := s.retryPushAll(context.Background(), string(pushStr), 1); err != nil {
log.Error("lessSecondproc s.bnj.PushAll error(%v)", err)
}
}
}
}
func (s *Service) retryBatchLikeActSum(c context.Context, lids []int64, retryCnt int) (res map[int64]int64, err error) {
for i := 0; i < retryCnt; i++ {
if res, err = s.dao.BatchLikeActSum(c, lids); err == nil {
break
}
time.Sleep(100 * time.Millisecond)
}
return
}
func (s *Service) retryAddCacheTimeFinish(c context.Context, value int64, retryCnt int) (err error) {
for i := 0; i < retryCnt; i++ {
if err = s.bnj.AddCacheTimeFinish(c, value); err == nil {
break
}
time.Sleep(100 * time.Millisecond)
}
return
}
func (s *Service) retryCacheTimeFinish(c context.Context, retryCnt int) (value int64, err error) {
for i := 0; i < retryCnt; i++ {
if value, err = s.bnj.CacheTimeFinish(c); err == nil {
break
}
time.Sleep(100 * time.Millisecond)
}
return
}
func (s *Service) retryPushAll(c context.Context, msg string, retryCnt int) (err error) {
for i := 0; i < retryCnt; i++ {
if err = s.bnj.PushAll(c, msg); err == nil {
break
}
time.Sleep(10 * time.Millisecond)
}
return
}
func (s *Service) cronInformationMessage() {
log.Info("cronInformationMessage start cron")
if s.c.Bnj2019.LID == 0 || s.c.Bnj2019.MidLimit == 0 {
log.Error("cronInformationMessage conf error")
return
}
var (
c = context.Background()
title, msg, mc string
)
for _, v := range s.c.Bnj2019.Message {
if time.Now().Unix() >= v.Start.Unix() {
title = v.Title
msg = v.Content
mc = v.Mc
break
}
}
if title == "" || msg == "" || mc == "" {
log.Error("cronInformationMessage message conf error")
return
}
s.sendMessageToSubs(c, s.c.Bnj2019.LID, mc, title, msg, _retryTimes)
log.Info("cronInformationMessage finish title(%s)", title)
}
func (s *Service) sendMessageToSubs(c context.Context, lid int64, mc, title, msg string, retryCnt int) {
var minID int64
log.Info("sendMessageToSubs mc:%s title:%s start", mc, title)
for {
time.Sleep(100 * time.Millisecond)
actions, err := s.retryLikeActList(c, lid, minID, s.c.Bnj2019.MidLimit, retryCnt)
if err != nil {
log.Error("sendMessageToSubs s.dao.LikeActList(%d,%d,%d) error(%v)", lid, minID, s.c.Bnj2019.MidLimit, err)
continue
}
if len(actions) == 0 {
log.Info("sendMessageToSubs finish")
break
}
var mids []int64
for i, v := range actions {
if v.Mid > 0 {
mids = append(mids, v.Mid)
}
if i == len(actions)-1 {
minID = v.ID
}
}
if len(mids) == 0 {
continue
}
if err = s.retrySendMessage(c, mids, mc, title, msg, _retryTimes); err != nil {
log.Error("sendMessageToSubs s.dao.SendMessage(mids:%v) error(%v)", mids, err)
}
}
}
func (s *Service) retryLikeActList(c context.Context, lid, minID, limit int64, retryCnt int) (list []*model.LikeAction, err error) {
for i := 0; i < retryCnt; i++ {
if list, err = s.dao.LikeActList(c, lid, minID, limit); err == nil {
break
}
time.Sleep(10 * time.Millisecond)
}
return
}
func (s *Service) retrySendMessage(c context.Context, mids []int64, mc, title, msg string, retryCnt int) (err error) {
for i := 0; i < retryCnt; i++ {
if err = s.bnj.SendMessage(c, mids, mc, title, msg); err == nil {
break
}
time.Sleep(10 * time.Millisecond)
}
return
}
func (s *Service) retryRsSet(c context.Context, key, value string, retryCnt int) (err error) {
for i := 0; i < retryCnt; i++ {
if err = s.dao.RsSet(c, key, value); err == nil {
break
}
time.Sleep(10 * time.Millisecond)
}
return
}
func (s *Service) retryRsGet(c context.Context, key string, retryCnt int) (value string, err error) {
for i := 0; i < retryCnt; i++ {
if value, err = s.dao.RsGet(c, key); err == nil {
break
}
time.Sleep(10 * time.Millisecond)
}
return
}
func (s *Service) retrySendWechat(c context.Context, title, msg, user string, retryCnt int) (err error) {
for i := 0; i < retryCnt; i++ {
if err = s.bnj.SendWechat(c, title, msg, user); err == nil {
break
}
time.Sleep(10 * time.Millisecond)
}
return
}

View File

@@ -0,0 +1,29 @@
package service
import (
"context"
"go-common/library/log"
)
// kfcActionDeal.
func (s *Service) kfcActionDeal(j int) {
defer s.waiter.Done()
var (
ch = s.kfcActionCh[j]
c = context.Background()
)
log.Info("kfcActionDeal goroutine(%d) start", j)
for {
ms, ok := <-ch
if !ok {
log.Warn("kfcActionDeal(%d): quit", j)
return
}
if err := s.kfcDao.KfcDelver(c, ms.CouponID, ms.UID); err != nil {
log.Error("kfcActionDeal(%d):s.kfcDao.KfcDelver(%d %d) error(%v)", j, ms.CouponID, ms.UID, err)
return
}
log.Info("kfcActionDeal(%d) success id(%d) uid(%d)", j, ms.CouponID, ms.UID)
}
}

View File

@@ -0,0 +1,116 @@
package service
import (
"context"
"encoding/json"
actmdl "go-common/app/interface/main/activity/model/like"
l "go-common/app/job/main/activity/model/like"
"go-common/library/log"
)
// AddLike like add data update cache .
func (s *Service) AddLike(c context.Context, addMsg json.RawMessage) (err error) {
var (
likeObj = new(l.Item)
)
if err = json.Unmarshal(addMsg, likeObj); err != nil {
log.Error("AddLike json.Unmarshal(%s) error(%+v)", addMsg, err)
return
}
if err = s.actRPC.LikeUp(c, &actmdl.ArgLikeUp{Lid: likeObj.ID}); err != nil {
log.Error("s.actRPC.LikeUp(%d) error(%+v)", likeObj.ID, err)
return
}
if err = s.actRPC.AddLikeCtimeCache(c, &actmdl.ArgLikeUp{Lid: likeObj.ID}); err != nil {
log.Error("s.actRPC.AddLikeCtimeCache(%d) error(%+v)", likeObj.ID, err)
return
}
log.Info("AddLike success s.actRPC.LikeUp(%d)", likeObj.ID)
return
}
// UpLike update likes data update cahce
func (s *Service) UpLike(c context.Context, newMsg, oldMsg json.RawMessage) (err error) {
var (
likeObj = new(l.Item)
oldObj = new(l.Item)
)
if err = json.Unmarshal(newMsg, likeObj); err != nil {
log.Error("UpLike json.Unmarshal(%s) error(%+v)", newMsg, err)
return
}
if err = json.Unmarshal(oldMsg, oldObj); err != nil {
log.Error("UpLike json.Unmarshal(%s) error(%+v)", oldMsg, err)
return
}
if err = s.actRPC.LikeUp(c, &actmdl.ArgLikeUp{Lid: likeObj.ID}); err != nil {
log.Error("s.actRPC.LikeUp(%d) error(%+v)", likeObj.ID, err)
return
}
if oldObj.State != likeObj.State {
if likeObj.State == 1 {
//add ctime cache
if err = s.actRPC.AddLikeCtimeCache(c, &actmdl.ArgLikeUp{Lid: likeObj.ID}); err != nil {
log.Error("s.actRPC.AddLikeCtimeCache(%d) error(%+v)", likeObj.ID, err)
return
}
} else {
//del ctime cahce
delItem := &actmdl.ArgLikeItem{
ID: likeObj.ID,
Sid: likeObj.Sid,
Type: likeObj.Type,
}
if err = s.actRPC.DelLikeCtimeCache(c, delItem); err != nil {
log.Error("s.actRPC.DelLikeCtimeCache(%v) error(%+v)", likeObj, err)
return
}
}
}
log.Info("UpLike success s.actRPC.LikeUp(%d)", likeObj.ID)
return
}
// DelLike delete like update cache
func (s *Service) DelLike(c context.Context, oldMsg json.RawMessage) (err error) {
var (
likeObj = new(l.Item)
)
if err = json.Unmarshal(oldMsg, likeObj); err != nil {
log.Error("DelLike json.Unmarshal(%s) error(%+v)", oldMsg, err)
return
}
if err = s.actRPC.LikeUp(c, &actmdl.ArgLikeUp{Lid: likeObj.ID}); err != nil {
log.Error("s.actRPC.LikeUp(%d) error(%+v)", likeObj.ID, err)
return
}
//del ctime cahce
delItem := &actmdl.ArgLikeItem{
ID: likeObj.ID,
Sid: likeObj.Sid,
Type: likeObj.Type,
}
if err = s.actRPC.DelLikeCtimeCache(c, delItem); err != nil {
log.Error("s.actRPC.DelLikeCtimeCache(%v) error(%+v)", likeObj, err)
return
}
log.Info("DelLike success s.actRPC.LikeUp(%d)", likeObj.ID)
return
}
// upLikeContent .
func (s *Service) upLikeContent(c context.Context, upMsg json.RawMessage) (err error) {
var (
cont = new(l.Content)
)
if err = json.Unmarshal(upMsg, cont); err != nil {
log.Error("upLikeContent json.Unmarshal(%s) error(%+v)", upMsg, err)
return
}
if err = s.dao.SetLikeContent(c, cont.ID); err != nil {
log.Error("s.dao.SetLikeContent(%d) error(%+v)", cont.ID, err)
}
log.Info("upLikeContent success s.dao.SetLikeContent(%d)", cont.ID)
return
}

View File

@@ -0,0 +1,106 @@
package service
import (
"context"
"encoding/json"
"time"
"go-common/app/interface/main/activity/model/like"
"go-common/app/job/main/activity/model/match"
"go-common/app/service/main/coin/model"
"go-common/library/ecode"
"go-common/library/log"
)
const (
_upMatchUserLimit = 100
_reason = "竞猜奖励"
)
func (s *Service) upMatchUser(c context.Context, newMsg, oldMsg json.RawMessage) {
var (
err error
newMatchObj = new(match.ActMatchObj)
oldMatchObj = new(match.ActMatchObj)
)
if err = json.Unmarshal(newMsg, newMatchObj); err != nil {
log.Error("upMatchUser json.Unmarshal(%s) error(%+v)", newMsg, err)
return
}
if err = json.Unmarshal(oldMsg, oldMatchObj); err != nil {
log.Error("upMatchUser json.Unmarshal(%s) error(%+v)", oldMsg, err)
return
}
if oldMatchObj.Result == match.ResultNo {
if newMatchObj.Result == match.ResultNo {
return
}
s.upUsers(c, newMatchObj)
}
}
// FinishMatch finish match.
func (s *Service) FinishMatch(c context.Context, moID int64) (err error) {
var matchObj *match.ActMatchObj
if matchObj, err = s.dao.MatchObjInfo(c, moID); err != nil || matchObj == nil {
return
}
if matchObj.Result == match.ResultNo {
log.Error("FinishMatch moID(%d) result error", moID)
err = ecode.RequestErr
return
}
go s.upUsers(context.Background(), matchObj)
return
}
func (s *Service) upUsers(c context.Context, matchObj *match.ActMatchObj) {
var (
matchs []*like.Match
list []*match.ActMatchUser
stake int64
err error
)
if matchs, err = s.actRPC.Matchs(c, &like.ArgMatch{Sid: matchObj.SID}); err != nil {
log.Error("upMatchUser s.actRPC.Matchs(%d) error(%v)", matchObj.SID, err)
return
}
for _, v := range matchs {
if v.ID == matchObj.MatchID {
stake = v.Stake
}
}
if stake == 0 {
log.Error("upMatchUser match_id(%d) not found", matchObj.MatchID)
return
}
for {
if list, err = s.dao.UnDoMatchUsers(context.Background(), matchObj.ID, _upMatchUserLimit); err != nil {
time.Sleep(time.Duration(s.c.Interval.QueryInterval))
continue
} else if len(list) == 0 {
log.Info("upMatchUser finish m_o_id(%d)", matchObj.ID)
return
}
var resultMids []int64
for _, v := range list {
if v.Result == matchObj.Result {
count := float64(v.Stake * stake)
if _, err = s.coinRPC.ModifyCoin(context.Background(), &model.ArgModifyCoin{Mid: v.Mid, Count: count, Reason: _reason}); err != nil {
log.Error("upMatchUser coin error s.coinRPC.ModifyCoin mid(%d) coin(%v) error(%v)", v.Mid, count, err)
continue
}
log.Info("upMatchUser s.coinRPC.ModifyCoin mid(%d) coin(%v)", v.Mid, count)
resultMids = append(resultMids, v.Mid)
time.Sleep(time.Duration(s.c.Interval.CoinInterval))
} else {
resultMids = append(resultMids, v.Mid)
}
}
if err = s.dao.UpMatchUserResult(context.Background(), matchObj.ID, resultMids); err != nil {
continue
}
log.Info("upMatchUser s.dao.UpMatchUserResult matchID(%d) mids(%+v)", matchObj.ID, resultMids)
time.Sleep(time.Duration(s.c.Interval.QueryInterval))
}
}

View File

@@ -0,0 +1,16 @@
package service
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestService_FinishMatch(t *testing.T) {
Convey("test finish match", t, WithService(func(s *Service) {
moID := int64(3)
err := s.FinishMatch(context.Background(), moID)
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,729 @@
package service
import (
"context"
"encoding/json"
"runtime"
"strconv"
"sync"
"time"
actrpc "go-common/app/interface/main/activity/rpc/client"
artmdl "go-common/app/interface/openplatform/article/model"
artrpc "go-common/app/interface/openplatform/article/rpc/client"
"go-common/app/job/main/activity/conf"
"go-common/app/job/main/activity/dao/bnj"
"go-common/app/job/main/activity/dao/dm"
"go-common/app/job/main/activity/dao/kfc"
"go-common/app/job/main/activity/dao/like"
kfcmdl "go-common/app/job/main/activity/model/kfc"
l "go-common/app/job/main/activity/model/like"
"go-common/app/job/main/activity/model/match"
"go-common/app/service/main/account/api"
arcapi "go-common/app/service/main/archive/api"
arcrpc "go-common/app/service/main/archive/api/gorpc"
comarcmdl "go-common/app/service/main/archive/model/archive"
"go-common/app/service/main/coin/api/gorpc"
"go-common/library/log"
"go-common/library/queue/databus"
"github.com/robfig/cron"
)
const (
//_startVoteP = 2
//_startVote = 3
//_endingVote = 4
//_endVote = 5
//_goOn = 6
//_next = 7
_matchObjTable = "act_matchs_object"
_subjectTable = "act_subject"
_likesTable = "likes"
_likeContentTable = "like_content"
_likeActionTable = "like_action"
//_vipActOrderTable = "vip_order_activity_record"
_objectPieceSize = 100
_retryTimes = 3
_typeArc = "archive"
_typeArt = "article"
_sharding = 10
)
// Service service
type Service struct {
c *conf.Config
dao *like.Dao
bnj *bnj.Dao
dm *dm.Dao
kfcDao *kfc.Dao
// waiter
waiter sync.WaitGroup
closed bool
// cache: type, upper
// arc rpc
arcRPC *arcrpc.Service2
coinRPC *coin.Service
actRPC *actrpc.Service
articleRPC *artrpc.Service
//grpc
accClient api.AccountClient
// databus
actSub *databus.Databus
bnjSub *databus.Databus
// vip binlog databus
//vipSub *databus.Databus
kfcSub *databus.Databus
kfcActionCh []chan *kfcmdl.CouponMsg
kfcShare int
subActionCh []chan *l.Action
actionSM []map[int64]*l.LastTmStat
// bnj
bnjMaxSecond int64
bnjLessSecond int64
bnjTimeFinish int64
bnjMsgFlagMap map[int]int64
bnjMsgFlagMu sync.Mutex
bnjWxMsgFlagMap map[int]int64
bnjWxMsgFlagMu sync.Mutex
// cron
cron *cron.Cron
}
// New is archive service implementation.
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
dao: like.New(c),
dm: dm.New(c),
bnj: bnj.New(c),
kfcDao: kfc.New(c),
arcRPC: arcrpc.New2(c.ArchiveRPC),
articleRPC: artrpc.New(c.ArticleRPC),
coinRPC: coin.New(c.CoinRPC),
actRPC: actrpc.New(c.ActRPC),
actSub: databus.New(c.ActSub),
bnjSub: databus.New(c.BnjSub),
//vipSub: databus.New(c.VipSub),
kfcSub: databus.New(c.KfcSub),
cron: cron.New(),
}
var err error
if s.accClient, err = api.NewClient(c.AccClient); err != nil {
panic(err)
}
if s.c.Bnj2019.MsgSpec != "" {
if err = s.cron.AddFunc(s.c.Bnj2019.MsgSpec, s.cronInformationMessage); err != nil {
panic(err)
}
log.Info("cronInformationMessage init")
s.cron.Start()
}
//time.Sleep(2 * time.Second)
//subject, err := s.sub(context.Background(), c.Rule.BroadcastSid)
//if err != nil {
// log.Error("error(%v)", err)
// return
//}
//log.Info("start-subject")
//log.Info("subject(%v)", subject)
//log.Info("end-subject")
//if subject != nil {
// go s.genesis(subject)
//}
s.bnjMsgFlagMap = make(map[int]int64, len(bnjSteps))
s.bnjWxMsgFlagMap = make(map[int]int64, len(bnjSteps))
for _, step := range bnjSteps {
s.bnjMsgFlagMap[step] = 0
s.bnjWxMsgFlagMap[step] = 0
}
for i := 0; i < _sharding; i++ {
s.subActionCh = append(s.subActionCh, make(chan *l.Action, 10240))
s.actionSM = append(s.actionSM, map[int64]*l.LastTmStat{})
s.waiter.Add(1)
go s.actionDealProc(i)
}
//s.waiter.Add(1)
//go s.vipCanal()
s.waiter.Add(1)
go s.consumeCanal()
go s.subjectStat(s.c.Rule.ArcObjStatSid, _typeArc)
go s.subjectStat(s.c.Rule.ArtObjStatSid, _typeArt)
go s.kingStoryTotalStat(s.c.Rule.KingStorySid)
go s.subsRankproc()
go s.initBnjSecond()
if runtime.NumCPU() <= 4 {
s.kfcShare = 4
} else if runtime.NumCPU() > 32 {
s.kfcShare = 32
} else {
s.kfcShare = runtime.NumCPU()
}
for j := 0; j < s.kfcShare; j++ {
s.kfcActionCh = append(s.kfcActionCh, make(chan *kfcmdl.CouponMsg, 10240))
s.waiter.Add(1)
go s.kfcActionDeal(j)
}
s.waiter.Add(1)
go s.kfcCanal()
return s
}
func (s *Service) likeArc(c context.Context, sub *l.Subject) (res *l.Subject, err error) {
if sub != nil {
if sub.ID == 0 {
res = nil
} else {
res = sub
var (
ok bool
arcs map[int64]*arcapi.Arc
aids []int64
)
for _, l := range res.List {
aids = append(aids, l.Wid)
}
argAids := &comarcmdl.ArgAids2{
Aids: aids,
}
if arcs, err = s.arcRPC.Archives3(c, argAids); err != nil {
log.Error("s.arcRPC.Archives(arcAids:(%v), arcs), err(%v)", aids, err)
return
}
for _, l := range res.List {
if l.Archive, ok = arcs[l.Wid]; !ok {
log.Info("s.arcs.wid:(%d), (%v)", l.Wid, ok)
continue
}
}
}
}
return
}
//func (s *Service) genesis(l *l.Subject) {
// var (
// index int
// nowTime, stage, yes, no, next int64
// err error
// c = context.Background()
// )
// log.Info("st")
// for {
// if time.Now().Unix() >= l.Stime.Time().Unix() {
// break
// }
// time.Sleep(time.Second)
// }
// lstime := map[string]interface{}{
// "aid": 0,
// "time": 0,
// "index": 0,
// "stage": 0,
// }
// go s.inLtime(lstime, l.ID)
// for i, a := range l.List {
// arg1 := &comarcmdl.ArgAid2{Aid: a.Archive.Aid}
// arc, errRPC := s.arcRPC.Archive3(c, arg1)
// if errRPC != nil {
// log.Error("act-job s.arcRPC.Archive3(%v) error(%v)", arg1, errRPC)
// errRPC = nil
// continue
// }
// if arc.State < 0 && arc.State != -6 {
// log.Error("act-job s.arcRPC.Archive3(%v) stat err", arg1)
// }
// index = i
// nowTime = 0
// stage = 0
// next = 0
// time.Sleep(time.Duration(l.Ltime) * time.Second)
// log.Info("aid sleep")
// aidTime := time.Now().Unix()
// ltime := map[string]interface{}{
// "aid": a.Archive.Aid,
// "time": aidTime,
// "index": i,
// "stage": stage,
// "title": arc.Title,
// "author": arc.Author.Name,
// "tname": arc.TypeName,
// }
// go s.inLtime(ltime, l.ID)
// for {
// fmt.Println(stage)
// log.Info("s.stage{%d}", stage)
// //演出开始
// ltime := map[string]interface{}{
// "aid": a.Archive.Aid,
// "time": aidTime,
// "index": i,
// "stage": stage,
// "title": arc.Title,
// "author": arc.Author.Name,
// "tname": arc.TypeName,
// }
// go s.inLtime(ltime, l.ID)
// tp := l.Interval - l.Ltime
// nowTime += tp
// time.Sleep(time.Duration(tp) * time.Second)
// //预备投票
// sdm := &dmm.ActDM{Act: _startVoteP, Aid: a.Archive.Aid, Next: next, Yes: 0, No: 0, Stage: stage, Title: arc.Title, Author: arc.Author.Name, Tname: arc.TypeName}
// go s.brodcast(sdm)
// log.Info("act:1")
// go s.dao.CreateSelection(c, a.Archive.Aid, stage)
// nowTime += l.Ltime
// time.Sleep(time.Duration(l.Ltime) * time.Second)
// //投票开始
// interval := &dmm.ActDM{Act: _startVote, Aid: a.Archive.Aid, Next: next, Yes: 0, No: 0, Stage: stage, Title: arc.Title, Author: arc.Author.Name, Tname: arc.TypeName}
// go s.brodcast(interval)
// log.Info("act:2")
// tl := l.Tlimit - l.Ltime
// nowTime += tl
// time.Sleep(time.Duration(tl) * time.Second)
// //投票预结束
// intervalP := &dmm.ActDM{Act: _endingVote, Aid: a.Archive.Aid, Next: next, Yes: 0, No: 0, Stage: stage, Title: arc.Title, Author: arc.Author.Name, Tname: arc.TypeName}
// log.Info("act:3")
// go s.brodcast(intervalP)
// nowTime += l.Ltime
// time.Sleep(time.Duration(l.Ltime) * time.Second)
// //投票结果
// if yes, no, err = s.dao.Selection(c, a.Archive.Aid, stage); err != nil {
// log.Error("s.dao.Selection() error(%v)", err)
// return
// }
// goNext := true
// if yes != 0 || no != 0 {
// goNext = (float64(no)/float64(yes+no)*100 > 40)
// }
// if goNext {
// next = 1
// } else {
// next = 0
// }
// intervalEnd := &dmm.ActDM{Act: _endVote, Aid: a.Archive.Aid, Next: next, Yes: yes, No: no, Stage: stage, Title: arc.Title, Author: arc.Author.Name, Tname: arc.TypeName}
// go s.brodcast(intervalEnd)
// log.Info("act:4")
// nowTime += l.Ltime
// time.Sleep(time.Duration(l.Ltime) * time.Second)
// go s.inOnlinelog(c, l.ID, a.Archive.Aid, stage, yes, no)
// if goNext {
// tlimit := &dmm.ActDM{Act: _next, Aid: a.Archive.Aid, Next: next, Yes: yes, No: no, Stage: stage, Title: arc.Title, Author: arc.Author.Name, Tname: arc.TypeName}
// go s.brodcast(tlimit)
// log.Info("act:6")
// nowTime += l.Ltime
// ldtime := map[string]interface{}{
// "aid": 0,
// "time": time.Now().Unix() + l.Ltime,
// "index": i + 1,
// "stage": 0,
// "title": arc.Title,
// "author": arc.Author.Name,
// "tname": arc.TypeName,
// }
// go s.inLtime(ldtime, l.ID)
// time.Sleep(time.Duration(l.Ltime) * time.Second)
// break
// }
// tlimit := &dmm.ActDM{Act: _goOn, Aid: a.Archive.Aid, Next: next, Yes: yes, No: no, Stage: stage, Title: arc.Title, Author: arc.Author.Name, Tname: arc.TypeName}
// log.Info("bro:%v", tlimit)
// go s.brodcast(tlimit)
// log.Info("act:5")
// //投票结果判断
// stage++
// if a.Archive.Duration-nowTime < 60 {
// go s.inOnlinelog(c, l.ID, a.Archive.Aid, 100, 0, 0)
// time.Sleep(time.Duration(a.Archive.Duration-nowTime) * time.Second)
// break
// }
// }
// }
// ltime := map[string]interface{}{
// "aid": 0,
// "time": time.Now().Unix(),
// "index": index + 1,
// "stage": 0,
// "title": "",
// "author": "",
// "tname": "",
// }
// go s.inLtime(ltime, l.ID)
// log.Info("end")
//}
//
//func (s *Service) inOnlinelog(c context.Context, sid, aid, stage, yes, no int64) {
// if row, err := s.dao.InOnlinelog(c, sid, aid, stage, yes, no); err != nil {
// log.Error("s.dao.inOnlinelog, err(%v) row(%v)", err, row)
// }
//}
//
//func (s *Service) inLtime(lt map[string]interface{}, sid int64) {
// var v, err = json.Marshal(lt)
// if err != nil {
// log.Error("s.genesis.inLtime.json.Marshal(dm:(%v)), err(%v)", v, err)
// return
// }
// s.dao.RbSet(context.Background(), "ltime:"+strconv.FormatInt(sid, 10), v)
//}
//
//func (s *Service) brodcast(d *dmm.ActDM) {
// var ds, err = json.Marshal(d)
// if err != nil {
// log.Error("s.genesis.json.Marshal(dm:(%v)), err(%v)", d, err)
// return
// }
// var m = &dmm.Broadcast{
// RoomID: s.c.Rule.BroadcastCid,
// CMD: dmm.BroadcastCMDACT,
// Info: ds,
// }
// s.dm.Broadcast(context.Background(), m)
//}
//
//func (s *Service) sub(c context.Context, sid int64) (res *l.Subject, err error) {
// var (
// eg errgroup.Group
// ls []*l.Like
// )
// eg.Go(func() (err error) {
// res, err = s.dao.Subject(c, sid)
// return
// })
// eg.Go(func() (err error) {
// ls, err = s.dao.Like(c, sid)
// return
// })
// if err = eg.Wait(); err != nil {
// log.Error("eg.Wait error(%v)", err)
// return
// }
// if res != nil {
// res.List = ls
// }
// if res, err = s.likeArc(c, res); err != nil {
// return
// }
// return
//}
//func (s *Service) vipCanal() {
// defer s.waiter.Done()
// var c = context.Background()
// for {
// msg, ok := <-s.vipSub.Messages()
// if !ok {
// log.Info("databus:activity-job vip binlog consumer exit!")
// return
// }
// msg.Commit()
// m := &match.Message{}
// if err := json.Unmarshal(msg.Value, m); err != nil {
// log.Error("json.Unmarshal(%s) error(%+v)", msg.Value, err)
// continue
// }
// switch m.Table {
// case _vipActOrderTable:
// if m.Action == match.ActInsert {
// s.addElemeLottery(c, m.New)
// }
// }
// log.Info("vipCanal key:%s partition:%d offset:%d table:%s", msg.Key, msg.Partition, msg.Offset, m.Table)
// }
//}
func (s *Service) consumeCanal() {
defer s.waiter.Done()
var c = context.Background()
for {
msg, ok := <-s.actSub.Messages()
if !ok {
log.Info("databus: activity-job binlog consumer exit!")
return
}
msg.Commit()
m := &match.Message{}
if err := json.Unmarshal(msg.Value, m); err != nil {
log.Error("json.Unmarshal(%s) error(%+v)", msg.Value, err)
continue
}
switch m.Table {
case _matchObjTable:
if m.Action == match.ActUpdate {
s.upMatchUser(c, m.New, m.Old)
}
case _subjectTable:
if m.Action == match.ActInsert || m.Action == match.ActUpdate {
s.upSubject(c, m.New)
} else if m.Action == match.ActDelete {
s.upSubject(c, m.Old)
}
case _likesTable:
if m.Action == match.ActInsert {
s.AddLike(c, m.New)
} else if m.Action == match.ActUpdate {
s.UpLike(c, m.New, m.Old)
} else if m.Action == match.ActDelete {
s.DelLike(c, m.Old)
}
case _likeContentTable:
if m.Action == match.ActDelete {
s.upLikeContent(c, m.Old)
} else {
s.upLikeContent(c, m.New)
}
case _likeActionTable:
if m.Action == match.ActInsert {
s.actionProc(c, m.New)
}
}
log.Info("consumeCanal key:%s partition:%d offset:%d table:%s", msg.Key, msg.Partition, msg.Offset, m.Table)
}
}
func (s *Service) kfcCanal() {
defer s.waiter.Done()
for {
if s.closed {
return
}
msg, ok := <-s.kfcSub.Messages()
if !ok {
log.Info("databus: activity-job binlog consumer exit!")
return
}
msg.Commit()
m := &kfcmdl.CouponMsg{}
if err := json.Unmarshal(msg.Value, m); err != nil {
log.Error("kfcCanal:json.Unmarshal(%s) error(%+v)", msg.Value, err)
continue
}
j := m.CouponID % int64(s.kfcShare)
select {
case s.kfcActionCh[j] <- m:
default:
log.Info("kfcCanal cache full (%d)", j)
}
log.Info("kfcCanal key:%s partition:%d offset:%d value %s goroutine(%d) all(%d)", msg.Key, msg.Partition, msg.Offset, msg.Value, j, s.kfcShare)
}
}
func (s *Service) subjectStat(sid int64, typ string) {
var err error
for {
if s.closed {
return
}
var (
statLike int64
likeCnt int
likes []*l.Like
)
if sid <= 0 {
log.Warn("conf sid == 0 typ(%s)", typ)
time.Sleep(time.Duration(s.c.Interval.ObjStatInterval))
continue
}
if likeCnt, err = s.dao.LikeCnt(context.Background(), sid); err != nil {
log.Error("s.dao.LikeCnt(sid:%d) error(%v)", sid, err)
time.Sleep(time.Duration(s.c.Interval.ObjStatInterval))
continue
}
if likeCnt == 0 {
log.Warn("s.dao.LikeCnt(sid:%d) likeCnt == 0", sid)
time.Sleep(time.Duration(s.c.Interval.ObjStatInterval))
continue
}
for i := 0; i < likeCnt; i += _objectPieceSize {
if likes, err = s.likeList(context.Background(), sid, i, _objectPieceSize, _retryTimes); err != nil {
log.Error("objectStatproc s.likeList(%d,%d,%d) error(%+v)", sid, i, _objectPieceSize, err)
time.Sleep(100 * time.Millisecond)
continue
} else {
var aids []int64
for _, v := range likes {
if v.Wid > 0 {
aids = append(aids, v.Wid)
}
}
switch typ {
case _typeArc:
var arcs map[int64]*arcapi.Arc
if arcs, err = s.arcs(context.Background(), aids, _retryTimes); err != nil {
log.Error("objectStatproc s.arcs(%v) error(%v)", aids, err)
time.Sleep(100 * time.Millisecond)
continue
} else {
for _, aid := range aids {
if arc, ok := arcs[aid]; ok && arc.IsNormal() {
statLike += int64(arc.Stat.Like)
} else {
likeCnt--
}
}
}
case _typeArt:
var arts map[int64]*artmdl.Meta
if arts, err = s.arts(context.Background(), aids, _retryTimes); err != nil {
log.Error("objectStatproc s.arcs(%v) error(%v)", aids, err)
time.Sleep(100 * time.Microsecond)
continue
} else {
for _, aid := range aids {
if art, ok := arts[aid]; ok && art.IsNormal() {
statLike += art.Stats.Like
} else {
likeCnt--
}
}
}
}
}
}
if err = s.setSubjectStat(context.Background(), sid, &l.SubjectTotalStat{SumLike: statLike}, likeCnt, _retryTimes); err != nil {
log.Error("objectStatproc s.setObjectStat(%d,%d) error(%+v)", sid, statLike, err)
time.Sleep(time.Duration(s.c.Interval.ObjStatInterval))
continue
}
time.Sleep(time.Duration(s.c.Interval.ObjStatInterval))
}
}
func (s *Service) likeList(c context.Context, sid int64, offset, limit, retryCnt int) (list []*l.Like, err error) {
for i := 0; i < retryCnt; i++ {
if list, err = s.dao.LikeList(c, sid, offset, limit); err == nil {
break
}
time.Sleep(100 * time.Millisecond)
}
return
}
func (s *Service) webDataList(c context.Context, vid int64, offset, limit, retryCnt int) (list []*l.WebData, err error) {
for i := 0; i < retryCnt; i++ {
if list, err = s.dao.WebDataList(c, vid, offset, limit); err == nil {
break
}
time.Sleep(100 * time.Millisecond)
}
return
}
func (s *Service) arts(c context.Context, aids []int64, retryCnt int) (arcs map[int64]*artmdl.Meta, err error) {
for i := 0; i < retryCnt; i++ {
if arcs, err = s.articleRPC.ArticleMetas(c, &artmdl.ArgAids{Aids: aids}); err == nil {
break
}
time.Sleep(100 * time.Millisecond)
}
return
}
func (s *Service) kingStoryTotalStat(vid int64) {
var err error
for {
if s.closed {
return
}
var (
statView, statLike, statFav, StatCoin int64
likeCnt int
likes []*l.WebData
)
if vid <= 0 {
log.Warn("conf vid == 0")
time.Sleep(time.Duration(s.c.Interval.KingStoryInterval))
continue
}
if likeCnt, err = s.dao.WebDataCnt(context.Background(), vid); err != nil {
log.Error("kingStoryTotalStat s.dao.WebDataCnt(sid:%d) error(%v)", vid, err)
time.Sleep(time.Duration(s.c.Interval.KingStoryInterval))
continue
}
if likeCnt == 0 {
log.Warn("kingStoryTotalStat s.dao.LikeCnt(sid:%d) likeCnt == 0", vid)
time.Sleep(time.Duration(s.c.Interval.KingStoryInterval))
continue
}
for i := 0; i < likeCnt; i += _objectPieceSize {
if likes, err = s.webDataList(context.Background(), vid, i, _objectPieceSize, _retryTimes); err != nil {
log.Error("kingStoryTotalStat s.webDataList(%d,%d,%d) error(%+v)", vid, i, _objectPieceSize, err)
time.Sleep(100 * time.Millisecond)
continue
} else {
var (
aids []int64
aidStruct = new(struct {
Aid string `json:"AID"`
})
)
for _, v := range likes {
if v.Data != "" {
if e := json.Unmarshal([]byte(v.Data), &aidStruct); e != nil {
log.Warn("kingStoryTotalStat json.Unmarshal(%s) error(%v)", v.Data, e)
continue
}
if aid, e := strconv.ParseInt(aidStruct.Aid, 10, 64); e != nil {
log.Warn("kingStoryTotalStat strconv.ParseInt(%s) error(%v)", aidStruct, e)
continue
} else {
aids = append(aids, aid)
}
}
}
var arcs map[int64]*arcapi.Arc
if arcs, err = s.arcs(context.Background(), aids, _retryTimes); err != nil {
log.Error("kingStoryTotalStat s.arcs(%v) error(%v)", aids, err)
time.Sleep(100 * time.Millisecond)
continue
} else {
for _, aid := range aids {
if arc, ok := arcs[aid]; ok && arc.IsNormal() {
statView += int64(arc.Stat.View)
statLike += int64(arc.Stat.Like)
statFav += int64(arc.Stat.Fav)
StatCoin += int64(arc.Stat.Coin)
}
}
}
}
}
if err = s.setSubjectStat(context.Background(), vid, &l.SubjectTotalStat{SumView: statView, SumLike: statLike, SumFav: statFav, SumCoin: StatCoin}, likeCnt, _retryTimes); err != nil {
log.Error("kingStoryTotalStat s.setObjectStat(%d,%d) error(%+v)", vid, statLike, err)
time.Sleep(time.Duration(s.c.Interval.KingStoryInterval))
continue
}
time.Sleep(time.Duration(s.c.Interval.KingStoryInterval))
}
}
func (s *Service) setSubjectStat(c context.Context, sid int64, stat *l.SubjectTotalStat, count, retryCnt int) (err error) {
for i := 0; i < retryCnt; i++ {
if err = s.dao.SetObjectStat(c, sid, stat, count); err == nil {
break
}
time.Sleep(100 * time.Millisecond)
}
return
}
// Ping reports the heath of services.
func (s *Service) Ping(c context.Context) (err error) {
return s.dao.Ping(c)
}
// Close kafaka consumer close.
func (s *Service) Close() (err error) {
defer s.waiter.Wait()
s.closed = true
if s.bnjTimeFinish == 0 {
s.bnj.AddCacheLessTime(context.Background(), s.bnjLessSecond)
}
s.cron.Stop()
s.dao.Close()
s.actSub.Close()
s.bnjSub.Close()
//s.vipSub.Close()
s.kfcSub.Close()
s.closed = true
return
}

View File

@@ -0,0 +1,44 @@
package service
import (
"context"
"flag"
"path/filepath"
"testing"
"time"
"go-common/app/job/main/activity/conf"
l "go-common/app/job/main/activity/model/like"
. "github.com/smartystreets/goconvey/convey"
)
var svf *Service
func init() {
dir, _ := filepath.Abs("../../cmd/activity-job-test.toml")
flag.Set("conf", dir)
if err := conf.Init(); err != nil {
panic(err)
}
if svf == nil {
svf = New(conf.Conf)
}
time.Sleep(time.Second)
}
func WithService(f func(s *Service)) func() {
return func() {
f(svf)
}
}
func TestService_LikeArc(t *testing.T) {
Convey("test archive view", t, WithService(func(s *Service) {
sub := &l.Subject{
ID: 1,
}
res, err := s.likeArc(context.Background(), sub)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
}))
}

View File

@@ -0,0 +1,45 @@
package service
import (
"context"
"encoding/json"
actmdl "go-common/app/interface/main/activity/model/like"
l "go-common/app/job/main/activity/model/like"
"go-common/library/log"
)
// upSubject update act_subject cache .
func (s *Service) upSubject(c context.Context, upMsg json.RawMessage) (err error) {
var (
subObj = new(l.ActSubject)
)
if err = json.Unmarshal(upMsg, subObj); err != nil {
log.Error("upSubject json.Unmarshal(%s) error(%+v)", upMsg, err)
return
}
if err = s.actRPC.SubjectUp(c, &actmdl.ArgSubjectUp{Sid: subObj.ID}); err != nil {
log.Error("s.actRPC.SubjectUp(%d) error(%+v)", subObj.ID, err)
return
}
log.Info("upSubject success s.actRPC.SubjectUp(%d)", subObj.ID)
return
}
//func (s *Service) addElemeLottery(c context.Context, msg json.RawMessage) {
// var (
// vipContent = &l.VipActOrder{}
// )
// if err := json.Unmarshal(msg, vipContent); err != nil {
// log.Error("addElemeLottery json.Unmarshal(%s) error(%v)", msg, err)
// return
// }
// if vipContent.PanelType == "ele" {
// if err := s.dao.AddLotteryTimes(c, s.c.Rule.EleLotteryID, vipContent.Mid); err != nil {
// log.Error("s.dao.AddLotteryTimes(%d,%d) error(%v)", s.c.Rule.EleLotteryID, vipContent.Mid, err)
// return
// }
// log.Info("addElemeLottery has AddLotteryTimes %d", vipContent.Mid)
// }
// log.Info("addElemeLottery success id:%d,panee:%s", vipContent.ID, vipContent.PanelType)
//}