Skip to content

Query cache keys ignore all filter → public/admin cache collision (festivals + editions) #55

Description

@chiptus

Bug (systemic pattern)

Several feature query-key factories produce a constant key while the underlying Supabase fetch varies by an all flag (which toggles a published = true filter). So the published-only and include-unpublished variants share one React Query cache entry — whichever runs last populates the cache for both → admin data (incl. unpublished) can bleed into public lists, or vice versa.

Instance 1 — festivals

  • fetchFestivals({ all }) filters published = true only when !all, but festivalsKeys.all() is the constant ["festivals"].
  • Call sites: src/pages/FestivalSelection.tsxuseFestivalsQuery() (published only); src/pages/admin/festivals/FestivalManagementTable.tsxuseFestivalsQuery({ all: true }).

Instance 2 — editions (found by Qodo on #57)

  • fetchFestivalEditions(festivalId, { all }) filters published = true only when !all, but editionsKeys.all(festivalId) is the constant ["festivals", festivalId, "editions"].
  • Call sites: src/pages/EditionSelection.tsxuseFestivalEditionsForFestivalQuery(festivalId) (published only); src/pages/admin/festivals/FestivalEditionManagement.tsx…({ all: true }).

Pre-existing

Neither instance was introduced by the restructure PRs (#54 festivals, #57 editions) — both exist identically on main. Those PRs are deliberately kept mechanical (no behavior change), so the behavioral fix is split out here.

Suggested fix (same shape for both)

Encode the filter into the key; keep mutation invalidation broad so all variants refresh:

  • festivals: festivalsKeys.list({ all }) => ["festivals", { all: !!all }]
  • editions: editionsKeys.list(festivalId, { all }) => ["festivals", festivalId, "editions", { all: !!all }]
  • point each queryOptions factory at the new key; mutations keep invalidating the broad prefix (["festivals"] / ["festivals", festivalId, "editions"]).

Audit TODO

As each remaining feature moves to src/api, check for the same shape (constant key + all/filter-dependent fetch) and fix it the same way — start with sets (setsByEditionQuery / setsQuery, #58).

Context

Found by Qodo review on #54 (festivals) and #57 (editions). Part of restructure #52 / epic #51.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions