fix: address PR review — bugs, dead code, error handling

Critical fixes:
- Smart Home: invalidate entity state query after toggle mutation
- Beszel live mode: use 5s refetchInterval instead of global 30s
- Fix unit test assertions for 5-arg setQueryCacheAsync signature
- Fix serialize/deserialize mismatch: JSON.parse on read (matches persister's JSON.stringify)
- Remove render-time setActiveQueryCacheBoardId race (keep only useEffect)

Error handling:
- Log persistence errors instead of swallowing with catch(() => {})
- Log QueryCacheHydration failures with ErrorWithMetadata
- Beszel: log partial failures (system details, container stats)

Dead code removal:
- Remove dead queryKey from all 39 request handlers + lib files
- Delete unused Redis APIs: createCacheChannel, createChannelWithLatestAndEvents,
  createChannelEventHistory, history-channel.ts
- Remove stale createCacheChannel mock from docker test

Cleanup:
- Seed system-resources chart from initial query data (no empty start)
- Remove redundant refetchOnWindowFocus/refetchOnReconnect from BoardProvider
This commit is contained in:
Thomas Camlong committed 2026-06-25 11:25:09 +02:00
1 parent 457b1b0ce0
commit c4a664b7ac
50 files changed
+31 -254

No files matched your search

@@ -3,17 +3,22 @@ import { createAsyncStoragePersister } from "@tanstack/query-async-storage-persi
import { fetchApi } from "@homarr/api/client";
import { getActiveQueryCacheBoardId, queryCacheStoragePrefix } from "@homarr/api/query-cache";
// ponytail: write-only persister — restore is SSR-only via QueryCacheHydration
const queryCacheStorage = {
getItem: (_key: string) => null as string | null,
async setItem(_key: string, value: string) {
const boardId = getActiveQueryCacheBoardId();
if (!boardId) return;
await fetchApi.queryCache.setItem.mutate({ boardId, value }).catch(() => {});
await fetchApi.queryCache.setItem.mutate({ boardId, value }).catch((error) => {
console.warn("[query-cache] persist failed", error);
});
},
async removeItem(_key: string) {
const boardId = getActiveQueryCacheBoardId();
if (!boardId) return;
await fetchApi.queryCache.removeItem.mutate({ boardId }).catch(() => {});
await fetchApi.queryCache.removeItem.mutate({ boardId }).catch((error) => {
console.warn("[query-cache] remove failed", error);
});
},
};
@@ -7,8 +7,6 @@ import "~/styles/gridstack.scss";
import { dehydrate, HydrationBoundary } from "@tanstack/react-query";
import type { PersistedClient } from "@tanstack/react-query-persist-client";
import { parse } from "superjson";
import { getQueryClient } from "@homarr/api/server";
import { IntegrationProvider } from "@homarr/auth/client";
import { auth } from "@homarr/auth/next";
@@ -123,11 +121,14 @@ async function QueryCacheHydration({ userId, boardId }: { userId: string; boardI
const serialized = await getQueryCacheAsync(userId, boardId);
if (!serialized) return null;
const persisted = parse<PersistedClient>(serialized);
const persisted = JSON.parse(serialized) as PersistedClient;
if (!persisted?.clientState?.queries?.length) return null;
return <HydrationBoundary state={persisted.clientState} />;
} catch {
} catch (error) {
logger.warn(
new ErrorWithMetadata("Failed to hydrate query cache", { userId, boardId }, { cause: error }),
);
return null;
}
}