Skip to content

Fix log mutations: invalidate the keys useLogs actually subscribes to #1369

@MODSetter

Description

@MODSetter

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

  1. Open a search space with logs (Settings → Logs).
  2. Create or delete a log.
  3. The list should refresh immediately (not after 3 minutes).

Acceptance criteria

  • All three log mutations invalidate the keys consumed by useLogs
  • Manual repro above passes
  • No regression in useLogsSummary (which uses cacheKeys.logs.summary)

Difficulty

Good first issue — single small file, mechanical fix, easy to verify.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions