fix: 좀비 슬롯 정리 및 보상 실패 상태 추적
- RequestEntry() 시 CheckStaleSlots() 호출하여 좀비 슬롯 자동 정리 - 블록체인 보상 실패 시 BossRoom 상태를 reward_failed로 업데이트 - UpdateRoomStatus() 레포지토리 메서드 추가 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -12,7 +12,8 @@ const (
|
||||
StatusWaiting RoomStatus = "waiting"
|
||||
StatusInProgress RoomStatus = "in_progress"
|
||||
StatusCompleted RoomStatus = "completed"
|
||||
StatusFailed RoomStatus = "failed"
|
||||
StatusFailed RoomStatus = "failed"
|
||||
StatusRewardFailed RoomStatus = "reward_failed"
|
||||
)
|
||||
|
||||
// BossRoom represents a boss raid session room.
|
||||
|
||||
@@ -219,6 +219,17 @@ func (r *Repository) ResetStaleSlots(threshold time.Time) (int64, error) {
|
||||
return result.RowsAffected, result.Error
|
||||
}
|
||||
|
||||
// UpdateRoomStatus updates only the status of a boss room by session name.
|
||||
func (r *Repository) UpdateRoomStatus(sessionName string, status RoomStatus) error {
|
||||
result := r.db.Model(&BossRoom{}).
|
||||
Where("session_name = ?", sessionName).
|
||||
Update("status", status)
|
||||
if result.RowsAffected == 0 {
|
||||
return fmt.Errorf("방을 찾을 수 없습니다: %s", sessionName)
|
||||
}
|
||||
return result.Error
|
||||
}
|
||||
|
||||
// GetRoomSlotsByServer returns all room slots for a given server.
|
||||
func (r *Repository) GetRoomSlotsByServer(serverID uint) ([]RoomSlot, error) {
|
||||
var slots []RoomSlot
|
||||
|
||||
@@ -55,6 +55,9 @@ func (s *Service) SetExpGranter(fn func(username string, exp int) error) {
|
||||
// Allocates an idle room slot from a registered dedicated server.
|
||||
// Returns the room with assigned session name.
|
||||
func (s *Service) RequestEntry(usernames []string, bossID int) (*BossRoom, error) {
|
||||
// 좀비 슬롯 정리 — idle 슬롯 검색 전에 stale 인스턴스를 리셋
|
||||
s.CheckStaleSlots()
|
||||
|
||||
if len(usernames) == 0 {
|
||||
return nil, fmt.Errorf("플레이어 목록이 비어있습니다")
|
||||
}
|
||||
@@ -222,6 +225,7 @@ func (s *Service) CompleteRaid(sessionName string, rewards []PlayerReward) (*Bos
|
||||
|
||||
// Grant rewards outside the transaction to avoid holding the lock during RPC calls
|
||||
resultRewards = make([]RewardResult, 0, len(rewards))
|
||||
hasRewardFailure := false
|
||||
if s.rewardGrant != nil {
|
||||
for _, r := range rewards {
|
||||
grantErr := s.rewardGrant(r.Username, r.TokenAmount, r.Assets)
|
||||
@@ -229,11 +233,19 @@ func (s *Service) CompleteRaid(sessionName string, rewards []PlayerReward) (*Bos
|
||||
if grantErr != nil {
|
||||
result.Error = grantErr.Error()
|
||||
log.Printf("보상 지급 실패: %s: %v", r.Username, grantErr)
|
||||
hasRewardFailure = true
|
||||
}
|
||||
resultRewards = append(resultRewards, result)
|
||||
}
|
||||
}
|
||||
|
||||
// 보상 실패가 있으면 상태를 reward_failed로 업데이트
|
||||
if hasRewardFailure {
|
||||
if err := s.repo.UpdateRoomStatus(sessionName, StatusRewardFailed); err != nil {
|
||||
log.Printf("보상 실패 상태 업데이트 실패: %s: %v", sessionName, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Grant experience to players
|
||||
if s.expGrant != nil {
|
||||
for _, r := range rewards {
|
||||
|
||||
Reference in New Issue
Block a user