Instant: stop stale background sync when embedded views are disposed (workaround + stress example) - #12
Draft
mutumbakato wants to merge 2 commits into
Draft
Instant: stop stale background sync when embedded views are disposed (workaround + stress example)#12mutumbakato wants to merge 2 commits into
mutumbakato wants to merge 2 commits into
Conversation
Closing a NutrientInstantView on Android does not stop the document's listen-for-server-changes long-poll: the InstantPdfDocument survives in the descriptor cache with its sync coordinator still listening, so every document ever viewed keeps a background /sync connection open. After viewing enough distinct documents these stale long-polls exhaust the per-host connection pool and the next document's auth/download queues behind them, surfacing as 40-60 s document loads (and, behind a reverse proxy with a read timeout, as endless empty-body 502s for previously viewed documents). iOS already stops sync on view teardown. The new "Instant Switch Stress" example demonstrates both the issue and the workaround, using only public APIs and the stock pub.dev packages: - InstantSyncLifecycleAdapter (an AndroidAdapter) prevents the listen-for-changes long-poll from starting at onPdfFragmentReady and stops listening on the cached document at onFragmentDetached. Timing matters: an already-running long-poll holds its pool slot until the server releases it (~47-60 s measured), so stopping at dispose alone is not enough. - syncNow() pulls server changes on demand, replacing the disabled real-time listener (local edits still push automatically). - The example automates document-switch / close-reopen cycles against a Document Engine and reports per-cycle load latency, with a UI toggle to compare baseline vs workaround. Measured on a 12-distinct-document sweep: baseline median 746 ms with 47.6 s stalls; with the adapter enabled median ~250 ms and no stalls. Verified against a licensed Document Engine that adapter registration does not affect licensing. Also removes the example's dependency_overrides that pointed outside the repository (a monorepo sync artifact that broke pub get on clean checkouts); all platform packages now resolve from pub.dev. Repro/verification for https://pspdfkit.zendesk.com/agent/tickets/134164 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…round 11.6.2 fixes the stale Instant sync long-poll upstream (AND-1957): disabling listening for server changes — which includes closing an embedded Instant view — now cancels the in-flight long-poll instead of leaving it holding a connection until the server releases it. That was the root cause behind the 40-60 s document loads in cd66772, so the InstantSyncLifecycleAdapter workaround is no longer needed. Measured with the Instant Switch Stress example against a local Document Engine, 12-cycle switch sweep over distinct never-downloaded documents, profile build, workaround disabled in both runs: 11.5.1 median 1392 ms worst 90014 ms (harness cap) 2 timeouts 11.6.2 median 734 ms worst 1386 ms 0 timeouts Re-verified after removing the adapter: median 732 ms, 0 timeouts. Not a document-specific artifact — fresh-doc-23 hit the 90 s cap on 11.5.1 and loaded in 1386 ms on 11.6.2. The switch-stress example stays in the catalog as a regression harness, with its doc comment rewritten to record where the fix landed. Note: the federated nutrient_flutter_android package hardcodes its own SDK default (1.2.0 -> 11.5.1, 2.0.0 -> 11.6.1), both below the fix. Gradle conflict resolution picks the inline plugin's 11.6.2 here, but that package needs a matching bump in the platform-packages repo. Resolves https://pspdfkit.zendesk.com/agent/tickets/134164 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Closing a
NutrientInstantViewon Android did not stop that document's listen-for-server-changes long-poll. TheInstantPdfDocumentsurvived in the descriptor cache with its sync coordinator still listening, so every document ever viewed kept a background/syncconnection open. After viewing enough distinct documents, these stale long-polls exhausted the per-host connection pool and the next document's auth/download queued behind them:Reported in ZD#134164.
The fix
Nutrient Android SDK 11.6.2 (released 6 Aug 2026, AND-1957):
This is the proper fix — real-time listening stays enabled, and no adapter or periodic sync timer is needed.
What this PR contains
android/config.gradlefrom11.5.1to11.6.2.InstantSyncLifecycleAdapterworkaround that the first commit introduced, along with its UI toggle andsyncNow()helper.example/pubspec.yaml— removesdependency_overridespointing outside the repository (a monorepo sync artifact that brokepub geton clean checkouts).Verification
12 distinct, never-before-downloaded documents opened in sequence; profile build on a clean API 36 emulator against a local Document Engine; no workaround active in either run.
Re-verified after deleting the adapter: median 732 ms, worst 2115 ms (first-cycle cold start), 0 timeouts.
Not a document-specific artifact —
fresh-doc-23hit the 90 s cap on 11.5.1 and loaded in 1386 ms on 11.6.2.For reference, the workaround measured in the first commit reached ~250 ms median with no stalls on 11.5.1; it is no longer required.
Note on the federated platform packages
nutrient_flutter_androidhardcodes its own SDK default inandroid/build.gradle— 1.2.0 pins 11.5.1 and 2.0.0 pins 11.6.1, both below the fix. It is included as a Gradle subproject, sodependencyInsightshows11.5.1 -> 11.6.2resolved by conflict resolution and this build is correct. A matching bump is still needed in the platform-packages repo, otherwise an app resolving the federated package without the inline plugin lands below the fix.Try it
The example defaults to a local Document Engine on
:5001with documentsfresh-doc-01..30andclean-doc-auploaded (see the header ofinstant_switch_stress_example.dartfor setup).Apps that cannot take a plugin update yet can pick up the SDK fix directly by adding
pspdfkit.version=11.6.2to their app'sandroid/local.properties.