go-common/app/job/main/sms/service/service.go
2019-04-22 18:49:16 +08:00

151 lines
4.2 KiB
Go

package service
import (
"context"
"sync"
"go-common/app/job/main/sms/conf"
"go-common/app/job/main/sms/dao"
"go-common/app/job/main/sms/dao/chuanglan"
"go-common/app/job/main/sms/dao/mengwang"
"go-common/app/job/main/sms/model"
smsgrpc "go-common/app/service/main/sms/api"
smsmdl "go-common/app/service/main/sms/model"
"go-common/library/log"
"go-common/library/queue/databus"
"go-common/library/sync/pipeline/fanout"
)
// Service struct of service.
type Service struct {
c *conf.Config
dao *dao.Dao
databus *databus.Databus
smsgrpc smsgrpc.SmsClient
waiter *sync.WaitGroup
sms chan *smsmdl.ModelSend // 验证码
actSms chan *smsmdl.ModelSend // 营销
batchSms chan *smsmdl.ModelSend // 批量
smsp *model.ConcurrentRing
intep *model.ConcurrentRing
actp *model.ConcurrentRing
batchp *model.ConcurrentRing
cache *fanout.Fanout
providers int
closed bool
smsCount int64
blacklist map[string]struct{}
}
// New create service instance and return.
func New(c *conf.Config) (s *Service) {
proLen := len(c.Provider.Providers)
if c.Speedup.Switch {
proLen *= 2 // 每个短信服务商再提供一个云线路 http client
}
s = &Service{
c: c,
dao: dao.New(c),
databus: databus.New(c.Databus),
waiter: new(sync.WaitGroup),
sms: make(chan *smsmdl.ModelSend, 10240),
actSms: make(chan *smsmdl.ModelSend, 10240),
batchSms: make(chan *smsmdl.ModelSend, 10240),
smsp: model.NewConcurrentRing(proLen),
intep: model.NewConcurrentRing(proLen),
actp: model.NewConcurrentRing(proLen),
batchp: model.NewConcurrentRing(proLen),
cache: fanout.New("async-task", fanout.Worker(1), fanout.Buffer(10240)),
providers: proLen,
}
s.initBlacklist()
var err error
if s.smsgrpc, err = smsgrpc.NewClient(c.SmsGRPC); err != nil {
panic(err)
}
s.initProviders()
s.waiter.Add(1)
go s.subproc()
go s.monitorproc()
for i := 0; i < s.c.Sms.SingleSendProc; i++ {
s.waiter.Add(1)
go s.smsproc()
s.waiter.Add(1)
go s.actsmsproc()
}
for i := 0; i < s.c.Sms.BatchSendProc; i++ {
s.waiter.Add(1)
go s.actbatchproc()
}
return
}
func (s *Service) initBlacklist() {
s.blacklist = make(map[string]struct{})
for _, v := range s.c.Sms.Blacklist {
s.blacklist[v] = struct{}{}
}
}
func (s *Service) initProviders() {
// 创建本地网络 http client
s.newProviders(s.c)
if !s.c.Speedup.Switch {
return
}
// 替换成 云加速线路 URL 配置
s.c.Provider.MengWangSmsURL = s.c.Speedup.MengWangSmsURL
s.c.Provider.MengWangActURL = s.c.Speedup.MengWangActURL
s.c.Provider.MengWangBatchURL = s.c.Speedup.MengWangBatchURL
s.c.Provider.MengWangInternationURL = s.c.Speedup.MengWangInternationURL
s.c.Provider.ChuangLanSmsURL = s.c.Speedup.ChuangLanSmsURL
s.c.Provider.ChuangLanActURL = s.c.Speedup.ChuangLanActURL
s.c.Provider.ChuangLanInternationURL = s.c.Speedup.ChuangLanInternationURL
s.c.Provider.MengWangSmsCallbackURL = s.c.Speedup.MengWangSmsCallbackURL
s.c.Provider.MengWangActCallbackURL = s.c.Speedup.MengWangActCallbackURL
s.c.Provider.MengWangInternationalCallbackURL = s.c.Speedup.MengWangInternationalCallbackURL
s.c.Provider.ChuangLanSmsCallbackURL = s.c.Speedup.ChuangLanSmsCallbackURL
s.c.Provider.ChuangLanActCallbackURL = s.c.Speedup.ChuangLanActCallbackURL
s.c.Provider.ChuangLanInternationalCallbackURL = s.c.Speedup.ChuangLanInternationalCallbackURL
// 创建云加速线路 http client
s.newProviders(s.c)
}
func (s *Service) newProviders(c *conf.Config) {
var cli model.Provider
for _, p := range c.Provider.Providers {
switch p {
case smsmdl.ProviderMengWang:
cli = mengwang.NewClient(c)
case smsmdl.ProviderChuangLan:
cli = chuanglan.NewClient(c)
default:
log.Error("invalid provider(%d)", p)
continue
}
s.smsp.Value = cli
s.smsp.Ring = s.smsp.Next()
s.intep.Value = cli
s.intep.Ring = s.intep.Next()
s.actp.Value = cli
s.actp.Ring = s.actp.Next()
s.batchp.Value = cli
s.batchp.Ring = s.batchp.Next()
for i := 0; i < s.c.Sms.CallbackProc; i++ {
s.dispatchCallback(p)
}
}
}
// Ping check service health.
func (s *Service) Ping(ctx context.Context) error {
return s.dao.Ping(ctx)
}
// Close kafka consumer close.
func (s *Service) Close() {
s.closed = true
s.databus.Close()
s.waiter.Wait()
}