go-common/app/job/main/favorite/service/service.go

242 lines
5.9 KiB
Go
Raw Normal View History

2019-04-22 10:49:16 +00:00
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 zerom:%+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
}