Problem
Log create/update/delete mutations invalidate cacheKeys.logs.list(...), summary, and detail, but the useLogs hook subscribes to cacheKeys.logs.withQueryParams(...) — a different key under the same "logs" prefix.
surfsense_web/atoms/logs/log-mutation.atoms.ts:21–26
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: cacheKeys.logs.list(searchSpaceId ?? undefined) });
queryClient.invalidateQueries({
queryKey: cacheKeys.logs.summary(searchSpaceId ?? undefined),
});
},
surfsense_web/hooks/use-logs.ts:94–108
const { data: logs, ... } = useQuery({
queryKey: cacheKeys.logs.withQueryParams({
search_space_id: searchSpaceId,
...buildQueryParams(filters ?? {}),
}),
// ...
staleTime: 3 * 60 * 1000,
});
cacheKeys.logs.list produces ["logs", "list", searchSpaceId]. cacheKeys.logs.withQueryParams produces ["logs", "with-query-params", ...]. These are sibling branches — invalidateQueries({ queryKey: ["logs", "list", id] }) does not match ["logs", "with-query-params", ...].
Result: After creating/updating/deleting a log, any UI rendered via useLogs stays stale until the 3-minute staleTime elapses (or the user navigates away and back).
Files
surfsense_web/atoms/logs/log-mutation.atoms.ts (3 mutation atoms: create, update, delete)
surfsense_web/hooks/use-logs.ts (the consumer)
surfsense_web/lib/query-client/cache-keys.ts (where cacheKeys.logs lives)
What to do
Option A (simple, broad invalidation): in each mutation's onSuccess, replace the narrow invalidations with a prefix invalidate that matches everything under "logs":
queryClient.invalidateQueries({ queryKey: ["logs"] });
This covers list, summary, detail, and withQueryParams. It re-fetches a few extra queries on each mutation, but log mutations are rare enough that this is fine.
Option B (precise): add a new helper to cacheKeys.logs and target it explicitly:
// cache-keys.ts
logs: {
// existing keys...
allForSpace: (searchSpaceId?: number | string) => ["logs"] as const, // or scope by space
}
then in mutations:
queryClient.invalidateQueries({ queryKey: cacheKeys.logs.allForSpace(searchSpaceId ?? undefined) });
Either is fine — prefer Option A unless you have a strong reason to scope by space.
Apply the fix to all three mutation atoms (createLogMutationAtom, updateLogMutationAtom, deleteLogMutationAtom).
Why this matters
- Restores the invariant "mutate → relevant queries refetch" that contributors expect.
- Aligns the cache-keys module with consumer reality.
- Removes a class of "why is the UI stale?" support questions.
How to verify
- Open a search space with logs (Settings → Logs).
- Create or delete a log.
- The list should refresh immediately (not after 3 minutes).
Acceptance criteria
Difficulty
Good first issue — single small file, mechanical fix, easy to verify.
Problem
Log create/update/delete mutations invalidate
cacheKeys.logs.list(...),summary, anddetail, but theuseLogshook subscribes tocacheKeys.logs.withQueryParams(...)— a different key under the same"logs"prefix.surfsense_web/atoms/logs/log-mutation.atoms.ts:21–26surfsense_web/hooks/use-logs.ts:94–108cacheKeys.logs.listproduces["logs", "list", searchSpaceId].cacheKeys.logs.withQueryParamsproduces["logs", "with-query-params", ...]. These are sibling branches —invalidateQueries({ queryKey: ["logs", "list", id] })does not match["logs", "with-query-params", ...].Result: After creating/updating/deleting a log, any UI rendered via
useLogsstays stale until the 3-minutestaleTimeelapses (or the user navigates away and back).Files
surfsense_web/atoms/logs/log-mutation.atoms.ts(3 mutation atoms: create, update, delete)surfsense_web/hooks/use-logs.ts(the consumer)surfsense_web/lib/query-client/cache-keys.ts(wherecacheKeys.logslives)What to do
Option A (simple, broad invalidation): in each mutation's
onSuccess, replace the narrow invalidations with a prefix invalidate that matches everything under"logs":This covers
list,summary,detail, andwithQueryParams. It re-fetches a few extra queries on each mutation, but log mutations are rare enough that this is fine.Option B (precise): add a new helper to
cacheKeys.logsand target it explicitly:then in mutations:
Either is fine — prefer Option A unless you have a strong reason to scope by space.
Apply the fix to all three mutation atoms (
createLogMutationAtom,updateLogMutationAtom,deleteLogMutationAtom).Why this matters
How to verify
Acceptance criteria
useLogsuseLogsSummary(which usescacheKeys.logs.summary)Difficulty
Good first issue — single small file, mechanical fix, easy to verify.