Skip to content

fix(dashboard): invalidate project caches after environment mutations (#657) - #690

Closed
Rish-it wants to merge 2 commits into
oblien:mainfrom
Rish-it:fix/657-env-cache-invalidation
Closed

fix(dashboard): invalidate project caches after environment mutations (#657)#690
Rish-it wants to merge 2 commits into
oblien:mainfrom
Rish-it:fix/657-env-cache-invalidation

Conversation

@Rish-it

@Rish-it Rish-it commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Closes #657

Problem

Adding a new environment didn't update the UI until a hard refresh, and a deleted environment lingered in every switcher the same way.

Root cause

Two writers into one environments state:

  • ProjectSettingsContext.tsx re-seeds the list from the bundled /info payload whenever projectInfo changes
  • refreshEnvironments() patches it from the dedicated list endpoint

createEnvironment only patched the second, so the module-level infoCache kept the stale bundle — the next projectInfo emit wrote the old list back over the fresh patch. Delete went through handleDeleteProject (which doubles as the environment delete — the server tears down THIS environment and only soft-deletes the app row once its last one is gone) with no invalidation at all, and it navigates home on success, so the dead entry survived in every sibling's cached bundle.

The list ships inside EVERY environment's /info payload, so sibling caches go stale on any mutation — invalidating only the current id would leave the bug one click away.

Fix

Two commits, each self-consistent green:

  1. Create (400b52c2) — createEnvironment calls invalidateProjectCaches(id) before returning, then also invalidates known sibling ids. refreshEnvironments() stays as the immediate correct patch.
  2. Delete (67671ef2) — all three success exits of handleDeleteProject invalidate: full ok, unrecoverable-partial, and the cross-tab 404 in catch, where another tab already deleted the row so this tab's bundles are guaranteed stale. Real failures (409 active-work, deletion-in-progress, teardown-failed) keep caches as-is.

Reuses the existing tool for this exact situation (useProjectEndpoints.ts — "Drop ALL caches for an id AND notify subscribed hooks to refetch"), already used by AdvancedSettings, RoutingUnsyncedCallout and useDeploymentBuild.

No flash risk: same-id refetches are stale-while-revalidate (beginFetchState keeps what's on screen), and eviction of unmounted siblings is pure cache-drop — no request storm.

Test plan

  • New project-settings-environments.test.ts pins the wiring in source (same no-jsdom idiom as advanced-migration-session.test.ts): create-path invalidation + ordering, sibling coverage, helper definition, ≥3 success exits, 404 ordering
  • vitest run: 1058/1058 passed (×2 clean runs)
  • tsc --noEmit: clean (×2)

createEnvironment patched the environments list from the dedicated
endpoint but left infoCache holding the old bundle — the next projectInfo
emit re-ran the seeding effect and wrote the stale list back over the
fresh patch, so the new environment vanished until a reload.

Invalidate the current id plus its known siblings first: the list ships
inside every environment's /info payload, so sibling bundles go stale
too. refreshEnvironments() stays as the immediate correct patch; the
invalidation-triggered /info refetch is stale-while-revalidate, so no
mounted page flashes empty.
…n#657)

handleDeleteProject doubles as the environment delete (the server tears
down THIS environment and only soft-deletes the app row once its last
one is gone) but navigated home on success without invalidating
anything, leaving the dead entry in every sibling's cached switcher.

All three success exits now drop the known ids — the two inside try and
the 404 in catch, where another tab already deleted the row so this
tab's bundles are guaranteed stale. Real failures (409 active-work,
deletion-in-progress, teardown-failed) keep every cache as-is. The
eviction cost for unmounted siblings is pure cache-drop — no request
storm, just a slower first paint on next visit.
Copilot AI lite review requested due to automatic review settings August 22, 2026 13:17

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@Hydralerne

Copy link
Copy Markdown
Member

already fixed sorry

@Hydralerne Hydralerne closed this Aug 23, 2026
@Rish-it

Rish-it commented Aug 24, 2026

Copy link
Copy Markdown
Contributor Author

my bad Thanks !!

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.

Adding new environment not update the ui state and need refresh, and deleting project from environment does not update the state too

3 participants