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
|
|||
|
}
|