242 lines
5.9 KiB
Go
242 lines
5.9 KiB
Go
package service
|
||
|
||
import (
|
||
"context"
|
||
"encoding/json"
|
||
"sync"
|
||
"time"
|
||
|
||
artmdl "go-common/app/interface/openplatform/article/model"
|
||
artrpc "go-common/app/interface/openplatform/article/rpc/client"
|
||
"go-common/app/job/main/favorite/conf"
|
||
favDao "go-common/app/job/main/favorite/dao/fav"
|
||
musicDao "go-common/app/job/main/favorite/dao/music"
|
||
pubDao "go-common/app/job/main/favorite/dao/pub"
|
||
statDao "go-common/app/job/main/favorite/dao/stat"
|
||
"go-common/app/service/main/archive/api"
|
||
arcrpc "go-common/app/service/main/archive/api/gorpc"
|
||
arcmdl "go-common/app/service/main/archive/model/archive"
|
||
coinrpc "go-common/app/service/main/coin/api/gorpc"
|
||
coinmdl "go-common/app/service/main/coin/model"
|
||
favmdl "go-common/app/service/main/favorite/model"
|
||
"go-common/library/log"
|
||
"go-common/library/queue/databus"
|
||
"go-common/library/sync/pipeline/fanout"
|
||
)
|
||
|
||
// Service favorite service.
|
||
type Service struct {
|
||
c *conf.Config
|
||
waiter *sync.WaitGroup
|
||
// fav
|
||
cleanCDTime int64
|
||
// dao
|
||
pubDao *pubDao.Dao
|
||
statDao *statDao.Dao
|
||
favDao *favDao.Dao
|
||
// databus
|
||
consumer *databus.Databus
|
||
playStatSub *databus.Databus
|
||
favStatSub *databus.Databus
|
||
shareStatSub *databus.Databus
|
||
procChan []chan *favmdl.Message
|
||
// rpc
|
||
coinRPC *coinrpc.Service
|
||
arcRPC *arcrpc.Service2
|
||
artRPC *artrpc.Service
|
||
// cache chan
|
||
cache *fanout.Fanout
|
||
statMerge *statMerge
|
||
musicDao *musicDao.Dao
|
||
}
|
||
|
||
type statMerge struct {
|
||
Business int
|
||
Target int64
|
||
Sources map[int64]bool
|
||
}
|
||
|
||
// New new a service and return.
|
||
func New(c *conf.Config) (s *Service) {
|
||
if c.Fav.Proc <= 0 {
|
||
c.Fav.Proc = 32
|
||
}
|
||
s = &Service{
|
||
c: c,
|
||
waiter: new(sync.WaitGroup),
|
||
// fav
|
||
cleanCDTime: int64(time.Duration(c.Fav.CleanCDTime) / time.Second),
|
||
// dao
|
||
favDao: favDao.New(c),
|
||
pubDao: pubDao.New(c),
|
||
statDao: statDao.New(c),
|
||
musicDao: musicDao.New(c),
|
||
// databus
|
||
consumer: databus.New(c.JobDatabus),
|
||
procChan: make([]chan *favmdl.Message, c.Fav.Proc),
|
||
// stat databus
|
||
playStatSub: databus.New(c.MediaListCntDatabus),
|
||
favStatSub: databus.New(c.FavStatDatabus),
|
||
shareStatSub: databus.New(c.ShareStatDatabus),
|
||
// rpc
|
||
coinRPC: coinrpc.New(c.RPCClient2.Coin),
|
||
artRPC: artrpc.New(c.RPCClient2.Article),
|
||
arcRPC: arcrpc.New2(c.RPCClient2.Archive),
|
||
// cache chan
|
||
cache: fanout.New("cache"),
|
||
}
|
||
|
||
if c.StatMerge != nil {
|
||
s.statMerge = &statMerge{
|
||
Business: c.StatMerge.Business,
|
||
Target: c.StatMerge.Target,
|
||
Sources: make(map[int64]bool),
|
||
}
|
||
for _, id := range c.StatMerge.Sources {
|
||
s.statMerge.Sources[id] = true
|
||
}
|
||
}
|
||
|
||
for i := int64(0); i < c.Fav.Proc; i++ {
|
||
ch := make(chan *favmdl.Message, 128)
|
||
s.procChan[i] = ch
|
||
s.waiter.Add(1)
|
||
go s.jobproc(ch)
|
||
}
|
||
|
||
s.waiter.Add(1)
|
||
go s.consumeStat()
|
||
|
||
s.waiter.Add(1)
|
||
go s.consumeproc()
|
||
return
|
||
}
|
||
|
||
func (s *Service) consumeproc() {
|
||
offsets := make(map[int32]int64, 9)
|
||
defer func() {
|
||
log.Info("end databus msg offsets:%v", offsets)
|
||
s.waiter.Done()
|
||
}()
|
||
for {
|
||
msg, ok := <-s.consumer.Messages()
|
||
if !ok {
|
||
log.Info("consumeproc exit")
|
||
for _, c := range s.procChan {
|
||
close(c)
|
||
}
|
||
return
|
||
}
|
||
if _, ok := offsets[msg.Partition]; !ok {
|
||
log.Info("begin databus msg offsets:%v", offsets)
|
||
}
|
||
offsets[msg.Partition] = msg.Offset
|
||
|
||
msg.Commit()
|
||
m := &favmdl.Message{}
|
||
if err := json.Unmarshal(msg.Value, m); err != nil {
|
||
log.Error("json.Unmarshal() error(%v)", err)
|
||
continue
|
||
}
|
||
if m.Mid <= 0 {
|
||
log.Warn("m.Mid shuld not be equal or lesser than zero,m:%+v", m)
|
||
continue
|
||
}
|
||
log.Info("consumer topic:%s, partitionId:%d, offset:%d, Key:%s, Value:%s Mid:%d Proc:%d", msg.Topic, msg.Partition, msg.Offset, msg.Key, msg.Value, m.Mid, s.c.Fav.Proc)
|
||
s.procChan[m.Mid%s.c.Fav.Proc] <- m
|
||
}
|
||
}
|
||
|
||
func (s *Service) jobproc(ch chan *favmdl.Message) {
|
||
defer s.waiter.Done()
|
||
for {
|
||
m, ok := <-ch
|
||
if !ok {
|
||
log.Info("jobproc exit")
|
||
return
|
||
}
|
||
switch m.Field {
|
||
case favmdl.FieldResource:
|
||
if err := s.upResource(context.Background(), m); err != nil {
|
||
log.Error("upResource(%v) error(%v)", m, err)
|
||
continue
|
||
}
|
||
default:
|
||
}
|
||
}
|
||
}
|
||
|
||
// Close close.
|
||
func (s *Service) Close() (err error) {
|
||
if err = s.consumer.Close(); err != nil {
|
||
log.Error("s.consumer.Close() error(%v)", err)
|
||
return
|
||
}
|
||
return s.favDao.Close()
|
||
}
|
||
|
||
// Wait wait.
|
||
func (s *Service) Wait() {
|
||
s.waiter.Wait()
|
||
}
|
||
|
||
// Ping ping method for server check
|
||
func (s *Service) Ping(c context.Context) (err error) {
|
||
if err = s.favDao.Ping(c); err != nil {
|
||
log.Error("s.favDao.Ping error(%v)", err)
|
||
return
|
||
}
|
||
return
|
||
}
|
||
|
||
// ArcRPC find archive by rpc
|
||
func (s *Service) archiveRPC(c context.Context, aid int64) (a *api.Arc, err error) {
|
||
argAid := &arcmdl.ArgAid2{
|
||
Aid: aid,
|
||
}
|
||
if a, err = s.arcRPC.Archive3(c, argAid); err != nil {
|
||
log.Error("arcRPC.Archive3(%v, archive), err(%v)", argAid, err)
|
||
}
|
||
return
|
||
}
|
||
|
||
// AddCoinRpc check user whether or not banned to post
|
||
func (s *Service) addCoinRPC(c context.Context, mid int64, coin float64, reason string) (err error) {
|
||
if _, err = s.coinRPC.ModifyCoin(c, &coinmdl.ArgModifyCoin{Mid: mid, Count: coin, Reason: reason}); err != nil {
|
||
log.Error("coinRPC.ModifyCoin(%v, %v), err(%v)", mid, coin, err)
|
||
}
|
||
return
|
||
}
|
||
|
||
// articleRPC find aritile by rpc
|
||
func (s *Service) articleRPC(c context.Context, aid int64) (a map[int64]*artmdl.Meta, err error) {
|
||
argAid := &artmdl.ArgAids{
|
||
Aids: []int64{aid},
|
||
}
|
||
if a, err = s.artRPC.ArticleMetas(c, argAid); err != nil {
|
||
log.Error("d.artRPC.ArticleMetas(%+v), error(%v)", argAid, err)
|
||
}
|
||
return
|
||
}
|
||
|
||
// ArcsRPC find archives by rpc.
|
||
func (s *Service) ArcsRPC(c context.Context, aids []int64) (as map[int64]*api.Arc, err error) {
|
||
if len(aids) == 0 {
|
||
return
|
||
}
|
||
argAids := &arcmdl.ArgAids2{
|
||
Aids: aids,
|
||
}
|
||
if as, err = s.arcRPC.Archives3(c, argAids); err != nil {
|
||
log.Error("s.arcRPC.Archives3(%v), error(%v)", argAids, err)
|
||
}
|
||
return
|
||
}
|
||
|
||
func (s *Service) mergeTarget(business int, aid int64) int64 {
|
||
if s.statMerge != nil && s.statMerge.Business == business && s.statMerge.Sources[aid] {
|
||
return s.statMerge.Target
|
||
}
|
||
return 0
|
||
}
|