Skip to content

chore: simplify pagination iterator state and query-param parsing#193

Merged
OmarAlJarrah merged 1 commit into
mainfrom
chore/pagination-iterator-state-cleanup
Jun 28, 2026
Merged

chore: simplify pagination iterator state and query-param parsing#193
OmarAlJarrah merged 1 commit into
mainfrom
chore/pagination-iterator-state-cleanup

Conversation

@OmarAlJarrah

Copy link
Copy Markdown
Member

Three small, behavior-preserving cleanups in the pagination package, grouped because they sit in the same subsystem. No public signatures move and the existing pagination tests stay green.

Paginator — drop the started flag

The PaginatorIterator carried a started boolean solely to pick initialRequest on the first fetch. Seeding nextRequest with initialRequest lets the first fetch read nextRequest exactly like every later page, so advance()'s two-stage request selection collapses into a single guard. The nextRequest ?: finishedPage.nextPageRequest() fallback was dead: by the time advance() re-runs, nextRequest already holds that page's nextPageRequest() (or null, which the page's own hasNext check short-circuits).

The page-budget increment (pagesFetched++) and the nextRequest reassignment both remain after the fetch/parse. That ordering is load-bearing: the sync iterator supports retry — if execute() throws, a caller can catch it and call hasNext() again, re-entering advance() to re-attempt the same request. Mutating either field before the fetch would burn the page budget or advance the cursor on a failed exchange.

RequestRebuilder.getQueryParam — use substringBefore/substringAfter

Replaced the hand-rolled indexOf('=') plus two conditional substring calls with substringBefore('=', segment) / substringAfter('=', ""), matching the idiom its sibling setQueryParam already uses for key extraction. The default-argument forms split on the first = and fall back to the supplied default when absent, so the no-=, empty-value, and =-in-value cases are identical.

LinkHeaderPaginationStrategy — drop the dead Link-header guards

The two empty-string guards around the header join were unreachable: an empty values(...) list joins to "", and extractNextUrl("") already returns null (an empty header splits to no link-values). The intermediate vals and branches fold into one extractNextUrl(...) call; the explicit separator = "," is kept so the join uses a bare comma.

Build

No public-API change — every edit is internal (PaginatorIterator is private, RequestRebuilder is an internal object, and parse(...) keeps its overriding signature), so apiCheck needs no apiDump. :sdk-core ktlint and the full org.dexpace.sdk.core.pagination.* test suite pass locally.

Closes #177.

Three behavior-preserving cleanups in the pagination package:

- Paginator: seed the iterator's nextRequest with initialRequest so the
  first fetch reads it like every later page, removing the started flag and
  the dead `nextRequest ?: nextPageRequest()` fallback. The page-budget and
  cursor mutations stay after the fetch, so the catch-and-retry-hasNext path
  still re-attempts the same request on a failed exchange.

- RequestRebuilder.getQueryParam: parse each segment with substringBefore/
  substringAfter on the first '=', matching setQueryParam's existing idiom
  and dropping the manual indexOf/substring bookkeeping. Edge cases (no '=',
  empty value, '=' in value) are identical.

- LinkHeaderPaginationStrategy: drop the empty-string guards around the Link
  header join. An empty values list joins to "" and extractNextUrl("")
  already returns null, so the guards were dead.

No public-API change; existing pagination tests stay green.
@OmarAlJarrah OmarAlJarrah merged commit 1970d8e into main Jun 28, 2026
1 check passed
@OmarAlJarrah OmarAlJarrah deleted the chore/pagination-iterator-state-cleanup branch June 28, 2026 01:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

pagination: redundant Paginator iterator state, query-param parsing, and dead Link-header guards

1 participant