test #433

Merged
klaus merged 41 commits from test into main 2026-07-10 07:20:07 +00:00
4 changed files with 68 additions and 0 deletions
Showing only changes of commit ca26577279 - Show all commits

View File

@@ -18,11 +18,21 @@ class RecommendationSnapshotPersistenceAdapter(
return repository.findLatestSnapshots(sectionType.name, offset, limit).map { it.toRecord() }
}
override fun existsLatestSnapshot(sectionType: RecommendedSectionType): Boolean {
return repository.existsBySectionType(sectionType)
}
override fun replaceSnapshots(
sectionType: RecommendedSectionType,
snapshotAt: LocalDateTime,
newSnapshots: List<RecommendationSnapshotRecord>
) {
if (newSnapshots.isEmpty() && sectionType == RecommendedSectionType.AI_CHARACTER) {
repository.deleteBySectionType(sectionType)
repository.save(emptySnapshotMarker(sectionType, snapshotAt).toEntity())
return
}
repository.deleteBySectionTypeAndSnapshotAt(sectionType, snapshotAt)
repository.saveAll(newSnapshots.map { it.toEntity() })
}
@@ -46,4 +56,21 @@ class RecommendationSnapshotPersistenceAdapter(
randomTieBreaker = randomTieBreaker
)
}
private fun emptySnapshotMarker(
sectionType: RecommendedSectionType,
snapshotAt: LocalDateTime
): RecommendationSnapshotRecord {
return RecommendationSnapshotRecord(
sectionType = sectionType,
targetId = EMPTY_SNAPSHOT_MARKER_TARGET_ID,
score = 0.0,
snapshotAt = snapshotAt,
randomTieBreaker = 0.0
)
}
companion object {
private const val EMPTY_SNAPSHOT_MARKER_TARGET_ID = 0L
}
}

View File

@@ -17,6 +17,7 @@ interface RecommendationSnapshotRepository : JpaRepository<RecommendationSnapsho
from recommendation_snapshot latest
where latest.section_type = :sectionType
)
and rs.target_id <> 0
order by rs.score desc, rs.random_tie_breaker asc
limit :limit offset :offset
""",
@@ -29,4 +30,8 @@ interface RecommendationSnapshotRepository : JpaRepository<RecommendationSnapsho
): List<RecommendationSnapshot>
fun deleteBySectionTypeAndSnapshotAt(sectionType: RecommendedSectionType, snapshotAt: LocalDateTime)
fun deleteBySectionType(sectionType: RecommendedSectionType)
fun existsBySectionType(sectionType: RecommendedSectionType): Boolean
}

View File

@@ -10,6 +10,8 @@ interface RecommendationSnapshotPort {
limit: Int = Int.MAX_VALUE
): List<RecommendationSnapshotRecord>
fun existsLatestSnapshot(sectionType: RecommendedSectionType): Boolean
fun replaceSnapshots(
sectionType: RecommendedSectionType,
snapshotAt: LocalDateTime,

View File

@@ -108,6 +108,40 @@ class RecommendationSnapshotPersistenceAdapterTest @Autowired constructor(
assertEquals(3, repository.findAll().size)
}
@Test
fun shouldClearAiCharacterSectionSnapshotsWhenReplacingWithEmptySnapshots() {
val oldSnapshotAt = LocalDateTime.of(2026, 5, 28, 23, 59, 59)
val snapshotAt = LocalDateTime.of(2026, 5, 29, 23, 59, 59)
repository.saveAll(
listOf(
snapshot(RecommendedSectionType.AI_CHARACTER, targetId = 1L, score = 100.0, snapshotAt = oldSnapshotAt),
snapshot(RecommendedSectionType.CHEER_CREATOR, targetId = 2L, score = 200.0, snapshotAt = oldSnapshotAt)
)
)
adapter.replaceSnapshots(RecommendedSectionType.AI_CHARACTER, snapshotAt, emptyList())
assertEquals(emptyList<RecommendationSnapshotRecord>(), adapter.findLatestSnapshots(RecommendedSectionType.AI_CHARACTER))
assertEquals(listOf(2L), adapter.findLatestSnapshots(RecommendedSectionType.CHEER_CREATOR).map { it.targetId })
assertEquals(true, adapter.existsLatestSnapshot(RecommendedSectionType.AI_CHARACTER))
assertEquals(
listOf(0L),
repository.findAll()
.filter { it.sectionType == RecommendedSectionType.AI_CHARACTER }
.map { it.targetId }
)
}
@Test
fun shouldExcludeEmptySnapshotMarkerFromLatestSnapshotResults() {
val snapshotAt = LocalDateTime.of(2026, 5, 29, 23, 59, 59)
adapter.replaceSnapshots(RecommendedSectionType.AI_CHARACTER, snapshotAt, emptyList())
assertEquals(emptyList<RecommendationSnapshotRecord>(), adapter.findLatestSnapshots(RecommendedSectionType.AI_CHARACTER))
assertEquals(true, adapter.existsLatestSnapshot(RecommendedSectionType.AI_CHARACTER))
}
private fun snapshot(
sectionType: RecommendedSectionType,
targetId: Long,