Skip to content

Commit

Permalink
Fix IndexOutOfBounds after getRefreshKey
Browse files Browse the repository at this point in the history
It's possible that on a paging source that's not in the initial
generation, we fail with an `IndexOutOfBoundsException`. This
is caused when the underlying data source undergoes a delete, which
then invalidates the paging source, which then calls
`getRefreshKey`. In the event that the the refresh key is the
very last index of the previous paging source, we would fail
with the above exception because that index does not exist
in the next generation paging source.

Closes cashapp#2434.
  • Loading branch information
kevincianfarini committed Dec 13, 2021
1 parent e7a3d77 commit cd6167c
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 2 deletions.
Expand Up @@ -34,9 +34,13 @@ internal class OffsetQueryPagingSource<RowType : Any>(
params: LoadParams<Long>
): LoadResult<Long, RowType> = withContext(dispatcher) {
try {
val key = params.key ?: 0L
transacter.transactionWithResult {
val count = countQuery.executeAsOne()
val key = when (params) {
is LoadParams.Refresh -> params.key?.let { notNullKey -> minOf(count - 1, notNullKey) }
else -> params.key
} ?: 0L

if (count != 0L && key >= count) throw IndexOutOfBoundsException()

val loadSize = if (key < 0) params.loadSize + key else params.loadSize
Expand Down
Expand Up @@ -234,11 +234,25 @@ class OffsetQueryPagingSourceTest {

runBlocking {
assertFailsWith<IndexOutOfBoundsException> {
source.load(Refresh(10, 2, false))
source.load(PagingSource.LoadParams.Append(10, 2, false))
}
}
}

@Test fun `refresh key too big gets truncated`() {
val source = OffsetQueryPagingSource(
this::query,
countQuery(),
transacter,
TestCoroutineDispatcher()
)

runBlocking {
val results = source.load(Refresh(10, 2, false))
assertEquals(listOf(9L), (results as LoadResult.Page).data)
}
}

@Test fun `query invalidation invalidates paging source`() {
val query = query(2, 0)
val source = OffsetQueryPagingSource(
Expand Down

0 comments on commit cd6167c

Please sign in to comment.