Skip to content

Fix SSE reconnect stability and add configurable query cache retention#2194

Merged
einari merged 4 commits into
mainfrom
fix/query-caching
May 5, 2026
Merged

Fix SSE reconnect stability and add configurable query cache retention#2194
einari merged 4 commits into
mainfrom
fix/query-caching

Conversation

@einari
Copy link
Copy Markdown
Contributor

@einari einari commented May 5, 2026

Fixed

  • SSE subscribe POST now retries up to 3 times with back-off (200/400/600 ms) before triggering a full reconnect, preventing the cascade of reconnects caused by round-robin load balancers routing the subscribe POST to a different backend instance than the one holding the SSE connection.
  • Observable query components no longer re-render when an SSE reconnect delivers data identical to what was already cached — transient UI state such as row selections is preserved across reconnects.

Added

  • queryCacheRetentionMs prop on <Arc /> and Globals.queryCacheRetentionMs — configures how long the query cache retains an entry after the last subscriber unmounts before evicting the subscription. Defaults to 30 seconds, allowing users to navigate back to a page without a loading flash. Set to 0 to restore immediate eviction.

einari and others added 4 commits May 5, 2026 13:30
In load-balanced deployments (e.g. Azure Container Apps) the SSE GET
and the subscribe POST can land on different backend instances.  The
server-side connection registry is in-process, so the subscribe returns
404 when it hits an instance that does not hold the SSE connection.

Previously a single 404 immediately tore down and re-opened the EventSource,
causing a reconnect cascade that took 2-3 cycles before the load balancer
happened to route both requests to the same instance.

Now sendSubscribe retries up to 3 times with increasing back-off delays
(200 ms, 400 ms, 600 ms) before falling back to a full reconnect.  With
round-robin load balancing across N instances, at most N-1 retries are
needed — covering deployments with up to 4 replicas without ever tearing
down the SSE connection unnecessarily.  A captured connectionId guard
ensures stale retries are silently dropped if a reconnect fires from
another cause in the meantime.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two related improvements to QueryInstanceCache:

1. setLastResult now compares the incoming data (JSON) and isSuccess against
   the previously cached result before broadcasting to listeners.  When an SSE
   reconnect causes the server to re-send an identical dataset the comparison
   short-circuits and React components are never asked to re-render — preserving
   transient UI state such as row selections, open panels, and scroll position.

2. The QueryInstanceCache constructor now accepts a retentionMs value (default
   30 000 ms) instead of the unused development boolean.  After the last
   subscriber unmounts the cache entry and its subscription are kept alive for
   this window before being evicted.  Users navigating back to a page within
   the window see cached data immediately; memory is still reclaimed once the
   timer expires.

Exposed through Globals.queryCacheRetentionMs and the new
<Arc queryCacheRetentionMs={...} /> prop so applications can tune the value
without modifying framework internals.

The now-meaningless *_in_development_mode and *_outside_development_mode spec
files are removed; their coverage is merged into the_only_subscriber.ts.  New
specs verify the before/after retention window behavior.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add documentation for the new queryCacheRetentionMs setting across all
three relevant pages: the Arc component reference, the React queries
configuration guide, and the core Globals configuration reference.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@einari einari added the patch label May 5, 2026
@einari einari merged commit 9b794e3 into main May 5, 2026
7 of 9 checks passed
@einari einari deleted the fix/query-caching branch May 5, 2026 11:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant