From 017ba309f041e5e009eddb49435fb3f6cc9692ea Mon Sep 17 00:00:00 2001 From: Klaus Date: Tue, 9 Jun 2026 12:31:46 +0900 Subject: [PATCH] =?UTF-8?q?feat(ranking):=20=EC=8A=A4=EB=83=85=EC=83=B7=20?= =?UTF-8?q?=EC=99=84=EC=A0=84=20=EA=B3=B5=EB=B0=B1=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=EB=A5=BC=20=EC=B6=94=EA=B0=80=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DefaultCreatorRankingSnapshotRepository.kt | 4 ++++ .../port/out/CreatorRankingSnapshotPort.kt | 2 ++ ...efaultCreatorRankingSnapshotRepositoryTest.kt | 16 ++++++++++++++++ .../CreatorRankingSnapshotRefreshServiceTest.kt | 2 ++ 4 files changed, 24 insertions(+) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/v2/ranking/adapter/out/persistence/DefaultCreatorRankingSnapshotRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/v2/ranking/adapter/out/persistence/DefaultCreatorRankingSnapshotRepository.kt index 5acccb76..1c2ec6ed 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/v2/ranking/adapter/out/persistence/DefaultCreatorRankingSnapshotRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/v2/ranking/adapter/out/persistence/DefaultCreatorRankingSnapshotRepository.kt @@ -28,6 +28,10 @@ class DefaultCreatorRankingSnapshotRepository( return repository.findPreviousCompletedSnapshots().map { it.toRecord() } } + override fun isSnapshotTableEmpty(): Boolean { + return repository.count() == 0L + } + @Transactional override fun replaceSnapshots( aggregationStartAtUtc: LocalDateTime, diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/v2/ranking/port/out/CreatorRankingSnapshotPort.kt b/src/main/kotlin/kr/co/vividnext/sodalive/v2/ranking/port/out/CreatorRankingSnapshotPort.kt index dc57ad9b..dd49e25c 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/v2/ranking/port/out/CreatorRankingSnapshotPort.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/v2/ranking/port/out/CreatorRankingSnapshotPort.kt @@ -12,6 +12,8 @@ interface CreatorRankingSnapshotPort { fun findPreviousCompletedSnapshots(): List + fun isSnapshotTableEmpty(): Boolean + fun replaceSnapshots( aggregationStartAtUtc: LocalDateTime, aggregationEndAtUtc: LocalDateTime, diff --git a/src/test/kotlin/kr/co/vividnext/sodalive/v2/ranking/adapter/out/persistence/DefaultCreatorRankingSnapshotRepositoryTest.kt b/src/test/kotlin/kr/co/vividnext/sodalive/v2/ranking/adapter/out/persistence/DefaultCreatorRankingSnapshotRepositoryTest.kt index 55d7df75..062db614 100644 --- a/src/test/kotlin/kr/co/vividnext/sodalive/v2/ranking/adapter/out/persistence/DefaultCreatorRankingSnapshotRepositoryTest.kt +++ b/src/test/kotlin/kr/co/vividnext/sodalive/v2/ranking/adapter/out/persistence/DefaultCreatorRankingSnapshotRepositoryTest.kt @@ -147,6 +147,22 @@ class DefaultCreatorRankingSnapshotRepositoryTest @Autowired constructor( assertEquals(emptyList(), snapshots) } + @Test + @DisplayName("스냅샷 row가 하나도 없을 때만 테이블 완전 공백으로 판단한다") + fun shouldReturnTrueOnlyWhenSnapshotTableHasNoRows() { + assertEquals(true, adapter.isSnapshotTableEmpty()) + + repository.save( + snapshot( + creatorId = 1L, + aggregationStartAtUtc = LocalDateTime.of(2026, 5, 24, 15, 0), + aggregationEndAtUtc = LocalDateTime.of(2026, 5, 31, 15, 0) + ) + ) + + assertEquals(false, adapter.isSnapshotTableEmpty()) + } + @Test @DisplayName("20위 점수 경계 동점 후보는 저장소에서 누락 없이 저장하고 조회할 수 있다") fun shouldPersistAllCandidatesTiedAtTwentiethScoreBoundary() { diff --git a/src/test/kotlin/kr/co/vividnext/sodalive/v2/ranking/application/CreatorRankingSnapshotRefreshServiceTest.kt b/src/test/kotlin/kr/co/vividnext/sodalive/v2/ranking/application/CreatorRankingSnapshotRefreshServiceTest.kt index a6de4469..f43fa67e 100644 --- a/src/test/kotlin/kr/co/vividnext/sodalive/v2/ranking/application/CreatorRankingSnapshotRefreshServiceTest.kt +++ b/src/test/kotlin/kr/co/vividnext/sodalive/v2/ranking/application/CreatorRankingSnapshotRefreshServiceTest.kt @@ -256,6 +256,8 @@ private class FakeCreatorRankingSnapshotPort : CreatorRankingSnapshotPort { override fun findPreviousCompletedSnapshots(): List = snapshots + override fun isSnapshotTableEmpty(): Boolean = snapshots.isEmpty() + override fun replaceSnapshots( aggregationStartAtUtc: LocalDateTime, aggregationEndAtUtc: LocalDateTime,