fix(beszel): widget transparency, error handling, and cache invalidation
- Remove hardcoded background colors from Beszel grid/table widgets so the board's opacity slider controls the background via the parent card's --background-color CSS variable - Grid: set bg="transparent" on inner Card components - Table: override mantine-datatable default backgrounds to transparent - Stats: make system selector toggle only visible on hover - Stats: fix chart width/height(-1) warning by setting minHeight: 1 - All Beszel widgets: throw query errors to trigger the ErrorBoundary instead of silently rendering an empty/black UI - Add retry: false to beszel-system-stats queries - Add invalidateIntegrationCacheAsync() to clear all cached data and session stores for an integration when it is updated or deleted, preventing stale/errored data from persisting after config changes
This commit is contained in:
10 files changed
+84
-20
No files matched your search
@@ -15,6 +15,7 @@ export {
|
||||
createGetSetChannel,
|
||||
createQueryCacheChannel,
|
||||
getAllQueryCacheAsync,
|
||||
invalidateIntegrationCacheAsync,
|
||||
} from "./lib/channel";
|
||||
|
||||
export { createIntegrationHistoryChannel } from "./lib/channels/history-channel";
|
||||
|
||||
@@ -261,6 +261,31 @@ export const createIntegrationOptionsChannel = <TData>(
|
||||
return createChannelWithLatestAndEvents<TData>(channelName);
|
||||
};
|
||||
|
||||
/**
|
||||
* Invalidates all cached data for a given integration by deleting every Redis key
|
||||
* that starts with `integration:${integrationId}:` as well as the integration's
|
||||
* session store entry. This ensures that stale data from a misconfigured or
|
||||
* updated integration is never served from cache.
|
||||
*/
|
||||
export const invalidateIntegrationCacheAsync = async (integrationId: string): Promise<void> => {
|
||||
const patterns = [`integration:${integrationId}:*`, `session-store:${integrationId}`];
|
||||
let deletedCount = 0;
|
||||
for (const pattern of patterns) {
|
||||
let cursor = "0";
|
||||
do {
|
||||
const [nextCursor, keys] = await getSetClient.scan(cursor, "MATCH", pattern, "COUNT", 200);
|
||||
cursor = nextCursor;
|
||||
if (keys.length > 0) {
|
||||
await getSetClient.del(...keys);
|
||||
deletedCount += keys.length;
|
||||
}
|
||||
} while (cursor !== "0");
|
||||
}
|
||||
if (deletedCount > 0) {
|
||||
logger.info("Invalidated integration cache", { integrationId, deletedKeys: deletedCount });
|
||||
}
|
||||
};
|
||||
|
||||
export const createWidgetOptionsChannel = <TData>(
|
||||
widgetKind: WidgetKind,
|
||||
queryKey: string,
|
||||
|
||||
Reference in new issue
Block a user