mirror of
https://github.com/christianselig/apollo-backend
synced 2024-11-21 19:37:41 +00:00
update scheduler to split account work
This commit is contained in:
parent
b0f7f6fccb
commit
73e7927d3f
1 changed files with 43 additions and 47 deletions
|
@ -7,7 +7,6 @@ import (
|
||||||
_ "net/http/pprof"
|
_ "net/http/pprof"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/DataDog/datadog-go/statsd"
|
"github.com/DataDog/datadog-go/statsd"
|
||||||
|
@ -24,6 +23,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const batchSize = 250
|
const batchSize = 250
|
||||||
|
const accountEnqueueSeconds = 60
|
||||||
|
|
||||||
func SchedulerCmd(ctx context.Context) *cobra.Command {
|
func SchedulerCmd(ctx context.Context) *cobra.Command {
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
|
@ -102,7 +102,7 @@ func SchedulerCmd(ctx context.Context) *cobra.Command {
|
||||||
s := gocron.NewScheduler(time.UTC)
|
s := gocron.NewScheduler(time.UTC)
|
||||||
s.SetMaxConcurrentJobs(8, gocron.WaitMode)
|
s.SetMaxConcurrentJobs(8, gocron.WaitMode)
|
||||||
|
|
||||||
eaj, _ := s.Every(10).Seconds().Do(func() { enqueueAccounts(ctx, logger, statsd, db, redis, luaSha, notifQueue) })
|
eaj, _ := s.Every(accountEnqueueSeconds).Seconds().Do(func() { enqueueAccounts(ctx, logger, statsd, db, redis, luaSha, notifQueue) })
|
||||||
eaj.SingletonMode()
|
eaj.SingletonMode()
|
||||||
|
|
||||||
_, _ = s.Every(5).Seconds().Do(func() { enqueueSubreddits(ctx, logger, statsd, db, []rmq.Queue{subredditQueue, trendingQueue}) })
|
_, _ = s.Every(5).Seconds().Do(func() { enqueueSubreddits(ctx, logger, statsd, db, []rmq.Queue{subredditQueue, trendingQueue}) })
|
||||||
|
@ -483,6 +483,47 @@ func enqueueAccounts(ctx context.Context, logger *zap.Logger, statsd *statsd.Cli
|
||||||
ids = append(ids, id)
|
ids = append(ids, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chunks := [][]string{}
|
||||||
|
for i := 0; i < accountEnqueueSeconds; i++ {
|
||||||
|
min := (i * len(ids) / accountEnqueueSeconds)
|
||||||
|
max := ((i + 1) * len(ids)) / accountEnqueueSeconds
|
||||||
|
chunks = append(chunks, ids[min:max])
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = statsd.Histogram("apollo.queue.runtime", float64(time.Since(now).Milliseconds()), []string{"queue:notifications"}, 1)
|
||||||
|
|
||||||
|
wg := sync.WaitGroup{}
|
||||||
|
for i := 0; i < accountEnqueueSeconds; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(ctx context.Context, offset int) {
|
||||||
|
ids := chunks[offset]
|
||||||
|
time.Sleep(time.Duration(offset) * time.Second)
|
||||||
|
|
||||||
|
enqueued, err := redisConn.EvalSha(ctx, luaSha, []string{"locks:accounts"}, ids).StringSlice()
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("failed to check for locked accounts", zap.Error(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = queue.Publish(enqueued...); err != nil {
|
||||||
|
logger.Error("failed to enqueue account batch",
|
||||||
|
zap.Error(err),
|
||||||
|
zap.Int("offset", offset),
|
||||||
|
zap.Int("candidates", len(ids)),
|
||||||
|
zap.Int("enqueued", len(enqueued)),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("enqueued account batch",
|
||||||
|
zap.Int("offset", offset),
|
||||||
|
zap.Int("attempts", len(ids)),
|
||||||
|
zap.Int("enqueued", len(enqueued)),
|
||||||
|
)
|
||||||
|
|
||||||
|
}(ctx, i)
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
var (
|
var (
|
||||||
enqueued int64 = 0
|
enqueued int64 = 0
|
||||||
skipped int64 = 0
|
skipped int64 = 0
|
||||||
|
@ -494,49 +535,4 @@ func enqueueAccounts(ctx context.Context, logger *zap.Logger, statsd *statsd.Cli
|
||||||
_ = statsd.Histogram("apollo.queue.skipped", float64(skipped), tags, 1)
|
_ = statsd.Histogram("apollo.queue.skipped", float64(skipped), tags, 1)
|
||||||
_ = statsd.Histogram("apollo.queue.runtime", float64(time.Since(now).Milliseconds()), tags, 1)
|
_ = statsd.Histogram("apollo.queue.runtime", float64(time.Since(now).Milliseconds()), tags, 1)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
logger.Debug("enqueueing account batch", zap.Int("count", len(ids)), zap.Time("start", now))
|
|
||||||
|
|
||||||
// Split ids in batches
|
|
||||||
wg := sync.WaitGroup{}
|
|
||||||
for i := 0; i < len(ids); i += batchSize {
|
|
||||||
wg.Add(1)
|
|
||||||
go func(offset int, ctx context.Context) {
|
|
||||||
defer wg.Done()
|
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
j := offset + batchSize
|
|
||||||
if j > len(ids) {
|
|
||||||
j = len(ids)
|
|
||||||
}
|
|
||||||
batch := ids[offset:j]
|
|
||||||
|
|
||||||
logger.Debug("enqueueing batch", zap.Int("len", len(batch)))
|
|
||||||
|
|
||||||
unlocked, err := redisConn.EvalSha(ctx, luaSha, []string{"locks:accounts"}, batch).StringSlice()
|
|
||||||
if err != nil {
|
|
||||||
logger.Error("failed to check for locked accounts", zap.Error(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
atomic.AddInt64(&skipped, int64(len(batch)-len(unlocked)))
|
|
||||||
atomic.AddInt64(&enqueued, int64(len(unlocked)))
|
|
||||||
|
|
||||||
if len(unlocked) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = queue.Publish(unlocked...); err != nil {
|
|
||||||
logger.Error("failed to enqueue account batch", zap.Error(err))
|
|
||||||
}
|
|
||||||
}(i, ctx)
|
|
||||||
}
|
|
||||||
wg.Wait()
|
|
||||||
|
|
||||||
logger.Info("enqueued account batch",
|
|
||||||
zap.Int64("count", enqueued),
|
|
||||||
zap.Int64("skipped", skipped),
|
|
||||||
zap.Int64("duration", time.Since(now).Milliseconds()),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue