Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ package com.flipcash.shared.chat.reactions
* reaction state, so refreshing it again would be redundant.
*
* Both are pure: callers own the "already refreshed" bookkeeping and pass in what's still needed.
*
* Both drop ids below 1. A pending or failed send is stored as `-(now)`, has no reactions to fetch,
* and fails the `MessageId` rule (>= 1) for the whole batch it rides in. Its real id arrives with
* the server echo and pages in as a new id.
*/
object ReactionRefreshPlanner {

Expand All @@ -30,6 +34,7 @@ object ReactionRefreshPlanner {
): List<Long> =
newestFirstIds
.asSequence()
.filter { it >= 1 }
.take(windowSize)
.filterNot { it in alreadyRefreshed }
.toList()
Expand All @@ -47,7 +52,7 @@ object ReactionRefreshPlanner {
chunkSize: Int = DEFAULT_CHUNK_SIZE,
): List<List<Long>> {
if (sourcedFromServer) return emptyList()
val remaining = pageIds.filterNot { it in alreadyRefreshed }
val remaining = pageIds.filter { it >= 1 && it !in alreadyRefreshed }
if (remaining.isEmpty()) return emptyList()
return remaining.chunked(chunkSize)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,20 @@ class ReactionRefreshPlannerTest {
val chunks = ReactionRefreshPlanner.forLoadedPage(emptyList(), sourcedFromServer = false)
assertEquals(emptyList<List<Long>>(), chunks)
}

// A pending or failed send is stored as -(now) and sorts among the newest rows. The
// MessageId rule is >= 1, so one in a batch fails the whole request.

@Test
fun `initial window skips unsent ids and still fills the window`() {
val unsent = -1_700_000_000_000L
val window = ReactionRefreshPlanner.initialWindow(listOf(unsent, 5L, 4L, 3L), windowSize = 2)
assertEquals(listOf(5L, 4L), window)
}

@Test
fun `loaded page of only an unsent id yields no chunks`() {
val chunks = ReactionRefreshPlanner.forLoadedPage(listOf(-1_700_000_000_000L), sourcedFromServer = false)
assertEquals(emptyList<List<Long>>(), chunks)
}
}
Loading