chore: remove dead code leftovers from caching rework
- Remove dead Redis exports (exampleChannel, homeAssistantEntityState, queueChannel) - Remove dead Beszel subscribeRealtimeMetrics/subscribeTopic (~100 lines) - Add missing onSettled invalidation to downloads queue + indexer-manager mutations - Rename invalidate-update-checker-cache → warm-update-checker - Delete empty cron-jobs/integrations directory - Fix stale comment and unused type imports
This commit is contained in:
7 files changed
+26
-144
No files matched your search
@@ -1,7 +1,7 @@
|
||||
import { invalidateUpdateCheckerCacheAsync } from "./invalidate-update-checker-cache";
|
||||
import { cleanupSessionsAsync } from "./session-cleanup";
|
||||
import { warmUpdateCheckerAsync } from "./warm-update-checker";
|
||||
|
||||
export async function onStartAsync() {
|
||||
await cleanupSessionsAsync();
|
||||
await invalidateUpdateCheckerCacheAsync();
|
||||
await warmUpdateCheckerAsync();
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
import { createLogger } from "@homarr/core/infrastructure/logs";
|
||||
import { updateCheckerRequestHandler } from "@homarr/request-handler/update-checker";
|
||||
|
||||
const logger = createLogger({ module: "invalidateUpdateCheckerCache" });
|
||||
|
||||
/**
|
||||
* Invalidates the update checker cache on startup to ensure fresh data.
|
||||
* It is important as we want to avoid showing pending updates after the update to latest version.
|
||||
*/
|
||||
export async function invalidateUpdateCheckerCacheAsync() {
|
||||
try {
|
||||
const handler = updateCheckerRequestHandler.handler({});
|
||||
await handler.getDataAsync();
|
||||
logger.debug("Update checker cache refreshed");
|
||||
} catch (error) {
|
||||
logger.error(new Error("Failed to invalidate update checker cache", { cause: error }));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { createLogger } from "@homarr/core/infrastructure/logs";
|
||||
import { updateCheckerRequestHandler } from "@homarr/request-handler/update-checker";
|
||||
|
||||
const logger = createLogger({ module: "warmUpdateChecker" });
|
||||
|
||||
export async function warmUpdateCheckerAsync() {
|
||||
try {
|
||||
const handler = updateCheckerRequestHandler.handler({});
|
||||
await handler.getDataAsync();
|
||||
logger.debug("Update checker warmed");
|
||||
} catch (error) {
|
||||
logger.error(new Error("Failed to warm update checker", { cause: error }));
|
||||
}
|
||||
}
|
||||
@@ -13,13 +13,11 @@ import type {
|
||||
BeszelAlertHistory,
|
||||
BeszelAuthResponse,
|
||||
BeszelContainer,
|
||||
BeszelContainerStats,
|
||||
BeszelContainerStatsRecord,
|
||||
BeszelSmartDevice,
|
||||
BeszelSystem,
|
||||
BeszelSystemDetails,
|
||||
BeszelSystemdService,
|
||||
BeszelSystemStats,
|
||||
BeszelSystemStatsRecord,
|
||||
CreateAlertInput,
|
||||
PocketBaseListResponse,
|
||||
@@ -286,111 +284,6 @@ export class BeszelIntegration extends Integration {
|
||||
});
|
||||
}
|
||||
|
||||
public async subscribeRealtimeMetrics(
|
||||
systemId: string,
|
||||
onMessage: (data: { stats: BeszelSystemStatsRecord; containerStats: BeszelContainerStatsRecord | null }) => void,
|
||||
signal: AbortSignal,
|
||||
): Promise<void> {
|
||||
const session = await this.authenticateAsync();
|
||||
const sseUrl = this.url("/api/realtime");
|
||||
logger.debug("Opening Beszel SSE connection", { integrationId: this.integration.id, systemId });
|
||||
|
||||
const sseResponse = await fetchWithTrustedCertificatesAsync(sseUrl, {
|
||||
headers: { Authorization: session.token },
|
||||
signal,
|
||||
});
|
||||
|
||||
if (!sseResponse.ok || !sseResponse.body) {
|
||||
logger.warn("Beszel SSE connection failed", {
|
||||
integrationId: this.integration.id,
|
||||
systemId,
|
||||
status: sseResponse.status,
|
||||
});
|
||||
throw new ResponseError(sseResponse);
|
||||
}
|
||||
logger.debug("Beszel SSE connection opened", { integrationId: this.integration.id, systemId });
|
||||
|
||||
const reader = sseResponse.body.getReader();
|
||||
const decoder = new TextDecoder();
|
||||
let buffer = "";
|
||||
let clientId: string | null = null;
|
||||
|
||||
const processLine = (line: string) => {
|
||||
if (!line.startsWith("data:")) return;
|
||||
const jsonStr = line.slice(5).trim();
|
||||
if (!jsonStr) return;
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(jsonStr) as Record<string, unknown>;
|
||||
|
||||
if (!clientId && typeof parsed.clientId === "string") {
|
||||
clientId = parsed.clientId;
|
||||
this.subscribeTopic(clientId, systemId, session.token).catch((err) => {
|
||||
logger.warn("Failed to subscribe to rt_metrics topic, aborting SSE", { error: err });
|
||||
reader.cancel().catch(() => {});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if ("stats" in parsed) {
|
||||
const now = new Date().toISOString();
|
||||
const envelope = { id: "", system: systemId, type: "1m" as const, created: now, updated: now };
|
||||
const stats: BeszelSystemStatsRecord = { ...envelope, stats: parsed.stats as BeszelSystemStats };
|
||||
|
||||
let containerStats: BeszelContainerStatsRecord | null = null;
|
||||
const hasContainers =
|
||||
parsed.container &&
|
||||
Array.isArray(parsed.container) &&
|
||||
(parsed.container as BeszelContainerStats[]).length > 0;
|
||||
if (hasContainers) {
|
||||
containerStats = { ...envelope, stats: parsed.container as BeszelContainerStats[] };
|
||||
}
|
||||
onMessage({ stats, containerStats });
|
||||
}
|
||||
} catch {
|
||||
logger.debug("Failed to parse SSE message", { line });
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
while (!signal.aborted) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) break;
|
||||
|
||||
buffer += decoder.decode(value, { stream: true });
|
||||
const lines = buffer.split("\n");
|
||||
buffer = lines.pop() ?? "";
|
||||
for (const line of lines) {
|
||||
processLine(line);
|
||||
}
|
||||
}
|
||||
if (!signal.aborted) {
|
||||
logger.warn("Beszel SSE stream ended unexpectedly", {
|
||||
integrationId: this.integration.id,
|
||||
systemId,
|
||||
});
|
||||
throw new Error("Beszel SSE stream ended unexpectedly");
|
||||
}
|
||||
} finally {
|
||||
reader.cancel().catch(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
private async subscribeTopic(clientId: string, systemId: string, token: string): Promise<void> {
|
||||
const topic = `rt_metrics?options=${JSON.stringify({ query: { system: systemId } })}`;
|
||||
const response = await fetchWithTrustedCertificatesAsync(this.url("/api/realtime"), {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: token,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({ clientId, subscriptions: [topic] }),
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new ResponseError(response);
|
||||
}
|
||||
}
|
||||
|
||||
protected async testingAsync(input: IntegrationTestingInput): Promise<TestingResult> {
|
||||
const response = await input.fetchAsync(this.url("/api/collections/users/auth-with-password"), {
|
||||
method: "POST",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { LogLevel } from "@homarr/core/infrastructure/logs/constants";
|
||||
|
||||
import { createListChannel, createQueueChannel, createSubPubChannel } from "./lib/channel";
|
||||
import { createListChannel, createSubPubChannel } from "./lib/channel";
|
||||
|
||||
export {
|
||||
handshakeAsync,
|
||||
@@ -12,23 +12,11 @@ export {
|
||||
invalidateIntegrationCacheAsync,
|
||||
} from "./lib/channel";
|
||||
|
||||
export const exampleChannel = createSubPubChannel<{ message: string }>("example");
|
||||
export const pingChannel = createSubPubChannel<
|
||||
{ url: string; statusCode: number; durationMs: number } | { url: string; error: string }
|
||||
>("ping");
|
||||
export const pingUrlChannel = createListChannel<string>("ping-url");
|
||||
|
||||
export const homeAssistantEntityState = createSubPubChannel<{
|
||||
entityId: string;
|
||||
state: string;
|
||||
}>("home-assistant/entity-state");
|
||||
|
||||
export const queueChannel = createQueueChannel<{
|
||||
name: string;
|
||||
executionDate: Date;
|
||||
data: unknown;
|
||||
}>("common-queue");
|
||||
|
||||
export interface LoggerMessage {
|
||||
message: string;
|
||||
level: LogLevel;
|
||||
|
||||
@@ -117,7 +117,7 @@ export default function DownloadClientsWidget({
|
||||
const { mutate: mutatePauseItem } = clientApi.widget.downloads.pauseItem.useMutation(invalidateDownloads);
|
||||
const { mutate: mutateDeleteItem } = clientApi.widget.downloads.deleteItem.useMutation(invalidateDownloads);
|
||||
|
||||
//Flatten Data array for which each element has it's integration, data (base + calculated) and actions. Memoized on data subscription
|
||||
//Flatten Data array for which each element has its integration, data (base + calculated) and actions
|
||||
const data = useMemo<ExtendedDownloadClientItem[]>(
|
||||
() =>
|
||||
currentItems
|
||||
@@ -748,8 +748,10 @@ const ClientsControl = ({ clients, filters, setFilters, availableStatuses }: Cli
|
||||
"/s",
|
||||
);
|
||||
|
||||
const { mutate: mutateResumeQueue } = clientApi.widget.downloads.resume.useMutation();
|
||||
const { mutate: mutatePauseQueue } = clientApi.widget.downloads.pause.useMutation();
|
||||
const utils = clientApi.useUtils();
|
||||
const invalidateDownloads = { onSettled: () => void utils.widget.downloads.getJobsAndStatuses.invalidate() };
|
||||
const { mutate: mutateResumeQueue } = clientApi.widget.downloads.resume.useMutation(invalidateDownloads);
|
||||
const { mutate: mutatePauseQueue } = clientApi.widget.downloads.pause.useMutation(invalidateDownloads);
|
||||
const [opened, { open, close }] = useDisclosure(false);
|
||||
const t = useScopedI18n("widget.downloads");
|
||||
return (
|
||||
|
||||
@@ -20,7 +20,10 @@ export default function IndexerManagerWidget({
|
||||
const t = useI18n();
|
||||
const { data: indexersData = [] } = clientApi.widget.indexerManager.getIndexersStatus.useQuery({ integrationIds });
|
||||
|
||||
const { mutate: testAll, isPending } = clientApi.widget.indexerManager.testAllIndexers.useMutation();
|
||||
const utils = clientApi.useUtils();
|
||||
const { mutate: testAll, isPending } = clientApi.widget.indexerManager.testAllIndexers.useMutation({
|
||||
onSettled: () => void utils.widget.indexerManager.getIndexersStatus.invalidate(),
|
||||
});
|
||||
const board = useRequiredBoard();
|
||||
const hasSmallWidth = width < 256;
|
||||
const hasSmallHeight = height < 256;
|
||||
|
||||
Reference in new issue
Block a user