feat(home): 크리에이터 랭킹 fallback job 집계를 추가한다
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
package kr.co.vividnext.sodalive.v2.ranking.adapter.out.persistence
|
package kr.co.vividnext.sodalive.v2.ranking.adapter.out.persistence
|
||||||
|
|
||||||
|
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.CreatorRankingSnapshotJobStatus
|
||||||
|
import kr.co.vividnext.sodalive.v2.ranking.port.out.CreatorRankingSnapshotJobTrigger
|
||||||
import org.springframework.data.jpa.repository.JpaRepository
|
import org.springframework.data.jpa.repository.JpaRepository
|
||||||
import org.springframework.data.jpa.repository.Lock
|
import org.springframework.data.jpa.repository.Lock
|
||||||
import org.springframework.data.jpa.repository.Query
|
import org.springframework.data.jpa.repository.Query
|
||||||
@@ -18,4 +20,11 @@ interface CreatorRankingSnapshotJobRepository : JpaRepository<CreatorRankingSnap
|
|||||||
aggregationEndAtUtc: LocalDateTime,
|
aggregationEndAtUtc: LocalDateTime,
|
||||||
statuses: List<CreatorRankingSnapshotJobStatus>
|
statuses: List<CreatorRankingSnapshotJobStatus>
|
||||||
): List<CreatorRankingSnapshotJob>
|
): List<CreatorRankingSnapshotJob>
|
||||||
|
|
||||||
|
fun countByRankingTypeAndAggregationStartAtUtcAndAggregationEndAtUtcAndTrigger(
|
||||||
|
rankingType: CreatorRankingType,
|
||||||
|
aggregationStartAtUtc: LocalDateTime,
|
||||||
|
aggregationEndAtUtc: LocalDateTime,
|
||||||
|
trigger: CreatorRankingSnapshotJobTrigger
|
||||||
|
): Long
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package kr.co.vividnext.sodalive.v2.ranking.adapter.out.persistence
|
package kr.co.vividnext.sodalive.v2.ranking.adapter.out.persistence
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.v2.ranking.domain.CreatorRankingType
|
||||||
import kr.co.vividnext.sodalive.v2.ranking.port.out.CreatorRankingSnapshotJobPort
|
import kr.co.vividnext.sodalive.v2.ranking.port.out.CreatorRankingSnapshotJobPort
|
||||||
import kr.co.vividnext.sodalive.v2.ranking.port.out.CreatorRankingSnapshotJobRecord
|
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.CreatorRankingSnapshotJobStatus
|
||||||
|
import kr.co.vividnext.sodalive.v2.ranking.port.out.CreatorRankingSnapshotJobTrigger
|
||||||
import org.springframework.stereotype.Repository
|
import org.springframework.stereotype.Repository
|
||||||
import org.springframework.transaction.annotation.Transactional
|
import org.springframework.transaction.annotation.Transactional
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
@@ -32,6 +34,20 @@ class DefaultCreatorRankingSnapshotJobRepository(
|
|||||||
).map { it.toRecord() }
|
).map { it.toRecord() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun countByRankingTypeAndPeriodAndTrigger(
|
||||||
|
rankingType: CreatorRankingType,
|
||||||
|
aggregationStartAtUtc: LocalDateTime,
|
||||||
|
aggregationEndAtUtc: LocalDateTime,
|
||||||
|
trigger: CreatorRankingSnapshotJobTrigger
|
||||||
|
): Long {
|
||||||
|
return repository.countByRankingTypeAndAggregationStartAtUtcAndAggregationEndAtUtcAndTrigger(
|
||||||
|
rankingType = rankingType,
|
||||||
|
aggregationStartAtUtc = aggregationStartAtUtc,
|
||||||
|
aggregationEndAtUtc = aggregationEndAtUtc,
|
||||||
|
trigger = trigger
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
override fun markProcessing(jobId: Long, processingStartedAt: LocalDateTime): CreatorRankingSnapshotJobRecord? {
|
override fun markProcessing(jobId: Long, processingStartedAt: LocalDateTime): CreatorRankingSnapshotJobRecord? {
|
||||||
val job = repository.findByIdForUpdate(jobId) ?: return null
|
val job = repository.findByIdForUpdate(jobId) ?: return null
|
||||||
|
|||||||
@@ -14,6 +14,13 @@ interface CreatorRankingSnapshotJobPort {
|
|||||||
statuses: List<CreatorRankingSnapshotJobStatus>
|
statuses: List<CreatorRankingSnapshotJobStatus>
|
||||||
): List<CreatorRankingSnapshotJobRecord>
|
): List<CreatorRankingSnapshotJobRecord>
|
||||||
|
|
||||||
|
fun countByRankingTypeAndPeriodAndTrigger(
|
||||||
|
rankingType: CreatorRankingType,
|
||||||
|
aggregationStartAtUtc: LocalDateTime,
|
||||||
|
aggregationEndAtUtc: LocalDateTime,
|
||||||
|
trigger: CreatorRankingSnapshotJobTrigger
|
||||||
|
): Long
|
||||||
|
|
||||||
fun markProcessing(jobId: Long, processingStartedAt: LocalDateTime): CreatorRankingSnapshotJobRecord?
|
fun markProcessing(jobId: Long, processingStartedAt: LocalDateTime): CreatorRankingSnapshotJobRecord?
|
||||||
|
|
||||||
fun markDone(jobId: Long, processedAt: LocalDateTime): CreatorRankingSnapshotJobRecord?
|
fun markDone(jobId: Long, processedAt: LocalDateTime): CreatorRankingSnapshotJobRecord?
|
||||||
@@ -32,7 +39,8 @@ enum class CreatorRankingSnapshotJobStatus {
|
|||||||
|
|
||||||
enum class CreatorRankingSnapshotJobTrigger {
|
enum class CreatorRankingSnapshotJobTrigger {
|
||||||
SCHEDULED,
|
SCHEDULED,
|
||||||
MANUAL
|
MANUAL,
|
||||||
|
FALLBACK
|
||||||
}
|
}
|
||||||
|
|
||||||
data class CreatorRankingSnapshotJobRecord(
|
data class CreatorRankingSnapshotJobRecord(
|
||||||
|
|||||||
@@ -138,4 +138,43 @@ class DefaultCreatorRankingSnapshotJobRepositoryTest @Autowired constructor(
|
|||||||
assertEquals(LocalDateTime.of(2026, 6, 8, 7, 30), unchanged?.processingStartedAt)
|
assertEquals(LocalDateTime.of(2026, 6, 8, 7, 30), unchanged?.processingStartedAt)
|
||||||
assertEquals(LocalDateTime.of(2026, 6, 8, 7, 31), unchanged?.processedAt)
|
assertEquals(LocalDateTime.of(2026, 6, 8, 7, 31), unchanged?.processedAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("fallback 제한 count는 같은 기간의 FALLBACK trigger만 계산한다")
|
||||||
|
fun shouldCountFallbackJobsByPeriodAndTriggerOnly() {
|
||||||
|
val startAt = LocalDateTime.of(2026, 5, 31, 15, 0)
|
||||||
|
val endAt = LocalDateTime.of(2026, 6, 7, 15, 0)
|
||||||
|
adapter.save(job(startAt, endAt, CreatorRankingSnapshotJobTrigger.FALLBACK))
|
||||||
|
adapter.save(job(startAt, endAt, CreatorRankingSnapshotJobTrigger.FALLBACK))
|
||||||
|
adapter.save(job(startAt, endAt, CreatorRankingSnapshotJobTrigger.SCHEDULED))
|
||||||
|
adapter.save(job(startAt, endAt, CreatorRankingSnapshotJobTrigger.MANUAL))
|
||||||
|
adapter.save(job(startAt.minusWeeks(1), endAt.minusWeeks(1), CreatorRankingSnapshotJobTrigger.FALLBACK))
|
||||||
|
|
||||||
|
val count = adapter.countByRankingTypeAndPeriodAndTrigger(
|
||||||
|
rankingType = CreatorRankingType.WEEKLY,
|
||||||
|
aggregationStartAtUtc = startAt,
|
||||||
|
aggregationEndAtUtc = endAt,
|
||||||
|
trigger = CreatorRankingSnapshotJobTrigger.FALLBACK
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(2L, count)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun job(
|
||||||
|
startAt: LocalDateTime,
|
||||||
|
endAt: LocalDateTime,
|
||||||
|
trigger: CreatorRankingSnapshotJobTrigger
|
||||||
|
): CreatorRankingSnapshotJobRecord {
|
||||||
|
return CreatorRankingSnapshotJobRecord(
|
||||||
|
rankingType = CreatorRankingType.WEEKLY,
|
||||||
|
aggregationStartAtUtc = startAt,
|
||||||
|
aggregationEndAtUtc = endAt,
|
||||||
|
visibleFromAtUtc = endAt.plusHours(9),
|
||||||
|
trigger = trigger,
|
||||||
|
status = CreatorRankingSnapshotJobStatus.FAILED,
|
||||||
|
lastError = null,
|
||||||
|
processingStartedAt = null,
|
||||||
|
processedAt = null
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user