28. 일괄 지급의 all-or-nothing 트랜잭션 (한 건 중복이 전체를 롤백)

난이도 하 해설 보기 →

결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커 (A)(B) 는 주목 위치 힌트다.

결함 코드 · C#
// 시나리오: 이벤트 보상 일괄 지급 — C# 서버
// - 운영 이벤트로 여러 플레이어에게 같은 보상 아이템을 우편으로 일괄 지급한다.
// - 우편 테이블에는 (player_id, item_id, event_id) UNIQUE 제약이 있어, 같은 이벤트
//   보상을 같은 플레이어에게 두 번 넣으면 UniqueViolationException 이 발생한다.
//   (지급 잡이 재시도되거나, 명단에 이미 받은 유저가 섞여 있을 수 있다.)
//
// 요구사항:
//   1) 명단의 각 플레이어는 서로 독립적으로 보상을 받아야 한다.
//   2) 일부 플레이어가 "이미 받음(중복)"이어도, 나머지 정상 플레이어의 지급은
//      완료되어야 한다.
//
// 과제: 명단에 이미 받은 유저가 한 명이라도 섞여 있으면, 정상 유저들도 보상을
//       받지 못하는 일이 발생한다. (A),(B) 지점을 근거로 원인과 수정안을 설명하라.

using System;

public sealed class UniqueViolationException : Exception { }

public interface IDb
{
    void Begin();
    void Commit();
    void Rollback();
    void Insert(int playerId, int itemId, int eventId);   // 중복이면 UniqueViolationException
}

public sealed class RewardGranter
{
    private readonly IDb _db;
    public RewardGranter(IDb db) { _db = db; }

    public void GrantToAll(int[] playerIds, int itemId, int eventId)
    {
        _db.Begin();
        foreach (var pid in playerIds)
        {
            _db.Insert(pid, itemId, eventId);   // (A)
        }
        _db.Commit();                            // (B)
    }
}
내 리뷰 · C#
내 답안 · 자동 저장

작성 후 위 해설 보기에서 모범 해설과 대조하세요.