let two windows onto the same dashboards agree again
The dashboard-state cache had staleTime: Infinity and there is no invalidateQueries anywhere in the
repo, so it was fetched once per page load and never again: two windows diverged permanently and neither
was ever told. It now refetches on focus — with three non-default guards, because this cache is
optimistic and a refetch that started before an in-flight PATCH landed would overwrite the value we
already showed. Never on mount (splitting a panel mounts a fresh consumer, which is exactly when a write
is in flight), never on reconnect, and on focus only after a short quiet period with nothing in flight.
The PATCH stopped assembling a full state blob it then returned to nobody — three SELECTs per splitter
release, thrown away, and a caller that did read it would be reading state assembled before whatever
concurrent write it raced.
And the last three `.catch(() => {})` in this family are gone: dashboard create, rename and delete build
their own multi-key patches and so bypass the hook. They now go through persistDashboardState, which
keeps the in-flight bookkeeping honest and, on failure, invalidates rather than reverts — there is no
single previous value to swap back once the roster has been rewritten, and a refetch is the only thing
that makes the list agree with the server. A failed delete used to leave the dashboard gone from the list
and alive on the server, reappearing at the next reload with no hint why.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -121,6 +121,8 @@ dashboardsRouter.patch('/', async (ctx) => {
|
||||
return ctx.json({ error: `unknown dashboard-state key "${key}"` }, 400);
|
||||
}
|
||||
|
||||
const state = await getAllDashboardState(userId);
|
||||
return ctx.json(state);
|
||||
// Three SELECTs per splitter release, thrown away — no caller has ever read this response body, and one
|
||||
// that did would be reading a blob assembled *before* the concurrent write it raced. The client
|
||||
// converges by refetching on focus instead (`useDashboardState`).
|
||||
return ctx.json({ ok: true });
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user