feat(recommend): 추천 스냅샷 성공 로그를 커밋 후 기록한다
This commit is contained in:
@@ -4,8 +4,11 @@ import kr.co.vividnext.sodalive.v2.recommend.domain.RecommendedSectionType
|
||||
import kr.co.vividnext.sodalive.v2.recommend.port.out.HomeRecommendationQueryPort
|
||||
import kr.co.vividnext.sodalive.v2.recommend.port.out.RecommendationSnapshotPort
|
||||
import kr.co.vividnext.sodalive.v2.recommend.port.out.RecommendationSnapshotRecord
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.stereotype.Service
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
import org.springframework.transaction.support.TransactionSynchronization
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZoneId
|
||||
|
||||
@@ -14,6 +17,8 @@ class RecommendationSnapshotRefreshService(
|
||||
private val snapshotPort: RecommendationSnapshotPort,
|
||||
private val queryPort: HomeRecommendationQueryPort
|
||||
) {
|
||||
private val log = LoggerFactory.getLogger(javaClass)
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
fun getLatestSnapshots(sectionType: RecommendedSectionType): List<RecommendationSnapshotRecord> {
|
||||
return snapshotPort.findLatestSnapshots(sectionType)
|
||||
@@ -26,6 +31,7 @@ class RecommendationSnapshotRefreshService(
|
||||
|
||||
@Transactional
|
||||
fun refreshDailySnapshots(now: LocalDateTime) {
|
||||
val startedAt = System.currentTimeMillis()
|
||||
val snapshotAt = now
|
||||
.atZone(UTC_ZONE)
|
||||
.withZoneSameInstant(KST_ZONE)
|
||||
@@ -34,24 +40,69 @@ class RecommendationSnapshotRefreshService(
|
||||
.atTime(23, 59, 59)
|
||||
val windowStart = snapshotAt.toLocalDate().minusDays(6).atStartOfDay()
|
||||
|
||||
replaceAiCharacterSnapshots(windowStart, snapshotAt)
|
||||
replaceCheerCreatorSnapshots(windowStart, snapshotAt)
|
||||
replacePopularCommunitySnapshots(windowStart, snapshotAt)
|
||||
runCatching {
|
||||
val aiCharacterCount = replaceAiCharacterSnapshots(windowStart, snapshotAt)
|
||||
val cheerCreatorCount = replaceCheerCreatorSnapshots(windowStart, snapshotAt)
|
||||
val popularCommunityCount = replacePopularCommunitySnapshots(windowStart, snapshotAt)
|
||||
RefreshCounts(aiCharacterCount, cheerCreatorCount, popularCommunityCount)
|
||||
}.onSuccess { counts ->
|
||||
afterCommit {
|
||||
log.info(
|
||||
"event=recommendation_snapshot_refresh_success " +
|
||||
"snapshotAt={} aiCharacterCount={} cheerCreatorCount={} popularCommunityCount={} elapsedMs={}",
|
||||
snapshotAt,
|
||||
counts.aiCharacterCount,
|
||||
counts.cheerCreatorCount,
|
||||
counts.popularCommunityCount,
|
||||
System.currentTimeMillis() - startedAt
|
||||
)
|
||||
}
|
||||
}.onFailure { ex ->
|
||||
log.warn(
|
||||
"event=recommendation_snapshot_refresh_failure snapshotAt={} elapsedMs={} error={}",
|
||||
snapshotAt,
|
||||
System.currentTimeMillis() - startedAt,
|
||||
ex.message,
|
||||
ex
|
||||
)
|
||||
throw ex
|
||||
}
|
||||
}
|
||||
|
||||
private fun replaceAiCharacterSnapshots(windowStart: LocalDateTime, snapshotAt: LocalDateTime) {
|
||||
private fun replaceAiCharacterSnapshots(windowStart: LocalDateTime, snapshotAt: LocalDateTime): Int {
|
||||
val snapshots = queryPort.findAiCharacterSnapshots(windowStart, snapshotAt, AI_CHARACTER_SNAPSHOT_LIMIT)
|
||||
snapshotPort.replaceSnapshots(RecommendedSectionType.AI_CHARACTER, snapshotAt, snapshots)
|
||||
return snapshots.size
|
||||
}
|
||||
|
||||
private fun replaceCheerCreatorSnapshots(windowStart: LocalDateTime, snapshotAt: LocalDateTime) {
|
||||
private fun replaceCheerCreatorSnapshots(windowStart: LocalDateTime, snapshotAt: LocalDateTime): Int {
|
||||
val snapshots = queryPort.findCheerCreatorSnapshots(windowStart, snapshotAt, CHEER_CREATOR_SNAPSHOT_LIMIT)
|
||||
snapshotPort.replaceSnapshots(RecommendedSectionType.CHEER_CREATOR, snapshotAt, snapshots)
|
||||
return snapshots.size
|
||||
}
|
||||
|
||||
private fun replacePopularCommunitySnapshots(windowStart: LocalDateTime, snapshotAt: LocalDateTime) {
|
||||
private fun replacePopularCommunitySnapshots(windowStart: LocalDateTime, snapshotAt: LocalDateTime): Int {
|
||||
val snapshots = queryPort.findPopularCommunitySnapshots(windowStart, snapshotAt, POPULAR_COMMUNITY_SNAPSHOT_LIMIT)
|
||||
snapshotPort.replaceSnapshots(RecommendedSectionType.POPULAR_COMMUNITY, snapshotAt, snapshots)
|
||||
return snapshots.size
|
||||
}
|
||||
|
||||
private data class RefreshCounts(
|
||||
val aiCharacterCount: Int,
|
||||
val cheerCreatorCount: Int,
|
||||
val popularCommunityCount: Int
|
||||
)
|
||||
|
||||
private fun afterCommit(action: () -> Unit) {
|
||||
if (!TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||
action()
|
||||
return
|
||||
}
|
||||
TransactionSynchronizationManager.registerSynchronization(
|
||||
object : TransactionSynchronization {
|
||||
override fun afterCommit() = action()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
Reference in New Issue
Block a user