From bfbb5e6fd77b5254cece116cdb333991166f9cd3 Mon Sep 17 00:00:00 2001 From: Klaus Date: Wed, 24 Jun 2026 23:45:30 +0900 Subject: [PATCH] =?UTF-8?q?feat(content-ranking):=20=EC=8A=A4=EB=83=85?= =?UTF-8?q?=EC=83=B7=20job=20=EA=B3=B5=EA=B0=9C=20=EB=A9=94=ED=83=80?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=EB=A5=BC=20=EC=A0=80=EC=9E=A5?= =?UTF-8?q?=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../out/persistence/CreatorRankingSnapshotJob.kt | 8 ++++++++ .../DefaultCreatorRankingSnapshotJobRepository.kt | 4 ++++ .../ranking/port/out/CreatorRankingSnapshotJobPort.kt | 3 +++ .../AdminCreatorRankingSnapshotJobControllerTest.kt | 3 +++ .../DefaultCreatorRankingSnapshotJobRepositoryTest.kt | 11 +++++++++++ 5 files changed, 29 insertions(+) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/v2/ranking/adapter/out/persistence/CreatorRankingSnapshotJob.kt b/src/main/kotlin/kr/co/vividnext/sodalive/v2/ranking/adapter/out/persistence/CreatorRankingSnapshotJob.kt index 27c85ed0..8a70f390 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/v2/ranking/adapter/out/persistence/CreatorRankingSnapshotJob.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/v2/ranking/adapter/out/persistence/CreatorRankingSnapshotJob.kt @@ -1,6 +1,7 @@ package kr.co.vividnext.sodalive.v2.ranking.adapter.out.persistence import kr.co.vividnext.sodalive.common.BaseEntity +import kr.co.vividnext.sodalive.v2.ranking.domain.CreatorRankingType import kr.co.vividnext.sodalive.v2.ranking.port.out.CreatorRankingSnapshotJobStatus import kr.co.vividnext.sodalive.v2.ranking.port.out.CreatorRankingSnapshotJobTrigger import java.time.LocalDateTime @@ -13,12 +14,19 @@ import javax.persistence.Table @Entity @Table(name = "creator_ranking_snapshot_job") class CreatorRankingSnapshotJob( + @Enumerated(EnumType.STRING) + @Column(name = "ranking_type", nullable = false, length = 30) + val rankingType: CreatorRankingType, + @Column(name = "aggregation_start_at_utc", nullable = false) val aggregationStartAtUtc: LocalDateTime, @Column(name = "aggregation_end_at_utc", nullable = false) val aggregationEndAtUtc: LocalDateTime, + @Column(name = "visible_from_at", nullable = false) + val visibleFromAtUtc: LocalDateTime, + @Enumerated(EnumType.STRING) @Column(name = "trigger_type", nullable = false, length = 20) val trigger: CreatorRankingSnapshotJobTrigger, diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/v2/ranking/adapter/out/persistence/DefaultCreatorRankingSnapshotJobRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/v2/ranking/adapter/out/persistence/DefaultCreatorRankingSnapshotJobRepository.kt index 19b70ec3..9560a794 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/v2/ranking/adapter/out/persistence/DefaultCreatorRankingSnapshotJobRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/v2/ranking/adapter/out/persistence/DefaultCreatorRankingSnapshotJobRepository.kt @@ -73,8 +73,10 @@ class DefaultCreatorRankingSnapshotJobRepository( private fun CreatorRankingSnapshotJobRecord.toEntity(): CreatorRankingSnapshotJob { return CreatorRankingSnapshotJob( + rankingType = rankingType, aggregationStartAtUtc = aggregationStartAtUtc, aggregationEndAtUtc = aggregationEndAtUtc, + visibleFromAtUtc = visibleFromAtUtc, trigger = trigger, status = status, lastError = lastError, @@ -86,8 +88,10 @@ class DefaultCreatorRankingSnapshotJobRepository( private fun CreatorRankingSnapshotJob.toRecord(): CreatorRankingSnapshotJobRecord { return CreatorRankingSnapshotJobRecord( id = id, + rankingType = rankingType, aggregationStartAtUtc = aggregationStartAtUtc, aggregationEndAtUtc = aggregationEndAtUtc, + visibleFromAtUtc = visibleFromAtUtc, trigger = trigger, status = status, lastError = lastError, diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/v2/ranking/port/out/CreatorRankingSnapshotJobPort.kt b/src/main/kotlin/kr/co/vividnext/sodalive/v2/ranking/port/out/CreatorRankingSnapshotJobPort.kt index 589b3c7d..adb6ef8b 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/v2/ranking/port/out/CreatorRankingSnapshotJobPort.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/v2/ranking/port/out/CreatorRankingSnapshotJobPort.kt @@ -1,5 +1,6 @@ package kr.co.vividnext.sodalive.v2.ranking.port.out +import kr.co.vividnext.sodalive.v2.ranking.domain.CreatorRankingType import java.time.LocalDateTime interface CreatorRankingSnapshotJobPort { @@ -36,8 +37,10 @@ enum class CreatorRankingSnapshotJobTrigger { data class CreatorRankingSnapshotJobRecord( val id: Long? = null, + val rankingType: CreatorRankingType, val aggregationStartAtUtc: LocalDateTime, val aggregationEndAtUtc: LocalDateTime, + val visibleFromAtUtc: LocalDateTime, val trigger: CreatorRankingSnapshotJobTrigger, val status: CreatorRankingSnapshotJobStatus, val lastError: String?, diff --git a/src/test/kotlin/kr/co/vividnext/sodalive/v2/admin/ranking/creator/AdminCreatorRankingSnapshotJobControllerTest.kt b/src/test/kotlin/kr/co/vividnext/sodalive/v2/admin/ranking/creator/AdminCreatorRankingSnapshotJobControllerTest.kt index 10981af4..fa6695b5 100644 --- a/src/test/kotlin/kr/co/vividnext/sodalive/v2/admin/ranking/creator/AdminCreatorRankingSnapshotJobControllerTest.kt +++ b/src/test/kotlin/kr/co/vividnext/sodalive/v2/admin/ranking/creator/AdminCreatorRankingSnapshotJobControllerTest.kt @@ -3,6 +3,7 @@ package kr.co.vividnext.sodalive.v2.admin.ranking.creator import kr.co.vividnext.sodalive.common.CountryContext import kr.co.vividnext.sodalive.i18n.LangContext import kr.co.vividnext.sodalive.i18n.SodaMessageSource +import kr.co.vividnext.sodalive.v2.ranking.domain.CreatorRankingType import kr.co.vividnext.sodalive.v2.ranking.port.out.CreatorRankingSnapshotJobRecord import kr.co.vividnext.sodalive.v2.ranking.port.out.CreatorRankingSnapshotJobStatus import kr.co.vividnext.sodalive.v2.ranking.port.out.CreatorRankingSnapshotJobTrigger @@ -160,8 +161,10 @@ class AdminCreatorRankingSnapshotJobControllerTest @Autowired constructor( private fun manualJob(status: CreatorRankingSnapshotJobStatus): CreatorRankingSnapshotJobRecord { return CreatorRankingSnapshotJobRecord( id = 1L, + rankingType = CreatorRankingType.WEEKLY, aggregationStartAtUtc = LocalDateTime.of(2026, 5, 31, 15, 0), aggregationEndAtUtc = LocalDateTime.of(2026, 6, 7, 15, 0), + visibleFromAtUtc = LocalDateTime.of(2026, 6, 8, 0, 0), trigger = CreatorRankingSnapshotJobTrigger.MANUAL, status = status, lastError = if (status == CreatorRankingSnapshotJobStatus.FAILED) "aggregate failed" else null, diff --git a/src/test/kotlin/kr/co/vividnext/sodalive/v2/ranking/adapter/out/persistence/DefaultCreatorRankingSnapshotJobRepositoryTest.kt b/src/test/kotlin/kr/co/vividnext/sodalive/v2/ranking/adapter/out/persistence/DefaultCreatorRankingSnapshotJobRepositoryTest.kt index d7cbd950..ac382278 100644 --- a/src/test/kotlin/kr/co/vividnext/sodalive/v2/ranking/adapter/out/persistence/DefaultCreatorRankingSnapshotJobRepositoryTest.kt +++ b/src/test/kotlin/kr/co/vividnext/sodalive/v2/ranking/adapter/out/persistence/DefaultCreatorRankingSnapshotJobRepositoryTest.kt @@ -1,6 +1,7 @@ package kr.co.vividnext.sodalive.v2.ranking.adapter.out.persistence import kr.co.vividnext.sodalive.configs.QueryDslConfig +import kr.co.vividnext.sodalive.v2.ranking.domain.CreatorRankingType import kr.co.vividnext.sodalive.v2.ranking.port.out.CreatorRankingSnapshotJobRecord import kr.co.vividnext.sodalive.v2.ranking.port.out.CreatorRankingSnapshotJobStatus import kr.co.vividnext.sodalive.v2.ranking.port.out.CreatorRankingSnapshotJobTrigger @@ -32,8 +33,10 @@ class DefaultCreatorRankingSnapshotJobRepositoryTest @Autowired constructor( val saved = adapter.save( CreatorRankingSnapshotJobRecord( + rankingType = CreatorRankingType.WEEKLY, aggregationStartAtUtc = startAt, aggregationEndAtUtc = endAt, + visibleFromAtUtc = endAt.plusHours(9), trigger = CreatorRankingSnapshotJobTrigger.SCHEDULED, status = CreatorRankingSnapshotJobStatus.PENDING, lastError = null, @@ -54,8 +57,10 @@ class DefaultCreatorRankingSnapshotJobRepositoryTest @Autowired constructor( adapter.markDone(savedId, processedAt) val failed = adapter.save( CreatorRankingSnapshotJobRecord( + rankingType = CreatorRankingType.WEEKLY, aggregationStartAtUtc = startAt.minusWeeks(1), aggregationEndAtUtc = endAt.minusWeeks(1), + visibleFromAtUtc = endAt.minusWeeks(1).plusHours(9), trigger = CreatorRankingSnapshotJobTrigger.SCHEDULED, status = CreatorRankingSnapshotJobStatus.FAILED, lastError = "aggregate failed", @@ -73,6 +78,8 @@ class DefaultCreatorRankingSnapshotJobRepositoryTest @Autowired constructor( assertEquals(1, jobs.size) assertEquals(CreatorRankingSnapshotJobTrigger.SCHEDULED, jobs.single().trigger) + assertEquals(CreatorRankingType.WEEKLY, jobs.single().rankingType) + assertEquals(endAt.plusHours(9), jobs.single().visibleFromAtUtc) assertEquals(CreatorRankingSnapshotJobStatus.DONE, jobs.single().status) assertEquals(processingStartedAt, jobs.single().processingStartedAt) assertEquals(processedAt, jobs.single().processedAt) @@ -86,8 +93,10 @@ class DefaultCreatorRankingSnapshotJobRepositoryTest @Autowired constructor( fun shouldMarkFailedSnapshotJobPendingForRetry() { val saved = adapter.save( CreatorRankingSnapshotJobRecord( + rankingType = CreatorRankingType.WEEKLY, aggregationStartAtUtc = LocalDateTime.of(2026, 5, 31, 15, 0), aggregationEndAtUtc = LocalDateTime.of(2026, 6, 7, 15, 0), + visibleFromAtUtc = LocalDateTime.of(2026, 6, 8, 0, 0), trigger = CreatorRankingSnapshotJobTrigger.MANUAL, status = CreatorRankingSnapshotJobStatus.FAILED, lastError = "aggregate failed", @@ -111,8 +120,10 @@ class DefaultCreatorRankingSnapshotJobRepositoryTest @Autowired constructor( fun shouldNotMarkNonFailedSnapshotJobPendingForRetry() { val saved = adapter.save( CreatorRankingSnapshotJobRecord( + rankingType = CreatorRankingType.WEEKLY, aggregationStartAtUtc = LocalDateTime.of(2026, 5, 31, 15, 0), aggregationEndAtUtc = LocalDateTime.of(2026, 6, 7, 15, 0), + visibleFromAtUtc = LocalDateTime.of(2026, 6, 8, 0, 0), trigger = CreatorRankingSnapshotJobTrigger.MANUAL, status = CreatorRankingSnapshotJobStatus.DONE, lastError = null,