diff --git a/internal/bossraid/service.go b/internal/bossraid/service.go index 5dbe579..bc696d3 100644 --- a/internal/bossraid/service.go +++ b/internal/bossraid/service.go @@ -221,28 +221,27 @@ func (s *Service) CompleteRaid(sessionName string, rewards []PlayerReward) (*Bos hasRewardFailure := false if s.rewardGrant != nil { for _, r := range rewards { - lastTxID, grantErr := s.grantWithRetry(r.Username, r.TokenAmount, r.Assets) + // 1회만 시도 — 실패 시 즉시 RewardFailure에 저장하여 백그라운드 워커가 재시도 + txID, grantErr := s.rewardGrant(r.Username, r.TokenAmount, r.Assets) result := RewardResult{Username: r.Username, Success: grantErr == nil} if grantErr != nil { result.Error = grantErr.Error() - log.Printf("보상 지급 실패 (재시도 소진): %s: %v", r.Username, grantErr) + log.Printf("보상 지급 실패: %s: %v (백그라운드 재시도 예정)", r.Username, grantErr) hasRewardFailure = true - // 실패한 보상을 DB에 기록하여 백그라운드 재시도 가능하게 함 - s.saveRewardFailure(sessionName, r, grantErr, lastTxID) + s.saveRewardFailure(sessionName, r, grantErr, txID) } resultRewards = append(resultRewards, result) } } - // Grant experience to players (with retry) + // Grant experience to players (1회 시도, 실패 시 백그라운드 재시도) if s.expGrant != nil { for _, r := range rewards { if r.Experience > 0 { - expErr := s.grantExpWithRetry(r.Username, r.Experience) + expErr := s.expGrant(r.Username, r.Experience) if expErr != nil { - log.Printf("경험치 지급 실패 (재시도 소진): %s: %v", r.Username, expErr) + log.Printf("경험치 지급 실패: %s: %v (백그라운드 재시도 예정)", r.Username, expErr) hasRewardFailure = true - // 경험치 실패도 RewardFailure에 기록 (토큰/에셋 없이 경험치만) s.saveRewardFailure(sessionName, PlayerReward{ Username: r.Username, Experience: r.Experience, @@ -541,49 +540,7 @@ func (s *Service) GetServerStatus(serverName string) (*DedicatedServer, []RoomSl return server, slots, nil } -// --- Reward retry helpers --- - -const immediateRetries = 3 - -// grantWithRetry attempts the reward grant up to 3 times with backoff (1s, 2s). -// Returns the last attempted transaction ID (may be empty) and the error. -func (s *Service) grantWithRetry(username string, tokenAmount uint64, assets []core.MintAssetPayload) (string, error) { - delays := []time.Duration{1 * time.Second, 2 * time.Second} - var lastErr error - var lastTxID string - for attempt := 0; attempt < immediateRetries; attempt++ { - txID, err := s.rewardGrant(username, tokenAmount, assets) - if txID != "" { - lastTxID = txID - } - if err == nil { - return txID, nil - } - lastErr = err - if attempt < len(delays) { - log.Printf("보상 지급 재시도 (%d/%d): %s: %v", attempt+1, immediateRetries, username, lastErr) - time.Sleep(delays[attempt]) - } - } - return lastTxID, lastErr -} - -// grantExpWithRetry attempts the experience grant up to 3 times with backoff (1s, 2s). -func (s *Service) grantExpWithRetry(username string, exp int) error { - delays := []time.Duration{1 * time.Second, 2 * time.Second} - var lastErr error - for attempt := 0; attempt < immediateRetries; attempt++ { - lastErr = s.expGrant(username, exp) - if lastErr == nil { - return nil - } - if attempt < len(delays) { - log.Printf("경험치 지급 재시도 (%d/%d): %s: %v", attempt+1, immediateRetries, username, lastErr) - time.Sleep(delays[attempt]) - } - } - return lastErr -} +// --- Reward helpers --- // saveRewardFailure records a failed reward in the DB for background retry. func (s *Service) saveRewardFailure(sessionName string, r PlayerReward, grantErr error, lastTxID string) {