You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
238 lines
5.4 KiB
238 lines
5.4 KiB
package service |
|
|
|
import ( |
|
"context" |
|
"errors" |
|
"fmt" |
|
"math" |
|
"strconv" |
|
"strings" |
|
"sync" |
|
"time" |
|
|
|
"go-common/app/interface/live/push-live/conf" |
|
"go-common/app/interface/live/push-live/dao" |
|
"go-common/library/cache/redis" |
|
"go-common/library/log" |
|
"go-common/library/queue/databus" |
|
) |
|
|
|
var ( |
|
_limitDecreaseUUIDKey = "ld:%s" // 接口请求防重复key |
|
|
|
errLimitRequestRepeat = errors.New("limit decrease request repeat") |
|
errConvertMidString = errors.New("convert mid string error") |
|
errConvertBusiness = errors.New("convert business error") |
|
) |
|
|
|
// Service struct |
|
type Service struct { |
|
c *conf.Config |
|
dao *dao.Dao |
|
liveStartSub *databus.Databus |
|
liveCommonSub *databus.Databus |
|
wg sync.WaitGroup |
|
closeCh chan bool |
|
pushTypes []string |
|
intervalExpired int32 |
|
mutex sync.RWMutex |
|
} |
|
|
|
// New init |
|
func New(c *conf.Config) (s *Service) { |
|
s = &Service{ |
|
c: c, |
|
dao: dao.New(c), |
|
liveStartSub: databus.New(c.LiveRoomSub), |
|
liveCommonSub: databus.New(c.LiveCommonSub), |
|
closeCh: make(chan bool), |
|
pushTypes: make([]string, 0, 4), |
|
mutex: sync.RWMutex{}, |
|
} |
|
s.wg.Add(1) |
|
go s.loadPushConfig() |
|
|
|
for i := 0; i < c.Push.ConsumerProcNum; i++ { |
|
s.wg.Add(1) |
|
go s.liveMessageConsumeproc() |
|
} |
|
|
|
return s |
|
} |
|
|
|
// loadPushConfig Load push config |
|
func (s *Service) loadPushConfig() { |
|
var ctx = context.TODO() |
|
defer s.wg.Done() |
|
for { |
|
select { |
|
case _, ok := <-s.closeCh: |
|
if !ok { |
|
log.Info("[service.push|loadPushConfig] s.loadPushConfig is closed by closeCh") |
|
return |
|
} |
|
default: |
|
} |
|
// get push delay time |
|
interval, err := s.dao.GetPushInterval(ctx) |
|
if err != nil || interval < 0 { |
|
time.Sleep(time.Duration(time.Minute)) |
|
continue |
|
} |
|
s.mutex.Lock() |
|
s.intervalExpired = interval |
|
s.mutex.Unlock() |
|
|
|
// get push options |
|
types, err := s.dao.GetPushConfig(ctx) |
|
if err != nil || len(types) == 0 { |
|
time.Sleep(time.Duration(time.Minute)) |
|
continue |
|
} |
|
s.mutex.Lock() |
|
s.pushTypes = types |
|
s.mutex.Unlock() |
|
|
|
time.Sleep(time.Duration(time.Minute)) |
|
} |
|
} |
|
|
|
// safeGetExpired |
|
func (s *Service) safeGetExpired() int32 { |
|
s.mutex.RLock() |
|
expired := s.intervalExpired |
|
s.mutex.RUnlock() |
|
return expired |
|
} |
|
|
|
// LimitDecrease do mid string limit decrease |
|
func (s *Service) LimitDecrease(ctx context.Context, business, targetID, uuid, midStr string) (err error) { |
|
var ( |
|
f *dao.Filter |
|
mids []int64 |
|
b int |
|
) |
|
|
|
// 判断请求是否重复 |
|
err = s.limitDecreaseUnique(getUniqueKey(business, targetID, uuid)) |
|
if err != nil { |
|
log.Error("[service.service|LimitDecrease] limitDecreaseUnique error(%v), uuid(%s), business(%s), targetID(%s), mid(%s)", |
|
err, uuid, business, targetID, midStr) |
|
return |
|
} |
|
|
|
b, err = strconv.Atoi(business) |
|
if err != nil { |
|
log.Error("[service.service|LimitDecrease] strconv business params error(%v)", err) |
|
err = errConvertBusiness |
|
return |
|
} |
|
filterConf := &dao.FilterConfig{ |
|
Business: b, |
|
DailyExpired: dailyExpired(time.Now())} |
|
|
|
// convert mid string to []int64 |
|
mids, err = s.convertStrToInt64(midStr) |
|
if err != nil { |
|
log.Error("[service.service|LimitDecrease] convertStrToInt64 error(%v), business(%s), uuid(%s), mids(%s)", |
|
err, business, uuid, midStr) |
|
err = errConvertMidString |
|
return |
|
} |
|
|
|
// aysnc decrease limit |
|
f, err = s.dao.NewFilter(filterConf) |
|
if err != nil { |
|
log.Error("[service.service|LimitDecrease] new filter error(%v), business(%s), uuid(%s), mids(%v)", |
|
err, business, uuid, mids) |
|
return |
|
} |
|
go f.BatchDecreaseLimit(ctx, mids) |
|
return |
|
} |
|
|
|
// Ping Service |
|
func (s *Service) Ping(c context.Context) (err error) { |
|
return nil |
|
} |
|
|
|
// Close Service |
|
func (s *Service) Close() { |
|
close(s.closeCh) |
|
s.subClose() |
|
s.wg.Wait() |
|
s.dao.Close() |
|
} |
|
|
|
// subClose Close all sub channels |
|
func (s *Service) subClose() { |
|
s.liveCommonSub.Close() |
|
s.liveStartSub.Close() |
|
} |
|
|
|
// dailyExpired |
|
func dailyExpired(from time.Time) float64 { |
|
tm1 := time.Date(from.Year(), from.Month(), from.Day(), 0, 0, 0, 0, from.Location()) |
|
tm2 := tm1.AddDate(0, 0, 1) |
|
return math.Floor(tm2.Sub(from).Seconds()) |
|
} |
|
|
|
// convertStrToInt64 convert mid string to []int64 slice |
|
func (s *Service) convertStrToInt64(m string) (mInts []int64, err error) { |
|
var ( |
|
mSplit []string |
|
errCount int |
|
) |
|
if m == "" { |
|
return |
|
} |
|
mSplit = strings.Split(m, ",") |
|
for _, mStr := range mSplit { |
|
mInt, convErr := strconv.Atoi(mStr) |
|
if convErr != nil { |
|
log.Error("[service.push|formatMidstr] convert mid(%v), error(%v)", mStr, convErr) |
|
errCount++ |
|
continue |
|
} |
|
mInts = append(mInts, int64(mInt)) |
|
} |
|
if errCount == len(mSplit) { |
|
err = fmt.Errorf("[service.push|formatMidstr] convert all mid failed, midstr(%s)", m) |
|
} |
|
return |
|
} |
|
|
|
// limitDecreaseUnique |
|
func (s *Service) limitDecreaseUnique(key string) (err error) { |
|
var ( |
|
conn redis.Conn |
|
reply interface{} |
|
) |
|
defer func() { |
|
if conn != nil { |
|
conn.Close() |
|
} |
|
}() |
|
conn, err = redis.Dial(s.c.Redis.PushInterval.Proto, s.c.Redis.PushInterval.Addr, s.dao.RedisOption()...) |
|
if err != nil { |
|
log.Error("[service.service|limitDecreaseUnique] redis.Dial error(%v)", err) |
|
return |
|
} |
|
|
|
// redis cache exists judgement |
|
reply, err = conn.Do("SET", key, time.Now(), "EX", dailyExpired(time.Now()), "NX") |
|
if err != nil { |
|
return |
|
} |
|
// key exists |
|
if reply == nil { |
|
err = errLimitRequestRepeat |
|
return |
|
} |
|
return |
|
} |
|
|
|
// getUniqueKey get request unique key |
|
func getUniqueKey(a, b, c string) string { |
|
return fmt.Sprintf(_limitDecreaseUUIDKey, a+b+c) |
|
}
|
|
|