Beta watch: pdf.js first-page rendering adequacy (fallback trigger for #629's B2) #630

Open
opened 2026-09-20 21:20:49 +00:00 by Cordy · 1 comment
Owner

Tracking issue for the #629 decision: A (pdf.js in the client) chosen; B2 (pdfium via wazero, server-side) is the recorded fallback if client-side rendering proves inadequate during the beta. This issue defines what "inadequate" means, as testable cases — run them during the beta (v0.7), and any structural failure (one that tuning cannot fix) activates B2.

Test cases

T1 · Non-linearized giant PDF. A 100–200 MB scanned PDF (not web-optimized). Measure bytes fetched before page 1 renders. Pass: hero renders in <3 s on LAN, or the size cutoff (30 MB constant) correctly suppresses the hero to the icon box. Fail: browser fetches the whole file below the cutoff and stalls the tab.

T2 · Low-power client. Page 1 of a typical 5 MB text PDF on an old phone and on a Pi's own browser. Pass: render <2 s, no visible main-thread jank while the pane's facts stay interactive (pdf.js must run in its worker). Fail: pane interaction blocks during render.

T3 · Rapid selection sweep. Arrow-key through ~50 PDFs in one listing. Pass: in-flight renders are cancelled, memory returns to baseline (canvases released), final selection shows the right page. Fail: runaway canvas memory or heroes arriving on the wrong row (stale-async, the #538-era guard pattern).

T4 · Password-protected / encrypted PDFs. Pass: silent fallback to the icon box — never a password prompt in the hero.

T5 · Malformed and hostile PDFs. A fuzzed/truncated sample set. Pass: pdf.js throws, hero falls back to icon, one debug-level console line at most, app state untouched. This is also the standing security argument for A — parsing stays in the browser sandbox.

T6 · Fonts. PDFs with non-embedded CJK/exotic fonts. Pass: legible substitute rendering via pdf.js standard fonts. Cosmetic differences are acceptable; blank pages are not.

T7 · Office chain latency. First selection of a 20-page pptx and a large xlsx: Gotenberg convert + client render. Pass: hero <4 s on LAN, pane facts render immediately regardless, shimmer state shows meanwhile. Fail: pane waits on the hero.

T8 · Browser parity. Chromium, Firefox, iOS Safari: same hero, same orientation, click-through works. iOS memory limits are the known risk.

T9 · Public path / proxy. Through the real chain (Caddy on the VPS → WireGuard → MetalLB): verify Accept-Ranges survives and pdf.js range requests actually 206 through the proxy. Fail: every preview downloads the full file over WAN.

T10 · Converter concurrency. Three parallel users selecting office files: Gotenberg pod (its own limits) keeps up or degrades to shimmer→icon gracefully; no cairnd memory growth (streaming, not buffering, the converted PDF).

Exit criteria

  • All pass → close this issue at beta end; A is confirmed.
  • Tunable failures (cutoff too high, worker not used, missing cancellation) → fix in place, re-run.
  • Structural failure (client rendering fundamentally unfit for a case that matters) → reopen #629, implement B2: pdfium via go-pdfium+wazero (BSD, cgo-free), server endpoint + content-addressed thumb cache design.
Tracking issue for the #629 decision: **A (pdf.js in the client) chosen; B2 (pdfium via wazero, server-side) is the recorded fallback** if client-side rendering proves inadequate during the beta. This issue defines what "inadequate" means, as testable cases — run them during the beta (v0.7), and any structural failure (one that tuning cannot fix) activates B2. ## Test cases **T1 · Non-linearized giant PDF.** A 100–200 MB scanned PDF (not web-optimized). Measure bytes fetched before page 1 renders. Pass: hero renders in <3 s on LAN, or the size cutoff (30 MB constant) correctly suppresses the hero to the icon box. Fail: browser fetches the whole file below the cutoff and stalls the tab. **T2 · Low-power client.** Page 1 of a typical 5 MB text PDF on an old phone and on a Pi's own browser. Pass: render <2 s, no visible main-thread jank while the pane's facts stay interactive (pdf.js must run in its worker). Fail: pane interaction blocks during render. **T3 · Rapid selection sweep.** Arrow-key through ~50 PDFs in one listing. Pass: in-flight renders are cancelled, memory returns to baseline (canvases released), final selection shows the right page. Fail: runaway canvas memory or heroes arriving on the wrong row (stale-async, the #538-era guard pattern). **T4 · Password-protected / encrypted PDFs.** Pass: silent fallback to the icon box — never a password prompt in the hero. **T5 · Malformed and hostile PDFs.** A fuzzed/truncated sample set. Pass: pdf.js throws, hero falls back to icon, one debug-level console line at most, app state untouched. This is also the standing security argument for A — parsing stays in the browser sandbox. **T6 · Fonts.** PDFs with non-embedded CJK/exotic fonts. Pass: legible substitute rendering via pdf.js standard fonts. Cosmetic differences are acceptable; blank pages are not. **T7 · Office chain latency.** First selection of a 20-page pptx and a large xlsx: Gotenberg convert + client render. Pass: hero <4 s on LAN, pane facts render immediately regardless, shimmer state shows meanwhile. Fail: pane waits on the hero. **T8 · Browser parity.** Chromium, Firefox, iOS Safari: same hero, same orientation, click-through works. iOS memory limits are the known risk. **T9 · Public path / proxy.** Through the real chain (Caddy on the VPS → WireGuard → MetalLB): verify `Accept-Ranges` survives and pdf.js range requests actually 206 through the proxy. Fail: every preview downloads the full file over WAN. **T10 · Converter concurrency.** Three parallel users selecting office files: Gotenberg pod (its own limits) keeps up or degrades to shimmer→icon gracefully; no cairnd memory growth (streaming, not buffering, the converted PDF). ## Exit criteria - All pass → close this issue at beta end; A is confirmed. - Tunable failures (cutoff too high, worker not used, missing cancellation) → fix in place, re-run. - Structural failure (client rendering fundamentally unfit for a case that matters) → reopen #629, implement B2: pdfium via go-pdfium+wazero (BSD, cgo-free), server endpoint + content-addressed thumb cache design.
Author
Owner

T1 · Non-linearized giant PDF. - already with SE-01590-C2-Swisscom-Security-Policy-DE.PDF on files-bao takes extremely long it is only a 351 KB pdf. but 1.1 MB words are super quick, this was done on a macbook pro with an M5 Pro chip.

T1 · Non-linearized giant PDF. - already with SE-01590-C2-Swisscom-Security-Policy-DE.PDF on files-bao takes extremely long it is only a 351 KB pdf. but 1.1 MB words are super quick, this was done on a macbook pro with an M5 Pro chip.
Sign in to join this conversation.
No labels
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Cordy/Cairn#630
No description provided.