package broadcast import ( "context" "log/slog" "time" "hyapp/pkg/logx" ) // RunWorker 先按需补齐播报群,再持续拉取持久化 outbox 投递腾讯 IM。 // 该 worker 只在 broadcast.enabled 且 tencent_im.enabled 时启动,本地默认关闭,防止开发环境误发真实 IM。 func (s *Service) RunWorker(ctx context.Context, options WorkerOptions) { options = normalizeWorkerOptions(options, s.cfg) if s.cfg.EnsureGroupsOnStartup { // 建群失败不退出进程:下一轮部署/定时任务可继续补偿,已经入队的消息仍保留在 MySQL。 if _, err := s.EnsureBroadcastGroups(ctx); err != nil && ctx.Err() == nil { logx.Error(ctx, "broadcast_group_reconcile_failed", err, slog.String("worker_id", options.WorkerID)) } } ticker := time.NewTicker(options.PollInterval) defer ticker.Stop() for { if _, err := s.ProcessPendingBroadcasts(ctx, options); err != nil && ctx.Err() == nil { // 批处理失败只影响当前轮询,outbox 记录没有被删除,下一轮会按锁和重试状态重新处理。 logx.Error(ctx, "broadcast_outbox_batch_failed", err, slog.String("worker_id", options.WorkerID)) } select { case <-ctx.Done(): return case <-ticker.C: } } }