Add count methods to JournalStore API and implementations for message counting per conversation (count(conversationId) and count(conversationId, after)), with supporting tests.
release / Publish KMP libraries → caffeine Nexus (release) Failing after 32s
release / Publish KMP libraries → caffeine Nexus (release) Failing after 32s
This commit is contained in:
+8
@@ -59,6 +59,14 @@ class InMemoryJournalStore : MutableJournalStore {
|
||||
records.removeAll { it.conversationId == conversationId }
|
||||
}
|
||||
|
||||
override suspend fun count(conversationId: String): Long = mutex.withLock {
|
||||
records.count { it.conversationId == conversationId }.toLong()
|
||||
}
|
||||
|
||||
override suspend fun count(conversationId: String, after: Instant): Long = mutex.withLock {
|
||||
records.count { it.conversationId == conversationId && it.createdAt > after }.toLong()
|
||||
}
|
||||
|
||||
/** Сколько записей сейчас в кэше. Для тестов/диагностики. */
|
||||
suspend fun size(): Int = mutex.withLock { records.size }
|
||||
|
||||
|
||||
+81
@@ -77,4 +77,85 @@ class InMemoryJournalStoreTest {
|
||||
assertTrue(store.list("c1", Instant.DISTANT_PAST, 0, 100).isEmpty())
|
||||
assertEquals(listOf("m2"), store.list("c2", Instant.DISTANT_PAST, 0, 100).map { it.id })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `count returns total per conversation`() = runTest {
|
||||
val store = InMemoryJournalStore()
|
||||
val t0 = Instant.parse("2026-09-21T10:00:00Z")
|
||||
assertEquals(0L, store.count("c1"))
|
||||
|
||||
store.append(userMsg("m1", "c1", "a", t0))
|
||||
store.append(userMsg("m2", "c1", "b", t0 + 1.seconds))
|
||||
store.append(userMsg("m3", "c2", "c", t0 + 2.seconds))
|
||||
|
||||
assertEquals(2L, store.count("c1"))
|
||||
assertEquals(1L, store.count("c2"))
|
||||
assertEquals(0L, store.count("never-existed"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `count is unaffected by clear of another conversation`() = runTest {
|
||||
val store = InMemoryJournalStore()
|
||||
val t0 = Instant.parse("2026-09-21T10:00:00Z")
|
||||
for (i in 1..20) {
|
||||
store.append(userMsg("m$i", "c1", "x", t0 + i.seconds))
|
||||
}
|
||||
store.append(userMsg("n1", "c2", "y", t0))
|
||||
assertEquals(20L, store.count("c1"))
|
||||
assertEquals(1L, store.count("c2"))
|
||||
|
||||
store.clear("c1")
|
||||
assertEquals(0L, store.count("c1"))
|
||||
assertEquals(1L, store.count("c2"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `count after cursor excludes earlier messages`() = runTest {
|
||||
val store = InMemoryJournalStore()
|
||||
val t0 = Instant.parse("2026-09-21T10:00:00Z")
|
||||
store.append(userMsg("m1", "c1", "a", t0))
|
||||
store.append(userMsg("m2", "c1", "b", t0 + 10.seconds))
|
||||
store.append(userMsg("m3", "c1", "c", t0 + 20.seconds))
|
||||
|
||||
// strictly > t0
|
||||
assertEquals(2L, store.count("c1", t0))
|
||||
// strictly > t0+10s — only the last
|
||||
assertEquals(1L, store.count("c1", t0 + 10.seconds))
|
||||
// after last — empty
|
||||
assertEquals(0L, store.count("c1", t0 + 20.seconds))
|
||||
// distant past — all
|
||||
assertEquals(3L, store.count("c1", Instant.DISTANT_PAST))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `count after cursor scopes to conversation`() = runTest {
|
||||
val store = InMemoryJournalStore()
|
||||
val t = Instant.parse("2026-09-21T10:00:00Z")
|
||||
store.append(userMsg("m1", "c1", "a", t))
|
||||
store.append(userMsg("m2", "c2", "b", t))
|
||||
|
||||
val future = Instant.parse("2099-01-01T00:00:00Z")
|
||||
assertEquals(0L, store.count("c1", future))
|
||||
assertEquals(0L, store.count("c2", future))
|
||||
assertEquals(1L, store.count("c1", Instant.DISTANT_PAST))
|
||||
assertEquals(1L, store.count("c2", Instant.DISTANT_PAST))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `count agrees with list size`() = runTest {
|
||||
val store = InMemoryJournalStore()
|
||||
val t0 = Instant.parse("2026-09-21T10:00:00Z")
|
||||
for (i in 1..15) {
|
||||
store.append(userMsg("m$i", "c1", "x", t0 + i.seconds))
|
||||
}
|
||||
assertEquals(
|
||||
store.list("c1", Instant.DISTANT_PAST, 0, 1000).size.toLong(),
|
||||
store.count("c1"),
|
||||
)
|
||||
val cutoff = t0 + 7.seconds
|
||||
assertEquals(
|
||||
store.list("c1", cutoff, 0, 1000).size.toLong(),
|
||||
store.count("c1", cutoff),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user