feat(recommend): 추천 스냅샷 저장소를 추가한다
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
package kr.co.vividnext.sodalive.v2.recommend.adapter.out.persistence
|
||||
|
||||
import kr.co.vividnext.sodalive.common.BaseEntity
|
||||
import kr.co.vividnext.sodalive.v2.recommend.domain.RecommendedSectionType
|
||||
import java.time.LocalDateTime
|
||||
import javax.persistence.Column
|
||||
import javax.persistence.Entity
|
||||
import javax.persistence.EnumType
|
||||
import javax.persistence.Enumerated
|
||||
import javax.persistence.Table
|
||||
|
||||
@Entity
|
||||
@Table(name = "recommendation_snapshot")
|
||||
class RecommendationSnapshot(
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "section_type", nullable = false, updatable = false, length = 50)
|
||||
val sectionType: RecommendedSectionType,
|
||||
|
||||
@Column(name = "target_id", nullable = false, updatable = false)
|
||||
val targetId: Long,
|
||||
|
||||
@Column(name = "score", nullable = false, updatable = false)
|
||||
val score: Double,
|
||||
|
||||
@Column(name = "snapshot_at", nullable = false, updatable = false)
|
||||
val snapshotAt: LocalDateTime,
|
||||
|
||||
@Column(name = "random_tie_breaker", nullable = false, updatable = false)
|
||||
val randomTieBreaker: Double
|
||||
) : BaseEntity()
|
||||
@@ -0,0 +1,47 @@
|
||||
package kr.co.vividnext.sodalive.v2.recommend.adapter.out.persistence
|
||||
|
||||
import kr.co.vividnext.sodalive.v2.recommend.domain.RecommendedSectionType
|
||||
import kr.co.vividnext.sodalive.v2.recommend.port.out.RecommendationSnapshotPort
|
||||
import kr.co.vividnext.sodalive.v2.recommend.port.out.RecommendationSnapshotRecord
|
||||
import org.springframework.stereotype.Repository
|
||||
import java.time.LocalDateTime
|
||||
|
||||
@Repository
|
||||
class RecommendationSnapshotPersistenceAdapter(
|
||||
private val repository: RecommendationSnapshotRepository
|
||||
) : RecommendationSnapshotPort {
|
||||
override fun findLatestSnapshots(sectionType: RecommendedSectionType): List<RecommendationSnapshotRecord> {
|
||||
val snapshotAt = repository.findTopBySectionTypeOrderBySnapshotAtDesc(sectionType)?.snapshotAt ?: return emptyList()
|
||||
return repository.findAllBySectionTypeAndSnapshotAtOrderByScoreDescRandomTieBreakerAsc(sectionType, snapshotAt)
|
||||
.map { it.toRecord() }
|
||||
}
|
||||
|
||||
override fun replaceSnapshots(
|
||||
sectionType: RecommendedSectionType,
|
||||
snapshotAt: LocalDateTime,
|
||||
newSnapshots: List<RecommendationSnapshotRecord>
|
||||
) {
|
||||
repository.deleteBySectionTypeAndSnapshotAt(sectionType, snapshotAt)
|
||||
repository.saveAll(newSnapshots.map { it.toEntity() })
|
||||
}
|
||||
|
||||
private fun RecommendationSnapshot.toRecord(): RecommendationSnapshotRecord {
|
||||
return RecommendationSnapshotRecord(
|
||||
sectionType = sectionType,
|
||||
targetId = targetId,
|
||||
score = score,
|
||||
snapshotAt = snapshotAt,
|
||||
randomTieBreaker = randomTieBreaker
|
||||
)
|
||||
}
|
||||
|
||||
private fun RecommendationSnapshotRecord.toEntity(): RecommendationSnapshot {
|
||||
return RecommendationSnapshot(
|
||||
sectionType = sectionType,
|
||||
targetId = targetId,
|
||||
score = score,
|
||||
snapshotAt = snapshotAt,
|
||||
randomTieBreaker = randomTieBreaker
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package kr.co.vividnext.sodalive.v2.recommend.adapter.out.persistence
|
||||
|
||||
import kr.co.vividnext.sodalive.v2.recommend.domain.RecommendedSectionType
|
||||
import org.springframework.data.jpa.repository.JpaRepository
|
||||
import java.time.LocalDateTime
|
||||
|
||||
interface RecommendationSnapshotRepository : JpaRepository<RecommendationSnapshot, Long> {
|
||||
fun findTopBySectionTypeOrderBySnapshotAtDesc(sectionType: RecommendedSectionType): RecommendationSnapshot?
|
||||
|
||||
fun findAllBySectionTypeAndSnapshotAtOrderByScoreDescRandomTieBreakerAsc(
|
||||
sectionType: RecommendedSectionType,
|
||||
snapshotAt: LocalDateTime
|
||||
): List<RecommendationSnapshot>
|
||||
|
||||
fun deleteBySectionTypeAndSnapshotAt(sectionType: RecommendedSectionType, snapshotAt: LocalDateTime)
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package kr.co.vividnext.sodalive.v2.recommend.port.out
|
||||
|
||||
import kr.co.vividnext.sodalive.v2.recommend.domain.RecommendedSectionType
|
||||
import java.time.LocalDateTime
|
||||
|
||||
interface RecommendationSnapshotPort {
|
||||
fun findLatestSnapshots(sectionType: RecommendedSectionType): List<RecommendationSnapshotRecord>
|
||||
|
||||
fun replaceSnapshots(
|
||||
sectionType: RecommendedSectionType,
|
||||
snapshotAt: LocalDateTime,
|
||||
newSnapshots: List<RecommendationSnapshotRecord>
|
||||
)
|
||||
}
|
||||
|
||||
data class RecommendationSnapshotRecord(
|
||||
val sectionType: RecommendedSectionType,
|
||||
val targetId: Long,
|
||||
val score: Double,
|
||||
val snapshotAt: LocalDateTime,
|
||||
val randomTieBreaker: Double
|
||||
)
|
||||
Reference in New Issue
Block a user