93 lines
2.3 KiB
Go
93 lines
2.3 KiB
Go
package roomnotice
|
||
|
||
import (
|
||
"context"
|
||
"log/slog"
|
||
"strings"
|
||
"time"
|
||
|
||
"hyapp/pkg/logx"
|
||
)
|
||
|
||
// RoomNoticeWorkerOptions 控制房间私有通知 worker 的运行参数。
|
||
type RoomNoticeWorkerOptions struct {
|
||
WorkerID string
|
||
PollInterval time.Duration
|
||
BatchSize int
|
||
LockTTL time.Duration
|
||
PublishTimeout time.Duration
|
||
MaxRetryCount int
|
||
InitialBackoff time.Duration
|
||
MaxBackoff time.Duration
|
||
}
|
||
|
||
// RunRoomKickWorker 持续消费 room_outbox 中的 RoomUserKicked 事件。
|
||
func (s *Service) RunRoomKickWorker(ctx context.Context, options RoomNoticeWorkerOptions) {
|
||
options = normalizeRoomNoticeWorkerOptions(options, s.cfg.NodeID)
|
||
ticker := time.NewTicker(options.PollInterval)
|
||
defer ticker.Stop()
|
||
for {
|
||
processed, err := s.ProcessRoomKickNotices(ctx, options)
|
||
if err != nil && ctx.Err() == nil {
|
||
logx.Error(ctx, "notice_room_kick_batch_failed", err, slog.String("worker_id", options.WorkerID))
|
||
}
|
||
if processed >= options.BatchSize {
|
||
// 批次打满说明有积压,立即继续 drain,降低被踢用户退出提示延迟。
|
||
continue
|
||
}
|
||
select {
|
||
case <-ctx.Done():
|
||
return
|
||
case <-ticker.C:
|
||
}
|
||
}
|
||
}
|
||
|
||
func normalizeRoomNoticeWorkerOptions(options RoomNoticeWorkerOptions, nodeID string) RoomNoticeWorkerOptions {
|
||
if strings.TrimSpace(options.WorkerID) == "" {
|
||
if strings.TrimSpace(nodeID) == "" {
|
||
nodeID = "notice"
|
||
}
|
||
options.WorkerID = "room-notice-" + nodeID
|
||
}
|
||
if options.PollInterval <= 0 {
|
||
options.PollInterval = time.Second
|
||
}
|
||
if options.BatchSize <= 0 {
|
||
options.BatchSize = 100
|
||
}
|
||
if options.LockTTL <= 0 {
|
||
options.LockTTL = 30 * time.Second
|
||
}
|
||
if options.PublishTimeout <= 0 {
|
||
options.PublishTimeout = 3 * time.Second
|
||
}
|
||
if options.MaxRetryCount <= 0 {
|
||
options.MaxRetryCount = 10
|
||
}
|
||
if options.InitialBackoff <= 0 {
|
||
options.InitialBackoff = 5 * time.Second
|
||
}
|
||
if options.MaxBackoff <= 0 {
|
||
options.MaxBackoff = 5 * time.Minute
|
||
}
|
||
return options
|
||
}
|
||
|
||
func roomNoticeBackoff(retryCount int, options RoomNoticeWorkerOptions) time.Duration {
|
||
if retryCount <= 0 {
|
||
return options.InitialBackoff
|
||
}
|
||
backoff := options.InitialBackoff
|
||
for i := 1; i < retryCount; i++ {
|
||
if backoff >= options.MaxBackoff/2 {
|
||
return options.MaxBackoff
|
||
}
|
||
backoff *= 2
|
||
}
|
||
if backoff > options.MaxBackoff {
|
||
return options.MaxBackoff
|
||
}
|
||
return backoff
|
||
}
|