fix(content-ranking): 공개 전 랭킹 조회를 차단한다

This commit is contained in:
2026-06-24 23:47:08 +09:00
parent 30b687737e
commit 79be172b93
3 changed files with 109 additions and 8 deletions

View File

@@ -5,6 +5,7 @@ import kr.co.vividnext.sodalive.v2.ranking.domain.CreatorRankingItem
import kr.co.vividnext.sodalive.v2.ranking.domain.CreatorRankingPeriodPolicy
import kr.co.vividnext.sodalive.v2.ranking.domain.CreatorRankingScorePolicy
import kr.co.vividnext.sodalive.v2.ranking.domain.CreatorRankingSnapshotCandidate
import kr.co.vividnext.sodalive.v2.ranking.domain.CreatorRankingType
import kr.co.vividnext.sodalive.v2.ranking.domain.CreatorRankingUtcRange
import kr.co.vividnext.sodalive.v2.ranking.port.out.CreatorRankingAggregationPort
import kr.co.vividnext.sodalive.v2.ranking.port.out.CreatorRankingBlockPort
@@ -14,6 +15,8 @@ import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.ZonedDateTime
@Service
@@ -34,10 +37,12 @@ class CreatorRankingQueryService(
fun getCreatorRankings(viewerMemberId: Long?): CreatorRankingResult {
val startedAt = System.currentTimeMillis()
return runCatching {
val latestItems = snapshotPort.findLatestSnapshots().toRankedItems()
val nowUtc = nowUtc()
val latestSnapshots = snapshotPort.findLatestVisibleSnapshots(CreatorRankingType.WEEKLY, nowUtc)
val latestItems = latestSnapshots.toRankedItems()
if (latestItems.isEmpty()) {
if (snapshotPort.isSnapshotTableEmpty()) {
val fallbackItems = aggregateColdStartFallback().toRankedItems()
val fallbackItems = aggregateColdStartFallback(nowUtc).toRankedItems()
if (fallbackItems.isNotEmpty()) {
delegateColdStartSnapshotRefresh()
}
@@ -56,7 +61,11 @@ class CreatorRankingQueryService(
)
}
val previousItems = snapshotPort.findPreviousCompletedSnapshots().toRankedItems()
val previousItems = snapshotPort.findPreviousVisibleSnapshots(
rankingType = CreatorRankingType.WEEKLY,
currentAggregationStartAtUtc = latestSnapshots.first().aggregationStartAtUtc,
nowUtc = nowUtc
).toRankedItems()
val previousRankByCreatorId = previousItems.associate { it.creatorId to it.rank }
val showRankChange = previousRankByCreatorId.isNotEmpty()
val blockedCreatorIds = findBlockedCreatorIds(viewerMemberId = viewerMemberId, items = latestItems)
@@ -95,10 +104,14 @@ class CreatorRankingQueryService(
val blockedCreatorCount: Int
)
private fun aggregateColdStartFallback(): List<CreatorRankingSnapshotRecord> {
private fun aggregateColdStartFallback(nowUtc: LocalDateTime): List<CreatorRankingSnapshotRecord> {
val startedAt = System.currentTimeMillis()
val period = periodPolicy.resolveLastCompletedWeek(nowProvider())
val utcRange = periodPolicy.toUtcRange(period)
val visibleFromAtUtc = periodPolicy.resolveVisibleFromAtUtc(period.endExclusiveKst)
if (visibleFromAtUtc > nowUtc) {
return emptyList()
}
log.info(
"event=creator_ranking_query_cold_start_fallback_attempt " +
"aggregationStartAtUtc={} aggregationEndAtUtc={}",
@@ -144,6 +157,10 @@ class CreatorRankingQueryService(
}
}
private fun nowUtc(): LocalDateTime {
return nowProvider().withZoneSameInstant(UTC_ZONE).toLocalDateTime()
}
private fun List<CreatorRankingSnapshotRecord>.toRankedItems(): List<CreatorRankingItem> {
return groupBy { it.finalScore }
.toSortedMap(compareByDescending { it })
@@ -190,8 +207,10 @@ class CreatorRankingQueryService(
)
return CreatorRankingSnapshotRecord(
rankingType = CreatorRankingType.WEEKLY,
aggregationStartAtUtc = utcRange.startInclusiveUtc,
aggregationEndAtUtc = utcRange.endExclusiveUtc,
visibleFromAtUtc = utcRange.endExclusiveUtc.plusHours(9),
creatorId = creatorId,
nickname = nickname,
profileImageUrl = profileImageUrl,
@@ -234,6 +253,7 @@ class CreatorRankingQueryService(
}
companion object {
private val UTC_ZONE: ZoneId = ZoneId.of("UTC")
private const val RANKING_LIMIT = 20
private const val MASKED_CREATOR_ID = 0L
private const val MASKED_NICKNAME = ""