diff --git a/src/main/java/com/bcsdlab/bcsdinternalapiv2/game/service/AdminGameBuildService.java b/src/main/java/com/bcsdlab/bcsdinternalapiv2/game/service/AdminGameBuildService.java index c5af3c5..158ac7c 100644 --- a/src/main/java/com/bcsdlab/bcsdinternalapiv2/game/service/AdminGameBuildService.java +++ b/src/main/java/com/bcsdlab/bcsdinternalapiv2/game/service/AdminGameBuildService.java @@ -31,8 +31,10 @@ @Transactional(readOnly = true) public class AdminGameBuildService { + // PROCESSING도 포함한다 — 홈페이지 서버가 죽거나 웹훅 호출 자체가 실패하면 빌드가 + // PROCESSING에서 영영 못 벗어나 재시도가 막히는 사각지대가 생긴다(재업로드는 멱등하다). private static final Set TOKEN_ISSUABLE_STATUSES = Set.of( - GameBuildStatus.PENDING, GameBuildStatus.FAILED); + GameBuildStatus.PENDING, GameBuildStatus.PROCESSING, GameBuildStatus.FAILED); private final GameRepository gameRepository; private final GameBuildRepository gameBuildRepository; diff --git a/src/test/java/com/bcsdlab/bcsdinternalapiv2/game/AdminGameBuildIntegrationTest.java b/src/test/java/com/bcsdlab/bcsdinternalapiv2/game/AdminGameBuildIntegrationTest.java index 5c5f044..92e0d43 100644 --- a/src/test/java/com/bcsdlab/bcsdinternalapiv2/game/AdminGameBuildIntegrationTest.java +++ b/src/test/java/com/bcsdlab/bcsdinternalapiv2/game/AdminGameBuildIntegrationTest.java @@ -145,8 +145,8 @@ void setUp() throws Exception { } @Test - @DisplayName("AC-9.15 PENDING 빌드에 업로드 토큰을 발급하면 status가 PROCESSING이 되고, 다시 발급하면 409다") - void 업로드_토큰_발급은_상태를_PROCESSING으로_바꾸고_재발급은_409() throws Exception { + @DisplayName("AC-9.15 PENDING 빌드에 업로드 토큰을 발급하면 status가 PROCESSING이 되고, PROCESSING에도 재발급할 수 있지만 ACTIVE에는 409다") + void 업로드_토큰_발급은_상태를_PROCESSING으로_바꾸고_ACTIVE_재발급은_409() throws Exception { long buildId = createBuild("1.0.0"); mockMvc.perform(post("/v1/admin/games/" + game.getId() + "/builds/" + buildId + "/upload-token") @@ -159,6 +159,13 @@ void setUp() throws Exception { .header("Authorization", "Bearer " + adminToken)) .andExpect(jsonPath("$[0].status").value("PROCESSING")); + // PROCESSING에서도 재발급 가능 — 홈페이지 서버가 죽거나 웹훅 호출이 실패해도 재시도 경로가 막히지 않는다. + mockMvc.perform(post("/v1/admin/games/" + game.getId() + "/builds/" + buildId + "/upload-token") + .header("Authorization", "Bearer " + adminToken)) + .andExpect(status().isOk()); + + activateBuild(buildId, "https://bcsdlab.com/games/neon-drift/index.html"); + mockMvc.perform(post("/v1/admin/games/" + game.getId() + "/builds/" + buildId + "/upload-token") .header("Authorization", "Bearer " + adminToken)) .andExpect(status().isConflict());