Skip to content

Auds/lazy loading: Added support for the lazy loading for the range-served / linearized PDFs, fixed caching bug on 2.2.24 - #692

Open
Satendra9984 wants to merge 6 commits into
espresso3389:masterfrom
Satendra9984:auds/lazy-loading
Open

Auds/lazy loading: Added support for the lazy loading for the range-served / linearized PDFs, fixed caching bug on 2.2.24#692
Satendra9984 wants to merge 6 commits into
espresso3389:masterfrom
Satendra9984:auds/lazy-loading

Conversation

@Satendra9984

Copy link
Copy Markdown

Summary

Large remote PDFs with preferRangeAccess: true still blocked first paint until
every page was measured. Measurement walks each page dictionary; on linearized
files those dictionaries are spread across the file, so the viewer faulted the
whole file (1 MB blocks, serialized) before painting page 1.

This PR adds an opt-in path (loadPageDimensionsOnDemand, default false)
that measures only pages entering the existing render-cache extent, plus related
correctness fixes that show up once range access continues for the document lifetime.

Based on tag pdfrx-v2.2.24 (not rebased onto current master). Happy to rebase
if preferred.

Changes

  • Opt-in lazy measurement (PdfViewerBehaviorControlParams.loadPageDimensionsOnDemand):
    skip exhaustive loadPagesProgressively; measure visible pages via reloadPages;
    fire onDocumentLoadFinished when the progressive pass is skipped.
  • Concurrent visible-page measurement with a 3-attempt failure budget (no permanent blacklist for transient errors).
  • reloadPages subset fix: apply worker results by pageIndex (was using list position).
  • Sparse HTTP cache / blank pages: do not treat a 304 cache file as a complete PDF unless fully resident; mark only blocks that actually arrived as resident.
  • Debug: Pdfrx.debugLazyLoading / fetch byte counters; tests with real PDFium over a fake Range-aware HTTP client + fixture.

Trade-offs when the flag is on

  • Unvisited page sizes stay estimates until scrolled into view.
  • Whole-document text search / loadText only covers measured pages.
  • Default path unchanged when the flag is off.

Motivation / deeper write-up: handwritten-notes demand paging in a Flutter app
serving large chapter PDFs over HTTP range requests.

Test plan

  • Default (loadPageDimensionsOnDemand: false) behavior unchanged.
  • Large linearized URI + preferRangeAccess: true + flag on → early first paint; progressive MEASURE logs.
  • Reopen after partial download / 304 → no permanent blank pages.
  • PDFIUM_PATH=... flutter test packages/pdfrx/test/lazy_loading_test.dart

Satendra9984 and others added 6 commits August 8, 2026 12:43
reloadPages reads the page list after its await and writes it back
synchronously, so concurrent calls cannot interleave and the queue that
serialised them was unnecessary. It was also harmful: one measurement that
faulted a block and waited on the network held up every other visible page
behind it, so a single slow page blanked the whole screen instead of itself.

The duplicate-request behaviour that motivated the queue had a different
cause -- _onDocumentChanged clears the in-flight set on every reset, and the
progress-notification reset storm was still running at the time.

Also replace the permanent measurement blacklist with a three-attempt budget,
and only count a failure when the viewer and document are still the ones that
asked. A throw during teardown says nothing about whether a page is readable,
and blacklisting on it left that page blank for the rest of the session.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Drives the real engine through a range-aware MockClient so the demand-paging
path is exercised rather than a stand-in, with knobs for latency, servers that
ignore Range, and forced failures.

Not yet passing: HTTP fires but the document never materialises. Two known
harness issues are documented in the file -- the load error is swallowed, and
PdfDocumentRef._listenables is a static registry that leaks a loaded document
between tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A sequential run of measurements looks identical whether the viewport is
moving through the document or something is walking it, so the trace could
not distinguish the two. Record the first and last page in the render cache
extent at the moment the request is made.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.

1 participant