Skip to content

paginate

paginate(provider, query, opts?): Pager

Defined in: src/provider/paging.ts:55

The shared read loop. Offset paging is UNSTABLE when the consumer mutates the mailbox it is paging: archiving shifts the window and the search re-returns already-processed ids. Three defenses, learned the hard way:

  • a seen-set, so nothing is ever yielded twice;
  • stall detection: > stallLimit consecutive pages with nothing new → stop;
  • in ‘drain’ mode the cursor only advances past items deliberately left in place (position = count of skip() calls) — consumed items are assumed removed from the query result by the caller’s own mutation.

‘scan’ mode is for read-only recon over a static result: position advances by items.length per page.

MODE CONTRACT (review finding, load-bearing): ‘drain’ ASSUMES every yielded item is either removed from the query result by the consumer’s mutation or marked skip(). A consumer that does neither — e.g. a DRY-RUN planning pass — re-reads page 1 until stall-out and silently misses every later page. Any non-mutating pass MUST use mode: ‘scan’ (pipelines derive this from their dryRun flag centrally, not per call site).

MailProvider

SearchQuery

PagerOptions = {}

Pager