2026-05-13 16:07:25 +08:00

93 lines
2.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package walletnotice
import (
"context"
"log/slog"
"strings"
"time"
"hyapp/pkg/logx"
)
// WalletNoticeWorkerOptions 是钱包余额私有通知 worker 的运行参数。
type WalletNoticeWorkerOptions struct {
WorkerID string
PollInterval time.Duration
BatchSize int
LockTTL time.Duration
PublishTimeout time.Duration
MaxRetryCount int
InitialBackoff time.Duration
MaxBackoff time.Duration
}
// RunWalletBalanceWorker 持续消费 wallet_outbox 的 WalletBalanceChanged 事件。
func (s *Service) RunWalletBalanceWorker(ctx context.Context, options WalletNoticeWorkerOptions) {
options = normalizeWalletNoticeWorkerOptions(options, s.cfg.NodeID)
ticker := time.NewTicker(options.PollInterval)
defer ticker.Stop()
for {
processed, err := s.ProcessWalletBalanceNotices(ctx, options)
if err != nil && ctx.Err() == nil {
logx.Error(ctx, "notice_wallet_balance_batch_failed", err, slog.String("worker_id", options.WorkerID))
}
if processed >= options.BatchSize {
// 批次打满说明有积压,立即继续 drain避免固定 tick 放大私有余额通知延迟。
continue
}
select {
case <-ctx.Done():
return
case <-ticker.C:
}
}
}
func normalizeWalletNoticeWorkerOptions(options WalletNoticeWorkerOptions, nodeID string) WalletNoticeWorkerOptions {
if strings.TrimSpace(options.WorkerID) == "" {
if strings.TrimSpace(nodeID) == "" {
nodeID = "notice"
}
options.WorkerID = "wallet-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 walletNoticeBackoff(retryCount int, options WalletNoticeWorkerOptions) 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
}