Skip to content

fix(storage-plugin): restore storages after an app reload - #390

Merged
V3RON merged 1 commit into
mainfrom
fix/storage-plugin-reload-discovery
Aug 12, 2026
Merged

fix(storage-plugin): restore storages after an app reload#390
V3RON merged 1 commit into
mainfrom
fix/storage-plugin-reload-discovery

Conversation

@V3RON

@V3RON V3RON commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Description

Fixes the Storage panel coming back empty after an app reload, stuck on Waiting for storages… until the app is killed and relaunched.

  • The device now sends a device-ready event once its message handlers are registered.
  • The panel re-runs discovery when it receives that event, and resets its query cache so it does not render entries read from the previous JS context.

Related Issue

Closes #389

Context

PluginView destroys and recreates the panel iframe on every execution-context cycle, so the panel restarts with no descriptors on each reload. BackendExecutionContextCreated fires as soon as the new JS context exists — before the app's React tree mounts useRozeniteStoragePlugin — so the recreated panel's single discover-storages request usually arrives while the device has no listener registered, and RozeniteDevToolsClient drops it. Discovery uses client.send rather than client.request, so there is no timeout to surface the loss either, and nothing asks again.

This is a regression from #341, which replaced the device's push-on-mount snapshot with panel-initiated discovery. That earlier flow was ordering-independent, and device-ready restores that property without giving up the pull-based data path: it is a bare signal, so discovery logic stays in one place and no entries are read speculatively.

device-ready is sent after the handler subscriptions are created, so a panel reacting to it is guaranteed to be answered. The panel subscribes before it sends its own first request, so the reverse ordering is covered too — whichever side is late, one of the two paths lands.

The same race exists in @rozenite/tanstack-query-plugin; it is fixed separately in #392.

Testing

  • pnpm --filter @rozenite/storage-plugin test — 194 tests passed, including a new regression guard in panel.test.tsx that asserts the panel runs discovery again on device-ready. Verified it fails against main (expected [...] to have a length of 2 but got 1).
  • pnpm --filter @rozenite/storage-plugin typecheck
  • pnpm --filter @rozenite/storage-plugin lint
  • pnpm format:all

Not verified on a device or emulator — the diagnosis and fix were derived from the panel/runtime lifecycle and reproduced with a message-level harness.

The panel iframe is recreated on every reload and asks for storages before
the app's React tree has mounted the plugin, so its single discover-storages
request is dropped and the panel waits forever.

The device now announces itself once its handlers are registered, and the
panel re-runs discovery and drops its stale query cache in response.
@V3RON
V3RON merged commit bdafd53 into main Aug 12, 2026
4 checks passed
@V3RON
V3RON deleted the fix/storage-plugin-reload-discovery branch August 12, 2026 11:04
V3RON added a commit that referenced this pull request Aug 12, 2026
## Description

Fixes the TanStack Query panel staying empty after an app reload until
the app is killed and relaunched.

- The device now sends a `device-ready` event once its message handlers
are registered.
- The panel pulls the cache again when it receives that event, clearing
what it holds first so it does not render queries from the previous JS
context.

## Related Issue

Closes #391

## Context

`PluginView` destroys and recreates the panel iframe on every
execution-context cycle, so the panel restarts empty on each reload.
`BackendExecutionContextCreated` fires as soon as the new JS context
exists — before the app's React tree mounts `useTanStackQueryDevTools` —
so the recreated panel's single `request-initial-data` message usually
arrives while `useHandleInitialData` has not registered its handler yet,
and `RozeniteDevToolsClient` drops it. Nothing asks again.

`device-ready` is sent from `useHandleInitialData`, which runs last in
`useTanStackQueryDevTools`, so a panel reacting to it is guaranteed to
find every handler listening. The panel subscribes before it sends its
own first request, so the reverse ordering is covered too — whichever
side is late, one of the two paths lands.

The same race affects `@rozenite/storage-plugin`; it is fixed separately
in #390.

## Testing

- `pnpm --filter @rozenite/tanstack-query-plugin test` — 20 tests
passed, including a new regression guard asserting the panel re-requests
and drops its stale cache on `device-ready`. Verified it fails against
`main` (`expected [...] to have a length of 2 but got 1`).
- `pnpm --filter @rozenite/tanstack-query-plugin typecheck`
- `pnpm --filter @rozenite/tanstack-query-plugin lint`
- `pnpm format:all`

Not verified on a device or emulator — the diagnosis and fix were
derived from the panel/runtime lifecycle and reproduced with a
message-level harness.
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.

storage-plugin: panel loses its storages after an app reload

1 participant