75 lines
2.3 KiB
Go

package broadcast
import (
"context"
"log/slog"
"time"
"hyapp/pkg/appcode"
"hyapp/pkg/logx"
broadcastdomain "hyapp/services/activity-service/internal/domain/broadcast"
)
type RedPacketWalletOutboxReader interface {
ListRedPacketCreatedEventsAfter(ctx context.Context, cursor broadcastdomain.RedPacketWalletCursor, batchSize int) ([]broadcastdomain.RedPacketCreatedEvent, error)
}
type RedPacketBroadcastWorkerOptions struct {
WorkerID string
PollInterval time.Duration
BatchSize int
}
// RunRedPacketBroadcastWorker 把 wallet-service 已提交的红包创建事实转成区域飘屏 outbox。
func (s *Service) RunRedPacketBroadcastWorker(ctx context.Context, reader RedPacketWalletOutboxReader, options RedPacketBroadcastWorkerOptions) {
if s == nil || reader == nil {
logx.Warn(ctx, "worker_disabled", slog.String("worker", "red_packet_broadcast"), slog.String("reason", "missing_dependency"))
return
}
if options.PollInterval <= 0 {
options.PollInterval = 5 * time.Second
}
if options.BatchSize <= 0 {
options.BatchSize = 100
}
var cursor broadcastdomain.RedPacketWalletCursor
for {
processed, err := s.processRedPacketBroadcastBatch(ctx, reader, &cursor, options.BatchSize)
if err != nil {
logx.Error(ctx, "worker_batch_failed", err, slog.String("worker", "red_packet_broadcast"), slog.String("worker_id", options.WorkerID))
}
if ctx.Err() != nil {
return
}
if processed >= options.BatchSize {
continue
}
select {
case <-ctx.Done():
return
case <-time.After(options.PollInterval):
}
}
}
func (s *Service) processRedPacketBroadcastBatch(ctx context.Context, reader RedPacketWalletOutboxReader, cursor *broadcastdomain.RedPacketWalletCursor, batchSize int) (int, error) {
events, err := reader.ListRedPacketCreatedEventsAfter(ctx, *cursor, batchSize)
if err != nil {
return 0, err
}
for _, event := range events {
eventCtx := appcode.WithContext(ctx, event.AppCode)
if _, err := s.PublishRegionBroadcast(eventCtx, PublishInput{
EventID: event.EventID,
BroadcastType: broadcastdomain.TypeRedPacket,
RegionID: event.RegionID,
PayloadJSON: event.PayloadJSON,
}); err != nil {
return 0, err
}
cursor.CreatedAtMS = event.CreatedAtMS
cursor.EventID = event.EventID
}
return len(events), nil
}