From 45c58c967e2036c6ffa64baa1dea2d2b4c4e9840 Mon Sep 17 00:00:00 2001 From: Thomas Camlong Date: Sat, 27 Jun 2026 12:09:48 +0200 Subject: [PATCH] revert: re-apply all deletions and request handler simplifications Restores the full PR changes after CodeRabbit review window. --- .../invalidate-update-checker-cache.ts | 18 -- packages/cron-jobs/src/jobs/docker.ts | 31 ---- .../src/jobs/integrations/dns-hole.ts | 15 -- .../src/jobs/integrations/downloads.ts | 16 -- .../src/jobs/integrations/firewall.ts | 46 ----- .../jobs/integrations/health-monitoring.ts | 33 ---- .../src/jobs/integrations/home-assistant.ts | 16 -- .../src/jobs/integrations/indexer-manager.ts | 14 -- .../src/jobs/integrations/media-organizer.ts | 36 ---- .../src/jobs/integrations/media-requests.ts | 24 --- .../src/jobs/integrations/media-server.ts | 14 -- .../jobs/integrations/media-transcoding.ts | 14 -- .../jobs/integrations/network-controller.ts | 14 -- .../src/jobs/integrations/notifications.ts | 14 -- .../src/jobs/integrations/timetable.ts | 20 --- .../src/jobs/integrations/tracearr.ts | 14 -- .../cron-jobs/src/jobs/integrations/umami.ts | 14 -- .../cron-jobs/src/jobs/integrations/vpn.ts | 14 -- .../src/jobs/minecraft-server-status.ts | 25 --- packages/cron-jobs/src/jobs/rss-feeds.ts | 39 ----- packages/cron-jobs/src/jobs/update-checker.ts | 11 -- packages/cron-jobs/src/jobs/weather.ts | 36 ---- .../redis/src/lib/channels/history-channel.ts | 6 - .../src/archive-team-warrior.ts | 8 +- .../request-handler/src/audiobookshelf.ts | 8 +- packages/request-handler/src/calendar.ts | 6 +- packages/request-handler/src/coolify.ts | 8 +- packages/request-handler/src/dns-hole.ts | 8 +- packages/request-handler/src/downloads.ts | 8 +- .../request-handler/src/indexer-manager.ts | 8 +- .../lib/cached-integration-request-handler.ts | 49 ------ .../src/lib/cached-request-handler.ts | 160 ------------------ .../cached-request-integration-job-handler.ts | 115 ------------- .../src/lib/cached-widget-request-handler.ts | 36 ---- packages/request-handler/src/media-release.ts | 8 +- .../request-handler/src/media-request-list.ts | 8 +- .../src/media-request-stats.ts | 8 +- packages/request-handler/src/media-server.ts | 8 +- .../request-handler/src/media-transcoding.ts | 8 +- .../src/minecraft-server-status.ts | 8 +- packages/request-handler/src/navidrome.ts | 8 +- .../request-handler/src/network-controller.ts | 8 +- packages/request-handler/src/notifications.ts | 8 +- packages/request-handler/src/paperless-ngx.ts | 8 +- packages/request-handler/src/releases.ts | 8 +- packages/request-handler/src/rss-feeds.ts | 8 +- .../src/smart-home-entity-state.ts | 8 +- .../request-handler/src/speedtest-tracker.ts | 8 +- packages/request-handler/src/stock-price.ts | 8 +- packages/request-handler/src/tracearr.ts | 8 +- packages/request-handler/src/ups.ts | 8 +- packages/request-handler/src/uptime-kuma.ts | 8 +- packages/request-handler/src/weather.ts | 8 +- 53 files changed, 52 insertions(+), 998 deletions(-) delete mode 100644 apps/tasks/src/on-start/invalidate-update-checker-cache.ts delete mode 100644 packages/cron-jobs/src/jobs/docker.ts delete mode 100644 packages/cron-jobs/src/jobs/integrations/dns-hole.ts delete mode 100644 packages/cron-jobs/src/jobs/integrations/downloads.ts delete mode 100644 packages/cron-jobs/src/jobs/integrations/firewall.ts delete mode 100644 packages/cron-jobs/src/jobs/integrations/health-monitoring.ts delete mode 100644 packages/cron-jobs/src/jobs/integrations/home-assistant.ts delete mode 100644 packages/cron-jobs/src/jobs/integrations/indexer-manager.ts delete mode 100644 packages/cron-jobs/src/jobs/integrations/media-organizer.ts delete mode 100644 packages/cron-jobs/src/jobs/integrations/media-requests.ts delete mode 100644 packages/cron-jobs/src/jobs/integrations/media-server.ts delete mode 100644 packages/cron-jobs/src/jobs/integrations/media-transcoding.ts delete mode 100644 packages/cron-jobs/src/jobs/integrations/network-controller.ts delete mode 100644 packages/cron-jobs/src/jobs/integrations/notifications.ts delete mode 100644 packages/cron-jobs/src/jobs/integrations/timetable.ts delete mode 100644 packages/cron-jobs/src/jobs/integrations/tracearr.ts delete mode 100644 packages/cron-jobs/src/jobs/integrations/umami.ts delete mode 100644 packages/cron-jobs/src/jobs/integrations/vpn.ts delete mode 100644 packages/cron-jobs/src/jobs/minecraft-server-status.ts delete mode 100644 packages/cron-jobs/src/jobs/rss-feeds.ts delete mode 100644 packages/cron-jobs/src/jobs/update-checker.ts delete mode 100644 packages/cron-jobs/src/jobs/weather.ts delete mode 100644 packages/redis/src/lib/channels/history-channel.ts delete mode 100644 packages/request-handler/src/lib/cached-integration-request-handler.ts delete mode 100644 packages/request-handler/src/lib/cached-request-handler.ts delete mode 100644 packages/request-handler/src/lib/cached-request-integration-job-handler.ts delete mode 100644 packages/request-handler/src/lib/cached-widget-request-handler.ts diff --git a/apps/tasks/src/on-start/invalidate-update-checker-cache.ts b/apps/tasks/src/on-start/invalidate-update-checker-cache.ts deleted file mode 100644 index 470989dcf..000000000 --- a/apps/tasks/src/on-start/invalidate-update-checker-cache.ts +++ /dev/null @@ -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.invalidateAsync(); - logger.debug("Update checker cache invalidated"); - } catch (error) { - logger.error(new Error("Failed to invalidate update checker cache", { cause: error })); - } -} diff --git a/packages/cron-jobs/src/jobs/docker.ts b/packages/cron-jobs/src/jobs/docker.ts deleted file mode 100644 index 963f395bf..000000000 --- a/packages/cron-jobs/src/jobs/docker.ts +++ /dev/null @@ -1,31 +0,0 @@ -import SuperJSON from "superjson"; - -import { createLogger } from "@homarr/core/infrastructure/logs"; -import { ErrorWithMetadata } from "@homarr/core/infrastructure/logs/error"; -import { EVERY_MINUTE } from "@homarr/cron-jobs-core/expressions"; -import { db, eq } from "@homarr/db"; -import { items } from "@homarr/db/schema"; -import { dockerContainersRequestHandler } from "@homarr/request-handler/docker"; - -import type { WidgetComponentProps } from "../../../widgets"; -import { createCronJob } from "../lib"; - -const logger = createLogger({ module: "dockerJobs" }); - -export const dockerContainersJob = createCronJob("dockerContainers", EVERY_MINUTE).withCallback(async () => { - const dockerItems = await db.query.items.findMany({ - where: eq(items.kind, "dockerContainers"), - }); - - await Promise.allSettled( - dockerItems.map(async (item) => { - try { - const options = SuperJSON.parse["options"]>(item.options); - const innerHandler = dockerContainersRequestHandler.handler(options); - await innerHandler.getCachedOrUpdatedDataAsync({ forceUpdate: true }); - } catch (error) { - logger.error(new ErrorWithMetadata("Failed to update Docker container status", { item }, { cause: error })); - } - }), - ); -}); diff --git a/packages/cron-jobs/src/jobs/integrations/dns-hole.ts b/packages/cron-jobs/src/jobs/integrations/dns-hole.ts deleted file mode 100644 index a78b28e08..000000000 --- a/packages/cron-jobs/src/jobs/integrations/dns-hole.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { EVERY_MINUTE } from "@homarr/cron-jobs-core/expressions"; -import { dnsHoleRequestHandler } from "@homarr/request-handler/dns-hole"; -import { createRequestIntegrationJobHandler } from "@homarr/request-handler/lib/cached-request-integration-job-handler"; - -import { createCronJob } from "../../lib"; - -export const dnsHoleJob = createCronJob("dnsHole", EVERY_MINUTE).withCallback( - createRequestIntegrationJobHandler(dnsHoleRequestHandler.handler, { - widgetKinds: ["dnsHoleSummary", "dnsHoleControls"], - getInput: { - dnsHoleSummary: () => ({}), - dnsHoleControls: () => ({}), - }, - }), -); diff --git a/packages/cron-jobs/src/jobs/integrations/downloads.ts b/packages/cron-jobs/src/jobs/integrations/downloads.ts deleted file mode 100644 index 54eb476dc..000000000 --- a/packages/cron-jobs/src/jobs/integrations/downloads.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { EVERY_5_SECONDS } from "@homarr/cron-jobs-core/expressions"; -import { downloadClientRequestHandler } from "@homarr/request-handler/downloads"; -import { createRequestIntegrationJobHandler } from "@homarr/request-handler/lib/cached-request-integration-job-handler"; - -import { createCronJob } from "../../lib"; - -export const downloadsJob = createCronJob("downloads", EVERY_5_SECONDS).withCallback( - createRequestIntegrationJobHandler(downloadClientRequestHandler.handler, { - widgetKinds: ["downloads"], - getInput: { - downloads: (options) => ({ - limit: options.limitPerIntegration, - }), - }, - }), -); diff --git a/packages/cron-jobs/src/jobs/integrations/firewall.ts b/packages/cron-jobs/src/jobs/integrations/firewall.ts deleted file mode 100644 index 50637a642..000000000 --- a/packages/cron-jobs/src/jobs/integrations/firewall.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { EVERY_5_SECONDS, EVERY_30_SECONDS, EVERY_HOUR, EVERY_MINUTE } from "@homarr/cron-jobs-core/expressions"; -import { - firewallCpuRequestHandler, - firewallInterfacesRequestHandler, - firewallMemoryRequestHandler, - firewallVersionRequestHandler, -} from "@homarr/request-handler/firewall"; -import { createRequestIntegrationJobHandler } from "@homarr/request-handler/lib/cached-request-integration-job-handler"; - -import { createCronJob } from "../../lib"; - -export const firewallCpuJob = createCronJob("firewallCpu", EVERY_5_SECONDS).withCallback( - createRequestIntegrationJobHandler(firewallCpuRequestHandler.handler, { - widgetKinds: ["firewall"], - getInput: { - firewall: () => ({}), - }, - }), -); - -export const firewallMemoryJob = createCronJob("firewallMemory", EVERY_MINUTE).withCallback( - createRequestIntegrationJobHandler(firewallMemoryRequestHandler.handler, { - widgetKinds: ["firewall"], - getInput: { - firewall: () => ({}), - }, - }), -); - -export const firewallInterfacesJob = createCronJob("firewallInterfaces", EVERY_30_SECONDS).withCallback( - createRequestIntegrationJobHandler(firewallInterfacesRequestHandler.handler, { - widgetKinds: ["firewall"], - getInput: { - firewall: () => ({}), - }, - }), -); - -export const firewallVersionJob = createCronJob("firewallVersion", EVERY_HOUR).withCallback( - createRequestIntegrationJobHandler(firewallVersionRequestHandler.handler, { - widgetKinds: ["firewall"], - getInput: { - firewall: () => ({}), - }, - }), -); diff --git a/packages/cron-jobs/src/jobs/integrations/health-monitoring.ts b/packages/cron-jobs/src/jobs/integrations/health-monitoring.ts deleted file mode 100644 index 4d09801d2..000000000 --- a/packages/cron-jobs/src/jobs/integrations/health-monitoring.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { EVERY_5_SECONDS } from "@homarr/cron-jobs-core/expressions"; -import { coolifyRequestHandler } from "@homarr/request-handler/coolify"; -import { clusterInfoRequestHandler, systemInfoRequestHandler } from "@homarr/request-handler/health-monitoring"; -import { createRequestIntegrationJobHandler } from "@homarr/request-handler/lib/cached-request-integration-job-handler"; - -import { createCronJob } from "../../lib"; - -export const healthMonitoringJob = createCronJob("healthMonitoring", EVERY_5_SECONDS).withCallback( - createRequestIntegrationJobHandler( - (integration, itemOptions: Record) => { - const { kind } = integration; - - if (kind === "beszel") { - return null as never; - } - if (kind !== "proxmox" && kind !== "mock" && kind !== "coolify") { - return systemInfoRequestHandler.handler({ ...integration, kind }, itemOptions); - } - if (kind === "coolify") { - return coolifyRequestHandler.handler({ ...integration, kind }, itemOptions); - } - return clusterInfoRequestHandler.handler({ ...integration, kind }, itemOptions); - }, - { - widgetKinds: ["healthMonitoring", "systemResources", "coolify"], - getInput: { - healthMonitoring: () => ({}), - systemResources: () => ({}), - coolify: () => ({}), - }, - }, - ), -); diff --git a/packages/cron-jobs/src/jobs/integrations/home-assistant.ts b/packages/cron-jobs/src/jobs/integrations/home-assistant.ts deleted file mode 100644 index 2723391a7..000000000 --- a/packages/cron-jobs/src/jobs/integrations/home-assistant.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { EVERY_MINUTE } from "@homarr/cron-jobs-core/expressions"; -import { createRequestIntegrationJobHandler } from "@homarr/request-handler/lib/cached-request-integration-job-handler"; -import { smartHomeEntityStateRequestHandler } from "@homarr/request-handler/smart-home-entity-state"; - -import { createCronJob } from "../../lib"; - -export const smartHomeEntityStateJob = createCronJob("smartHomeEntityState", EVERY_MINUTE).withCallback( - createRequestIntegrationJobHandler(smartHomeEntityStateRequestHandler.handler, { - widgetKinds: ["smartHome-entityState"], - getInput: { - "smartHome-entityState": (options) => ({ - entityId: options.entityId, - }), - }, - }), -); diff --git a/packages/cron-jobs/src/jobs/integrations/indexer-manager.ts b/packages/cron-jobs/src/jobs/integrations/indexer-manager.ts deleted file mode 100644 index 11da75508..000000000 --- a/packages/cron-jobs/src/jobs/integrations/indexer-manager.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { EVERY_5_MINUTES } from "@homarr/cron-jobs-core/expressions"; -import { indexerManagerRequestHandler } from "@homarr/request-handler/indexer-manager"; -import { createRequestIntegrationJobHandler } from "@homarr/request-handler/lib/cached-request-integration-job-handler"; - -import { createCronJob } from "../../lib"; - -export const indexerManagerJob = createCronJob("indexerManager", EVERY_5_MINUTES).withCallback( - createRequestIntegrationJobHandler(indexerManagerRequestHandler.handler, { - widgetKinds: ["indexerManager"], - getInput: { - indexerManager: () => ({}), - }, - }), -); diff --git a/packages/cron-jobs/src/jobs/integrations/media-organizer.ts b/packages/cron-jobs/src/jobs/integrations/media-organizer.ts deleted file mode 100644 index a84696da9..000000000 --- a/packages/cron-jobs/src/jobs/integrations/media-organizer.ts +++ /dev/null @@ -1,36 +0,0 @@ -import dayjs from "dayjs"; - -import { EVERY_MINUTE } from "@homarr/cron-jobs-core/expressions"; -import { calendarMonthRequestHandler } from "@homarr/request-handler/calendar"; -import { createRequestIntegrationJobHandler } from "@homarr/request-handler/lib/cached-request-integration-job-handler"; - -import { createCronJob } from "../../lib"; - -export const mediaOrganizerJob = createCronJob("mediaOrganizer", EVERY_MINUTE).withCallback( - createRequestIntegrationJobHandler(calendarMonthRequestHandler.handler, { - widgetKinds: ["calendar"], - getInput: { - // Request handler will run for all specified months - calendar: (options) => { - const inputs = []; - - const startOffset = -Number(options.filterPastMonths); - const endOffset = Number(options.filterFutureMonths); - - for (let offsetMonths = startOffset; offsetMonths <= endOffset; offsetMonths++) { - const year = dayjs().subtract(offsetMonths, "months").year(); - const month = dayjs().subtract(offsetMonths, "months").month(); - - inputs.push({ - year, - month, - releaseType: options.releaseType, - showUnmonitored: options.showUnmonitored, - }); - } - - return inputs; - }, - }, - }), -); diff --git a/packages/cron-jobs/src/jobs/integrations/media-requests.ts b/packages/cron-jobs/src/jobs/integrations/media-requests.ts deleted file mode 100644 index ededb6141..000000000 --- a/packages/cron-jobs/src/jobs/integrations/media-requests.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { EVERY_MINUTE } from "@homarr/cron-jobs-core/expressions"; -import { createRequestIntegrationJobHandler } from "@homarr/request-handler/lib/cached-request-integration-job-handler"; -import { mediaRequestListRequestHandler } from "@homarr/request-handler/media-request-list"; -import { mediaRequestStatsRequestHandler } from "@homarr/request-handler/media-request-stats"; - -import { createCronJob } from "../../lib"; - -export const mediaRequestStatsJob = createCronJob("mediaRequestStats", EVERY_MINUTE).withCallback( - createRequestIntegrationJobHandler(mediaRequestStatsRequestHandler.handler, { - widgetKinds: ["mediaRequests-requestStats"], - getInput: { - "mediaRequests-requestStats": () => ({}), - }, - }), -); - -export const mediaRequestListJob = createCronJob("mediaRequestList", EVERY_MINUTE).withCallback( - createRequestIntegrationJobHandler(mediaRequestListRequestHandler.handler, { - widgetKinds: ["mediaRequests-requestList"], - getInput: { - "mediaRequests-requestList": () => ({}), - }, - }), -); diff --git a/packages/cron-jobs/src/jobs/integrations/media-server.ts b/packages/cron-jobs/src/jobs/integrations/media-server.ts deleted file mode 100644 index 099ea53ae..000000000 --- a/packages/cron-jobs/src/jobs/integrations/media-server.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { EVERY_5_SECONDS } from "@homarr/cron-jobs-core/expressions"; -import { createRequestIntegrationJobHandler } from "@homarr/request-handler/lib/cached-request-integration-job-handler"; -import { mediaServerRequestHandler } from "@homarr/request-handler/media-server"; - -import { createCronJob } from "../../lib"; - -export const mediaServerJob = createCronJob("mediaServer", EVERY_5_SECONDS).withCallback( - createRequestIntegrationJobHandler(mediaServerRequestHandler.handler, { - widgetKinds: ["mediaServer"], - getInput: { - mediaServer: ({ showOnlyPlaying }) => ({ showOnlyPlaying }), - }, - }), -); diff --git a/packages/cron-jobs/src/jobs/integrations/media-transcoding.ts b/packages/cron-jobs/src/jobs/integrations/media-transcoding.ts deleted file mode 100644 index c039dc250..000000000 --- a/packages/cron-jobs/src/jobs/integrations/media-transcoding.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { EVERY_5_MINUTES } from "@homarr/cron-jobs-core/expressions"; -import { createRequestIntegrationJobHandler } from "@homarr/request-handler/lib/cached-request-integration-job-handler"; -import { mediaTranscodingRequestHandler } from "@homarr/request-handler/media-transcoding"; - -import { createCronJob } from "../../lib"; - -export const mediaTranscodingJob = createCronJob("mediaTranscoding", EVERY_5_MINUTES).withCallback( - createRequestIntegrationJobHandler(mediaTranscodingRequestHandler.handler, { - widgetKinds: ["mediaTranscoding"], - getInput: { - mediaTranscoding: () => ({ pageOffset: 0, pageSize: 10 }), - }, - }), -); diff --git a/packages/cron-jobs/src/jobs/integrations/network-controller.ts b/packages/cron-jobs/src/jobs/integrations/network-controller.ts deleted file mode 100644 index 5d9354588..000000000 --- a/packages/cron-jobs/src/jobs/integrations/network-controller.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { EVERY_MINUTE } from "@homarr/cron-jobs-core/expressions"; -import { createRequestIntegrationJobHandler } from "@homarr/request-handler/lib/cached-request-integration-job-handler"; -import { networkControllerRequestHandler } from "@homarr/request-handler/network-controller"; - -import { createCronJob } from "../../lib"; - -export const networkControllerJob = createCronJob("networkController", EVERY_MINUTE).withCallback( - createRequestIntegrationJobHandler(networkControllerRequestHandler.handler, { - widgetKinds: ["networkControllerSummary"], - getInput: { - networkControllerSummary: () => ({}), - }, - }), -); diff --git a/packages/cron-jobs/src/jobs/integrations/notifications.ts b/packages/cron-jobs/src/jobs/integrations/notifications.ts deleted file mode 100644 index 0f544995f..000000000 --- a/packages/cron-jobs/src/jobs/integrations/notifications.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { EVERY_5_MINUTES } from "@homarr/cron-jobs-core/expressions"; -import { createRequestIntegrationJobHandler } from "@homarr/request-handler/lib/cached-request-integration-job-handler"; -import { notificationsRequestHandler } from "@homarr/request-handler/notifications"; - -import { createCronJob } from "../../lib"; - -export const refreshNotificationsJob = createCronJob("refreshNotifications", EVERY_5_MINUTES).withCallback( - createRequestIntegrationJobHandler(notificationsRequestHandler.handler, { - widgetKinds: ["notifications"], - getInput: { - notifications: (options) => options, - }, - }), -); diff --git a/packages/cron-jobs/src/jobs/integrations/timetable.ts b/packages/cron-jobs/src/jobs/integrations/timetable.ts deleted file mode 100644 index b3964dc38..000000000 --- a/packages/cron-jobs/src/jobs/integrations/timetable.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { EVERY_5_MINUTES } from "@homarr/cron-jobs-core/expressions"; -import { createRequestIntegrationJobHandler } from "@homarr/request-handler/lib/cached-request-integration-job-handler"; -import { timetableGetTimetableRequestHandler } from "@homarr/request-handler/timetable"; - -import { createCronJob } from "../../lib"; - -export const timetableJob = createCronJob("timetable", EVERY_5_MINUTES).withCallback( - createRequestIntegrationJobHandler(timetableGetTimetableRequestHandler.handler, { - widgetKinds: ["timetable"], - getInput: { - timetable: (options) => - options.station - ? { - stationId: options.station.value, - limit: 10, - } - : [], - }, - }), -); diff --git a/packages/cron-jobs/src/jobs/integrations/tracearr.ts b/packages/cron-jobs/src/jobs/integrations/tracearr.ts deleted file mode 100644 index f80130374..000000000 --- a/packages/cron-jobs/src/jobs/integrations/tracearr.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { EVERY_5_SECONDS } from "@homarr/cron-jobs-core/expressions"; -import { createRequestIntegrationJobHandler } from "@homarr/request-handler/lib/cached-request-integration-job-handler"; -import { tracearrRequestHandler } from "@homarr/request-handler/tracearr"; - -import { createCronJob } from "../../lib"; - -export const tracearrJob = createCronJob("tracearr", EVERY_5_SECONDS).withCallback( - createRequestIntegrationJobHandler(tracearrRequestHandler.handler, { - widgetKinds: ["tracearr"], - getInput: { - tracearr: () => ({}), - }, - }), -); diff --git a/packages/cron-jobs/src/jobs/integrations/umami.ts b/packages/cron-jobs/src/jobs/integrations/umami.ts deleted file mode 100644 index c50a3c604..000000000 --- a/packages/cron-jobs/src/jobs/integrations/umami.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { EVERY_30_SECONDS } from "@homarr/cron-jobs-core/expressions"; -import { createRequestIntegrationJobHandler } from "@homarr/request-handler/lib/cached-request-integration-job-handler"; -import { umamiActiveVisitorsRequestHandler } from "@homarr/request-handler/umami"; - -import { createCronJob } from "../../lib"; - -export const umamiActiveVisitorsJob = createCronJob("umamiActiveVisitors", EVERY_30_SECONDS).withCallback( - createRequestIntegrationJobHandler(umamiActiveVisitorsRequestHandler.handler, { - widgetKinds: ["umami"], - getInput: { - umami: (options) => (options.websiteId ? { websiteId: options.websiteId } : []), - }, - }), -); diff --git a/packages/cron-jobs/src/jobs/integrations/vpn.ts b/packages/cron-jobs/src/jobs/integrations/vpn.ts deleted file mode 100644 index b6495b359..000000000 --- a/packages/cron-jobs/src/jobs/integrations/vpn.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { EVERY_30_SECONDS } from "@homarr/cron-jobs-core/expressions"; -import { vpnSummaryHandler } from "@homarr/request-handler/vpn"; -import { createRequestIntegrationJobHandler } from "@homarr/request-handler/lib/cached-request-integration-job-handler"; - -import { createCronJob } from "../../lib"; - -export const vpnJob = createCronJob("vpn", EVERY_30_SECONDS).withCallback( - createRequestIntegrationJobHandler(vpnSummaryHandler.handler, { - widgetKinds: ["vpn"], - getInput: { - vpn: () => ({}), - }, - }), -); diff --git a/packages/cron-jobs/src/jobs/minecraft-server-status.ts b/packages/cron-jobs/src/jobs/minecraft-server-status.ts deleted file mode 100644 index e6c084702..000000000 --- a/packages/cron-jobs/src/jobs/minecraft-server-status.ts +++ /dev/null @@ -1,25 +0,0 @@ -import SuperJSON from "superjson"; - -import { EVERY_5_MINUTES } from "@homarr/cron-jobs-core/expressions"; -import { db, eq } from "@homarr/db"; -import { items } from "@homarr/db/schema"; -import { minecraftServerStatusRequestHandler } from "@homarr/request-handler/minecraft-server-status"; - -import type { WidgetComponentProps } from "../../../widgets/src"; -import { createCronJob } from "../lib"; - -export const minecraftServerStatusJob = createCronJob("minecraftServerStatus", EVERY_5_MINUTES).withCallback( - async () => { - const dbItems = await db.query.items.findMany({ - where: eq(items.kind, "minecraftServerStatus"), - }); - - await Promise.allSettled( - dbItems.map(async (item) => { - const options = SuperJSON.parse["options"]>(item.options); - const innerHandler = minecraftServerStatusRequestHandler.handler(options); - await innerHandler.getCachedOrUpdatedDataAsync({ forceUpdate: true }); - }), - ); - }, -); diff --git a/packages/cron-jobs/src/jobs/rss-feeds.ts b/packages/cron-jobs/src/jobs/rss-feeds.ts deleted file mode 100644 index 6a497a043..000000000 --- a/packages/cron-jobs/src/jobs/rss-feeds.ts +++ /dev/null @@ -1,39 +0,0 @@ -import SuperJSON from "superjson"; - -import { createLogger } from "@homarr/core/infrastructure/logs"; -import { ErrorWithMetadata } from "@homarr/core/infrastructure/logs/error"; -import { EVERY_10_MINUTES } from "@homarr/cron-jobs-core/expressions"; -import { db, eq } from "@homarr/db"; -import { items } from "@homarr/db/schema"; -import { rssFeedsRequestHandler } from "@homarr/request-handler/rss-feeds"; - -// This import is done that way to avoid circular dependencies. -import type { WidgetComponentProps } from "../../../widgets"; -import { createCronJob } from "../lib"; - -const logger = createLogger({ module: "rssFeedsJobs" }); - -export const rssFeedsJob = createCronJob("rssFeeds", EVERY_10_MINUTES).withCallback(async () => { - const rssItems = await db.query.items.findMany({ - where: eq(items.kind, "rssFeed"), - }); - - const itemOptions = rssItems.map((item) => SuperJSON.parse["options"]>(item.options)); - - for (const option of itemOptions) { - const maxAmountPosts = typeof option.maximumAmountPosts === "number" ? option.maximumAmountPosts : 100; - for (const url of option.feedUrls) { - try { - const innerHandler = rssFeedsRequestHandler.handler({ - url, - count: maxAmountPosts, - }); - await innerHandler.getCachedOrUpdatedDataAsync({ - forceUpdate: true, - }); - } catch (error) { - logger.error(new ErrorWithMetadata("Failed to update RSS feed", { url }, { cause: error })); - } - } - } -}); diff --git a/packages/cron-jobs/src/jobs/update-checker.ts b/packages/cron-jobs/src/jobs/update-checker.ts deleted file mode 100644 index eea68d07b..000000000 --- a/packages/cron-jobs/src/jobs/update-checker.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { EVERY_DAY } from "@homarr/cron-jobs-core/expressions"; -import { updateCheckerRequestHandler } from "@homarr/request-handler/update-checker"; - -import { createCronJob } from "../lib"; - -export const updateCheckerJob = createCronJob("updateChecker", EVERY_DAY, { - runOnStart: true, -}).withCallback(async () => { - const handler = updateCheckerRequestHandler.handler({}); - await handler.getCachedOrUpdatedDataAsync({}); -}); diff --git a/packages/cron-jobs/src/jobs/weather.ts b/packages/cron-jobs/src/jobs/weather.ts deleted file mode 100644 index 1b23ade4c..000000000 --- a/packages/cron-jobs/src/jobs/weather.ts +++ /dev/null @@ -1,36 +0,0 @@ -import SuperJSON from "superjson"; - -import { createLogger } from "@homarr/core/infrastructure/logs"; -import { ErrorWithMetadata } from "@homarr/core/infrastructure/logs/error"; -import { EVERY_10_MINUTES } from "@homarr/cron-jobs-core/expressions"; -import { db, eq } from "@homarr/db"; -import { items } from "@homarr/db/schema"; -import { weatherRequestHandler } from "@homarr/request-handler/weather"; - -import type { WidgetComponentProps } from "../../../widgets"; -import { createCronJob } from "../lib"; - -const logger = createLogger({ module: "weatherJobs" }); - -export const weatherJob = createCronJob("weather", EVERY_10_MINUTES).withCallback(async () => { - const weatherItems = await db.query.items.findMany({ - where: eq(items.kind, "weather"), - }); - - const parsedItems = weatherItems.map((item) => ({ - id: item.id, - options: SuperJSON.parse["options"]>(item.options), - })); - - for (const item of parsedItems) { - try { - const innerHandler = weatherRequestHandler.handler({ - longitude: item.options.location.longitude, - latitude: item.options.location.latitude, - }); - await innerHandler.getCachedOrUpdatedDataAsync({ forceUpdate: true }); - } catch (error) { - logger.error(new ErrorWithMetadata("Failed to update weather", { id: item.id }, { cause: error })); - } - } -}); diff --git a/packages/redis/src/lib/channels/history-channel.ts b/packages/redis/src/lib/channels/history-channel.ts deleted file mode 100644 index 541830464..000000000 --- a/packages/redis/src/lib/channels/history-channel.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createChannelEventHistory } from "../channel"; - -export const createIntegrationHistoryChannel = (integrationId: string, queryKey: string, maxElements = 32) => { - const channelName = `integration:${integrationId}:history:${queryKey}`; - return createChannelEventHistory(channelName, maxElements); -}; diff --git a/packages/request-handler/src/archive-team-warrior.ts b/packages/request-handler/src/archive-team-warrior.ts index 4038ec9dc..e02391f19 100644 --- a/packages/request-handler/src/archive-team-warrior.ts +++ b/packages/request-handler/src/archive-team-warrior.ts @@ -1,12 +1,10 @@ -import dayjs from "dayjs"; - import type { IntegrationKindByCategory } from "@homarr/definitions"; import type { ArchiveTeamWarriorStatus } from "@homarr/integrations"; import { createIntegrationAsync } from "@homarr/integrations"; -import { createCachedIntegrationRequestHandler } from "./lib/cached-integration-request-handler"; +import { createIntegrationRequestHandler } from "./lib/integration-request-handler"; -export const archiveTeamWarriorRequestHandler = createCachedIntegrationRequestHandler< +export const archiveTeamWarriorRequestHandler = createIntegrationRequestHandler< ArchiveTeamWarriorStatus, IntegrationKindByCategory<"archiving">, Record @@ -15,6 +13,4 @@ export const archiveTeamWarriorRequestHandler = createCachedIntegrationRequestHa const integrationInstance = await createIntegrationAsync(integration); return await integrationInstance.getStatusAsync(); }, - cacheDuration: dayjs.duration(5, "minute"), - queryKey: "archiveTeamWarriorStatus", }); diff --git a/packages/request-handler/src/audiobookshelf.ts b/packages/request-handler/src/audiobookshelf.ts index bb4b2d83c..12562342c 100644 --- a/packages/request-handler/src/audiobookshelf.ts +++ b/packages/request-handler/src/audiobookshelf.ts @@ -1,11 +1,9 @@ -import dayjs from "dayjs"; - import { createIntegrationAsync } from "@homarr/integrations"; import type { AudiobookshelfDashboardData } from "@homarr/integrations/types"; -import { createCachedIntegrationRequestHandler } from "./lib/cached-integration-request-handler"; +import { createIntegrationRequestHandler } from "./lib/integration-request-handler"; -export const audiobookshelfRequestHandler = createCachedIntegrationRequestHandler< +export const audiobookshelfRequestHandler = createIntegrationRequestHandler< AudiobookshelfDashboardData, "audiobookshelf", Record @@ -14,6 +12,4 @@ export const audiobookshelfRequestHandler = createCachedIntegrationRequestHandle const integrationInstance = await createIntegrationAsync(integration); return await integrationInstance.getDashboardDataAsync(); }, - cacheDuration: dayjs.duration(10, "minutes"), - queryKey: "audiobookshelfDashboard", }); diff --git a/packages/request-handler/src/calendar.ts b/packages/request-handler/src/calendar.ts index dd198912a..a358d13e8 100644 --- a/packages/request-handler/src/calendar.ts +++ b/packages/request-handler/src/calendar.ts @@ -4,9 +4,9 @@ import type { IntegrationKindByCategory } from "@homarr/definitions"; import { createIntegrationAsync } from "@homarr/integrations"; import type { CalendarEvent, RadarrReleaseType } from "@homarr/integrations/types"; -import { createCachedIntegrationRequestHandler } from "./lib/cached-integration-request-handler"; +import { createIntegrationRequestHandler } from "./lib/integration-request-handler"; -export const calendarMonthRequestHandler = createCachedIntegrationRequestHandler< +export const calendarMonthRequestHandler = createIntegrationRequestHandler< CalendarEvent[], IntegrationKindByCategory<"calendar">, { year: number; month: number; releaseType: RadarrReleaseType[]; showUnmonitored: boolean } @@ -23,6 +23,4 @@ export const calendarMonthRequestHandler = createCachedIntegrationRequestHandler input.showUnmonitored, ); }, - cacheDuration: dayjs.duration(1, "minute"), - queryKey: "calendarMonth", }); diff --git a/packages/request-handler/src/coolify.ts b/packages/request-handler/src/coolify.ts index d307a780f..25ddfe962 100644 --- a/packages/request-handler/src/coolify.ts +++ b/packages/request-handler/src/coolify.ts @@ -1,11 +1,9 @@ -import dayjs from "dayjs"; - import { createIntegrationAsync } from "@homarr/integrations"; import type { CoolifyInstanceInfo } from "@homarr/integrations/types"; -import { createCachedIntegrationRequestHandler } from "./lib/cached-integration-request-handler"; +import { createIntegrationRequestHandler } from "./lib/integration-request-handler"; -export const coolifyRequestHandler = createCachedIntegrationRequestHandler< +export const coolifyRequestHandler = createIntegrationRequestHandler< CoolifyInstanceInfo, "coolify", Record @@ -14,6 +12,4 @@ export const coolifyRequestHandler = createCachedIntegrationRequestHandler< const integrationInstance = await createIntegrationAsync(integration); return await integrationInstance.getInstanceInfoAsync(); }, - cacheDuration: dayjs.duration(30, "seconds"), - queryKey: "coolifyInfo", }); diff --git a/packages/request-handler/src/dns-hole.ts b/packages/request-handler/src/dns-hole.ts index a8c920801..85188c740 100644 --- a/packages/request-handler/src/dns-hole.ts +++ b/packages/request-handler/src/dns-hole.ts @@ -1,12 +1,10 @@ -import dayjs from "dayjs"; - import type { IntegrationKindByCategory } from "@homarr/definitions"; import { createIntegrationAsync } from "@homarr/integrations"; import type { DnsHoleSummary } from "@homarr/integrations/types"; -import { createCachedIntegrationRequestHandler } from "./lib/cached-integration-request-handler"; +import { createIntegrationRequestHandler } from "./lib/integration-request-handler"; -export const dnsHoleRequestHandler = createCachedIntegrationRequestHandler< +export const dnsHoleRequestHandler = createIntegrationRequestHandler< DnsHoleSummary, IntegrationKindByCategory<"dnsHole">, Record @@ -15,6 +13,4 @@ export const dnsHoleRequestHandler = createCachedIntegrationRequestHandler< const integrationInstance = await createIntegrationAsync(integration); return await integrationInstance.getSummaryAsync(); }, - cacheDuration: dayjs.duration(5, "seconds"), - queryKey: "dnsHoleSummary", }); diff --git a/packages/request-handler/src/downloads.ts b/packages/request-handler/src/downloads.ts index 06d4e9c64..12106b07a 100644 --- a/packages/request-handler/src/downloads.ts +++ b/packages/request-handler/src/downloads.ts @@ -1,12 +1,10 @@ -import dayjs from "dayjs"; - import type { IntegrationKindByCategory } from "@homarr/definitions"; import type { DownloadClientJobsAndStatus } from "@homarr/integrations"; import { createIntegrationAsync } from "@homarr/integrations"; -import { createCachedIntegrationRequestHandler } from "./lib/cached-integration-request-handler"; +import { createIntegrationRequestHandler } from "./lib/integration-request-handler"; -export const downloadClientRequestHandler = createCachedIntegrationRequestHandler< +export const downloadClientRequestHandler = createIntegrationRequestHandler< DownloadClientJobsAndStatus, IntegrationKindByCategory<"downloadClient">, { limit: number } @@ -15,6 +13,4 @@ export const downloadClientRequestHandler = createCachedIntegrationRequestHandle const integrationInstance = await createIntegrationAsync(integration); return await integrationInstance.getClientJobsAndStatusAsync(input); }, - cacheDuration: dayjs.duration(5, "seconds"), - queryKey: "downloadClientJobStatus", }); diff --git a/packages/request-handler/src/indexer-manager.ts b/packages/request-handler/src/indexer-manager.ts index a957b32ad..f21a61f8f 100644 --- a/packages/request-handler/src/indexer-manager.ts +++ b/packages/request-handler/src/indexer-manager.ts @@ -1,12 +1,10 @@ -import dayjs from "dayjs"; - import type { IntegrationKindByCategory } from "@homarr/definitions"; import { createIntegrationAsync } from "@homarr/integrations"; import type { Indexer } from "@homarr/integrations/types"; -import { createCachedIntegrationRequestHandler } from "./lib/cached-integration-request-handler"; +import { createIntegrationRequestHandler } from "./lib/integration-request-handler"; -export const indexerManagerRequestHandler = createCachedIntegrationRequestHandler< +export const indexerManagerRequestHandler = createIntegrationRequestHandler< Indexer[], IntegrationKindByCategory<"indexerManager">, Record @@ -15,6 +13,4 @@ export const indexerManagerRequestHandler = createCachedIntegrationRequestHandle const integrationInstance = await createIntegrationAsync(integration); return await integrationInstance.getIndexersAsync(); }, - cacheDuration: dayjs.duration(5, "minutes"), - queryKey: "indexerManager", }); diff --git a/packages/request-handler/src/lib/cached-integration-request-handler.ts b/packages/request-handler/src/lib/cached-integration-request-handler.ts deleted file mode 100644 index aee69e39c..000000000 --- a/packages/request-handler/src/lib/cached-integration-request-handler.ts +++ /dev/null @@ -1,49 +0,0 @@ -import type { Duration } from "dayjs/plugin/duration"; - -import type { Modify } from "@homarr/common/types"; -import type { Integration, IntegrationSecret } from "@homarr/db/schema"; -import type { IntegrationKind } from "@homarr/definitions"; -import { createIntegrationOptionsChannel } from "@homarr/redis"; - -import { createCachedRequestHandler } from "./cached-request-handler"; - -type IntegrationOfKind = Omit & { - kind: TKind; - decryptedSecrets: Modify, { value: string }>[]; - externalUrl: string | null; -}; - -interface Options> { - queryKey: string; - requestAsync: (integration: IntegrationOfKind, input: TInput) => Promise; - cacheDuration: Duration; - cacheDurationForInput?: (input: TInput) => Duration | undefined; - fallbackToStaleOnError?: boolean; - retry?: { attempts?: number; delayMs?: number }; - isValid?: (data: TData) => boolean; -} - -export const createCachedIntegrationRequestHandler = < - TData, - TKind extends IntegrationKind, - TInput extends Record, ->( - options: Options, -) => { - return { - handler: (integration: IntegrationOfKind, itemOptions: TInput) => - createCachedRequestHandler({ - queryKey: options.queryKey, - requestAsync: async (input: { options: TInput; integration: IntegrationOfKind }) => { - return await options.requestAsync(input.integration, input.options); - }, - cacheDuration: options.cacheDurationForInput?.(itemOptions) ?? options.cacheDuration, - fallbackToStaleOnError: options.fallbackToStaleOnError, - retry: options.retry, - isValid: options.isValid, - createRedisChannel(input, handlerOptions) { - return createIntegrationOptionsChannel(input.integration.id, handlerOptions.queryKey, input.options); - }, - }).handler({ options: itemOptions, integration }), - }; -}; diff --git a/packages/request-handler/src/lib/cached-request-handler.ts b/packages/request-handler/src/lib/cached-request-handler.ts deleted file mode 100644 index c2342eed3..000000000 --- a/packages/request-handler/src/lib/cached-request-handler.ts +++ /dev/null @@ -1,160 +0,0 @@ -import dayjs from "dayjs"; -import type { Duration } from "dayjs/plugin/duration"; - -import { ErrorWithMetadata } from "@homarr/core/infrastructure/logs/error"; -import { createLogger } from "@homarr/core/infrastructure/logs"; -import type { createChannelWithLatestAndEvents } from "@homarr/redis"; - -const logger = createLogger({ module: "cachedRequestHandler" }); - -type FetchResult = { data: TData; timestamp: Date }; -type InFlightEntry = Promise>; - -const inFlightFetches = new Map(); - -const isAbortedError = (error: unknown): boolean => { - if (!(error instanceof Error)) return false; - return error.name === "AbortError" || error.name === "TimeoutError"; -}; - -interface Options> { - // Unique key for this request handler - queryKey: string; - requestAsync: (input: TInput) => Promise; - createRedisChannel: ( - input: TInput, - options: Options, - ) => ReturnType>; - cacheDuration: Duration; - fallbackToStaleOnError?: boolean; - // Retry the upstream call on failure. attempts=1 means no retry (default). - // AbortError / TimeoutError are never retried. - retry?: { attempts?: number; delayMs?: number }; - // Predicate to decide whether a fetched response is worth caching. - // Return false to skip the cache write (next call will refetch). - isValid?: (data: TData) => boolean; -} - -const defaultRetry = { attempts: 1, delayMs: 0 }; -const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); - -export const createCachedRequestHandler = >( - options: Options, -) => { - return { - handler: (input: TInput) => { - const channel = options.createRedisChannel(input, options); - const retryConfig = { ...defaultRetry, ...options.retry }; - - return { - async getCachedOrUpdatedDataAsync({ forceUpdate = false }) { - const channelData = await channel.getAsync(); - - const requestNewDataAsync = (): Promise> => { - const inflight = inFlightFetches.get(channel.name); - if (inflight) { - logger.debug("Cached request handler joining in-flight fetch", { - channel: channel.name, - queryKey: options.queryKey, - }); - return inflight as Promise>; - } - - const promise = (async (): Promise> => { - let lastError: unknown; - for (let attempt = 1; attempt <= retryConfig.attempts; attempt++) { - try { - const data = await options.requestAsync(input); - if (options.isValid && !options.isValid(data)) { - logger.warn("Cached request handler received invalid data, not caching", { - channel: channel.name, - queryKey: options.queryKey, - attempt, - }); - return { data, timestamp: new Date() }; - } - await channel.publishAndUpdateLastStateAsync(data); - return { data, timestamp: new Date() }; - } catch (error) { - lastError = error; - if (isAbortedError(error) || attempt === retryConfig.attempts) { - break; - } - logger.warn("Cached request handler fetch failed, retrying", { - channel: channel.name, - queryKey: options.queryKey, - attempt, - nextDelayMs: retryConfig.delayMs, - error: error instanceof Error ? `${error.name}: ${error.message}` : String(error), - }); - await sleep(retryConfig.delayMs); - } - } - - if (options.fallbackToStaleOnError && channelData) { - logger.warn( - new ErrorWithMetadata( - "Cached request handler using stale cache after fetch failure", - { - channel: channel.name, - queryKey: options.queryKey, - attempts: retryConfig.attempts, - }, - { cause: lastError }, - ), - ); - return channelData; - } - - throw lastError; - })().finally(() => { - inFlightFetches.delete(channel.name); - }); - - inFlightFetches.set(channel.name, promise as InFlightEntry); - return promise; - }; - - if (forceUpdate) { - logger.debug("Cached request handler forced update", { - channel: channel.name, - queryKey: options.queryKey, - }); - return await requestNewDataAsync(); - } - - const shouldRequestNewData = - !channelData || - dayjs().diff(channelData.timestamp, "milliseconds") > options.cacheDuration.asMilliseconds(); - - if (shouldRequestNewData) { - logger.debug("Cached request handler cache miss", { - channel: channel.name, - queryKey: options.queryKey, - reason: !channelData ? "no data" : "cache expired", - }); - return await requestNewDataAsync(); - } - - logger.debug("Cached request handler cache hit", { - channel: channel.name, - queryKey: options.queryKey, - expiresAt: dayjs(channelData.timestamp).add(options.cacheDuration).toISOString(), - }); - - return channelData; - }, - async invalidateAsync() { - logger.debug("Cached request handler invalidating cache", { - channel: channel.name, - queryKey: options.queryKey, - }); - await this.getCachedOrUpdatedDataAsync({ forceUpdate: true }); - }, - subscribe(callback: (data: TData) => void) { - return channel.subscribe(callback); - }, - }; - }, - }; -}; diff --git a/packages/request-handler/src/lib/cached-request-integration-job-handler.ts b/packages/request-handler/src/lib/cached-request-integration-job-handler.ts deleted file mode 100644 index 63e7682c2..000000000 --- a/packages/request-handler/src/lib/cached-request-integration-job-handler.ts +++ /dev/null @@ -1,115 +0,0 @@ -import SuperJSON from "superjson"; - -import { hashObjectBase64, Stopwatch } from "@homarr/common"; -import { decryptSecret } from "@homarr/common/server"; -import type { MaybeArray } from "@homarr/common/types"; -import { createLogger } from "@homarr/core/infrastructure/logs"; -import { ErrorWithMetadata } from "@homarr/core/infrastructure/logs/error"; -import { db } from "@homarr/db"; -import { getItemsWithIntegrationsAsync, getServerSettingsAsync } from "@homarr/db/queries"; -import type { WidgetKind } from "@homarr/definitions"; - -// This imports are done that way to avoid circular dependencies. -import type { inferSupportedIntegrationsStrict } from "../../../widgets/src"; -import { reduceWidgetOptionsWithDefaultValues } from "../../../widgets/src"; -import type { WidgetComponentProps } from "../../../widgets/src/definition"; -import type { createCachedIntegrationRequestHandler } from "./cached-integration-request-handler"; - -const logger = createLogger({ module: "cachedRequestIntegrationJobHandler" }); - -export const createRequestIntegrationJobHandler = < - TWidgetKind extends WidgetKind, - TIntegrationKind extends inferSupportedIntegrationsStrict, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - THandler extends ReturnType>["handler"], ->( - handler: THandler, - { - widgetKinds, - getInput, - }: { - widgetKinds: TWidgetKind[]; - getInput: { - [key in TWidgetKind]: (options: WidgetComponentProps["options"]) => MaybeArray[1]>; - }; - }, -) => { - return async () => { - const serverSettings = await getServerSettingsAsync(db); - const itemsForIntegration = await getItemsWithIntegrationsAsync(db, { - kinds: widgetKinds, - }); - - logger.debug("Found items for integration", { - widgetKinds: widgetKinds.join(","), - count: itemsForIntegration.length, - }); - - const distinctIntegrations: { - integrationId: string; - inputHash: string; - integration: (typeof itemsForIntegration)[number]["integrations"][number]["integration"]; - input: Parameters[1]; - }[] = []; - - for (const itemForIntegration of itemsForIntegration) { - const oneOrMultipleInputs = getInput[itemForIntegration.kind]( - reduceWidgetOptionsWithDefaultValues( - itemForIntegration.kind, - { - enableStatusByDefault: serverSettings.board.enableStatusByDefault, - forceDisableStatus: serverSettings.board.forceDisableStatus, - }, - SuperJSON.parse>(itemForIntegration.options), - ) as never, - ); - for (const { integration } of itemForIntegration.integrations) { - const inputArray = Array.isArray(oneOrMultipleInputs) ? oneOrMultipleInputs : [oneOrMultipleInputs]; - - for (const input of inputArray) { - const inputHash = hashObjectBase64(input); - if ( - distinctIntegrations.some( - (distinctIntegration) => - distinctIntegration.integrationId === integration.id && distinctIntegration.inputHash === inputHash, - ) - ) { - continue; - } - - distinctIntegrations.push({ integrationId: integration.id, inputHash, integration, input }); - } - } - } - - for (const { integrationId, integration, input, inputHash } of distinctIntegrations) { - try { - const decryptedSecrets = integration.secrets.map((secret) => ({ - ...secret, - value: decryptSecret(secret.value), - })); - - const innerHandler = handler( - { - ...integration, - kind: integration.kind as TIntegrationKind, - decryptedSecrets, - externalUrl: integration.app?.href ?? null, - }, - input, - ); - const stopWatch = new Stopwatch(); - await innerHandler.getCachedOrUpdatedDataAsync({ forceUpdate: true }); - logger.debug("Ran integration job", { - integration: integrationId, - inputHash, - elapsed: stopWatch.getElapsedInHumanWords(), - }); - } catch (error) { - logger.error( - new ErrorWithMetadata("Failed to run integration job", { integrationId, inputHash }, { cause: error }), - ); - } - } - }; -}; diff --git a/packages/request-handler/src/lib/cached-widget-request-handler.ts b/packages/request-handler/src/lib/cached-widget-request-handler.ts deleted file mode 100644 index 4016bc5b4..000000000 --- a/packages/request-handler/src/lib/cached-widget-request-handler.ts +++ /dev/null @@ -1,36 +0,0 @@ -import type { Duration } from "dayjs/plugin/duration"; - -import type { WidgetKind } from "@homarr/definitions"; -import { createWidgetOptionsChannel } from "@homarr/redis"; - -import { createCachedRequestHandler } from "./cached-request-handler"; - -interface Options> { - // Unique key for this request handler - queryKey: string; - requestAsync: (input: TInput) => Promise; - cacheDuration: Duration; - widgetKind: TKind; -} - -export const createCachedWidgetRequestHandler = < - TData, - TKind extends WidgetKind, - TInput extends Record, ->( - requestHandlerOptions: Options, -) => { - return { - handler: (widgetOptions: TInput) => - createCachedRequestHandler({ - queryKey: requestHandlerOptions.queryKey, - requestAsync: async (input: TInput) => { - return await requestHandlerOptions.requestAsync(input); - }, - cacheDuration: requestHandlerOptions.cacheDuration, - createRedisChannel(input, options) { - return createWidgetOptionsChannel(requestHandlerOptions.widgetKind, options.queryKey, input); - }, - }).handler(widgetOptions), - }; -}; diff --git a/packages/request-handler/src/media-release.ts b/packages/request-handler/src/media-release.ts index c0ffe48f3..02209f68f 100644 --- a/packages/request-handler/src/media-release.ts +++ b/packages/request-handler/src/media-release.ts @@ -1,12 +1,10 @@ -import dayjs from "dayjs"; - import type { IntegrationKindByCategory } from "@homarr/definitions"; import { createIntegrationAsync } from "@homarr/integrations"; import type { MediaRelease } from "@homarr/integrations/types"; -import { createCachedIntegrationRequestHandler } from "./lib/cached-integration-request-handler"; +import { createIntegrationRequestHandler } from "./lib/integration-request-handler"; -export const mediaReleaseRequestHandler = createCachedIntegrationRequestHandler< +export const mediaReleaseRequestHandler = createIntegrationRequestHandler< MediaRelease[], IntegrationKindByCategory<"mediaRelease">, Record @@ -15,6 +13,4 @@ export const mediaReleaseRequestHandler = createCachedIntegrationRequestHandler< const integrationInstance = await createIntegrationAsync(integration); return await integrationInstance.getMediaReleasesAsync(); }, - cacheDuration: dayjs.duration(5, "minutes"), - queryKey: "mediaReleases", }); diff --git a/packages/request-handler/src/media-request-list.ts b/packages/request-handler/src/media-request-list.ts index fd4e02234..62cf29a18 100644 --- a/packages/request-handler/src/media-request-list.ts +++ b/packages/request-handler/src/media-request-list.ts @@ -1,12 +1,10 @@ -import dayjs from "dayjs"; - import type { IntegrationKindByCategory } from "@homarr/definitions"; import { createIntegrationAsync } from "@homarr/integrations"; import type { MediaRequest } from "@homarr/integrations/types"; -import { createCachedIntegrationRequestHandler } from "./lib/cached-integration-request-handler"; +import { createIntegrationRequestHandler } from "./lib/integration-request-handler"; -export const mediaRequestListRequestHandler = createCachedIntegrationRequestHandler< +export const mediaRequestListRequestHandler = createIntegrationRequestHandler< MediaRequest[], IntegrationKindByCategory<"mediaRequest">, Record @@ -15,6 +13,4 @@ export const mediaRequestListRequestHandler = createCachedIntegrationRequestHand const integrationInstance = await createIntegrationAsync(integration); return await integrationInstance.getRequestsAsync(); }, - cacheDuration: dayjs.duration(1, "minute"), - queryKey: "mediaRequestList", }); diff --git a/packages/request-handler/src/media-request-stats.ts b/packages/request-handler/src/media-request-stats.ts index a6568aecd..61ff810b8 100644 --- a/packages/request-handler/src/media-request-stats.ts +++ b/packages/request-handler/src/media-request-stats.ts @@ -1,12 +1,10 @@ -import dayjs from "dayjs"; - import type { IntegrationKindByCategory } from "@homarr/definitions"; import { createIntegrationAsync } from "@homarr/integrations"; import type { MediaRequestStats } from "@homarr/integrations/types"; -import { createCachedIntegrationRequestHandler } from "./lib/cached-integration-request-handler"; +import { createIntegrationRequestHandler } from "./lib/integration-request-handler"; -export const mediaRequestStatsRequestHandler = createCachedIntegrationRequestHandler< +export const mediaRequestStatsRequestHandler = createIntegrationRequestHandler< MediaRequestStats, IntegrationKindByCategory<"mediaRequest">, Record @@ -18,6 +16,4 @@ export const mediaRequestStatsRequestHandler = createCachedIntegrationRequestHan users: await integrationInstance.getUsersAsync(), }; }, - cacheDuration: dayjs.duration(1, "minute"), - queryKey: "mediaRequestStats", }); diff --git a/packages/request-handler/src/media-server.ts b/packages/request-handler/src/media-server.ts index b13b90eb0..55a7850e0 100644 --- a/packages/request-handler/src/media-server.ts +++ b/packages/request-handler/src/media-server.ts @@ -1,12 +1,10 @@ -import dayjs from "dayjs"; - import type { IntegrationKindByCategory } from "@homarr/definitions"; import type { StreamSession } from "@homarr/integrations"; import { createIntegrationAsync } from "@homarr/integrations"; -import { createCachedIntegrationRequestHandler } from "./lib/cached-integration-request-handler"; +import { createIntegrationRequestHandler } from "./lib/integration-request-handler"; -export const mediaServerRequestHandler = createCachedIntegrationRequestHandler< +export const mediaServerRequestHandler = createIntegrationRequestHandler< StreamSession[], IntegrationKindByCategory<"mediaService">, { @@ -17,6 +15,4 @@ export const mediaServerRequestHandler = createCachedIntegrationRequestHandler< const integrationInstance = await createIntegrationAsync(integration); return await integrationInstance.getCurrentSessionsAsync({ showOnlyPlaying: input.showOnlyPlaying }); }, - cacheDuration: dayjs.duration(5, "seconds"), - queryKey: "mediaServerSessions", }); diff --git a/packages/request-handler/src/media-transcoding.ts b/packages/request-handler/src/media-transcoding.ts index 698d7347b..ba6455ccd 100644 --- a/packages/request-handler/src/media-transcoding.ts +++ b/packages/request-handler/src/media-transcoding.ts @@ -1,18 +1,14 @@ -import dayjs from "dayjs"; - import type { IntegrationKindByCategory } from "@homarr/definitions"; import { createIntegrationAsync } from "@homarr/integrations"; import type { TdarrQueue, TdarrStatistics, TdarrWorker } from "@homarr/integrations"; -import { createCachedIntegrationRequestHandler } from "./lib/cached-integration-request-handler"; +import { createIntegrationRequestHandler } from "./lib/integration-request-handler"; -export const mediaTranscodingRequestHandler = createCachedIntegrationRequestHandler< +export const mediaTranscodingRequestHandler = createIntegrationRequestHandler< MediaTranscoding, IntegrationKindByCategory<"mediaTranscoding">, { pageOffset: number; pageSize: number } >({ - queryKey: "mediaTranscoding", - cacheDuration: dayjs.duration(5, "minutes"), async requestAsync(integration, input) { const integrationInstance = await createIntegrationAsync(integration); return { diff --git a/packages/request-handler/src/minecraft-server-status.ts b/packages/request-handler/src/minecraft-server-status.ts index 98d850171..664a0a7f3 100644 --- a/packages/request-handler/src/minecraft-server-status.ts +++ b/packages/request-handler/src/minecraft-server-status.ts @@ -1,14 +1,11 @@ -import dayjs from "dayjs"; import { z } from "zod/v4"; import { fetchWithTrustedCertificatesAsync } from "@homarr/core/infrastructure/http"; import { withTimeoutAsync } from "@homarr/core/infrastructure/http/timeout"; -import { createCachedWidgetRequestHandler } from "./lib/cached-widget-request-handler"; +import { createWidgetRequestHandler } from "./lib/widget-request-handler"; -export const minecraftServerStatusRequestHandler = createCachedWidgetRequestHandler({ - queryKey: "minecraftServerStatusApiResult", - widgetKind: "minecraftServerStatus", +export const minecraftServerStatusRequestHandler = createWidgetRequestHandler({ async requestAsync(input: { domain: string; isBedrockServer: boolean }) { const path = `${input.isBedrockServer ? "/bedrock" : ""}/3/${input.domain}`; @@ -17,7 +14,6 @@ export const minecraftServerStatusRequestHandler = createCachedWidgetRequestHand ); return responseSchema.parse(await response.json()); }, - cacheDuration: dayjs.duration(5, "minutes"), }); const responseSchema = z diff --git a/packages/request-handler/src/navidrome.ts b/packages/request-handler/src/navidrome.ts index b59f852a8..0ad39ed9a 100644 --- a/packages/request-handler/src/navidrome.ts +++ b/packages/request-handler/src/navidrome.ts @@ -1,11 +1,9 @@ -import dayjs from "dayjs"; - import { createIntegrationAsync } from "@homarr/integrations"; import type { NavidromeDashboardData } from "@homarr/integrations/types"; -import { createCachedIntegrationRequestHandler } from "./lib/cached-integration-request-handler"; +import { createIntegrationRequestHandler } from "./lib/integration-request-handler"; -export const navidromeRequestHandler = createCachedIntegrationRequestHandler< +export const navidromeRequestHandler = createIntegrationRequestHandler< NavidromeDashboardData, "navidrome", Record @@ -14,6 +12,4 @@ export const navidromeRequestHandler = createCachedIntegrationRequestHandler< const integrationInstance = await createIntegrationAsync(integration); return await integrationInstance.getDashboardDataAsync(); }, - cacheDuration: dayjs.duration(10, "minutes"), - queryKey: "navidromeDashboard", }); diff --git a/packages/request-handler/src/network-controller.ts b/packages/request-handler/src/network-controller.ts index f5975acf2..123261025 100644 --- a/packages/request-handler/src/network-controller.ts +++ b/packages/request-handler/src/network-controller.ts @@ -1,12 +1,10 @@ -import dayjs from "dayjs"; - import type { IntegrationKindByCategory } from "@homarr/definitions"; import { createIntegrationAsync } from "@homarr/integrations"; import type { NetworkControllerSummary } from "@homarr/integrations/types"; -import { createCachedIntegrationRequestHandler } from "./lib/cached-integration-request-handler"; +import { createIntegrationRequestHandler } from "./lib/integration-request-handler"; -export const networkControllerRequestHandler = createCachedIntegrationRequestHandler< +export const networkControllerRequestHandler = createIntegrationRequestHandler< NetworkControllerSummary, IntegrationKindByCategory<"networkController">, Record @@ -15,6 +13,4 @@ export const networkControllerRequestHandler = createCachedIntegrationRequestHan const integrationInstance = await createIntegrationAsync(integration); return await integrationInstance.getNetworkSummaryAsync(); }, - cacheDuration: dayjs.duration(5, "minutes"), - queryKey: "networkControllerSummary", }); diff --git a/packages/request-handler/src/notifications.ts b/packages/request-handler/src/notifications.ts index 41098e660..479ff81fa 100644 --- a/packages/request-handler/src/notifications.ts +++ b/packages/request-handler/src/notifications.ts @@ -1,12 +1,10 @@ -import dayjs from "dayjs"; - import type { IntegrationKindByCategory } from "@homarr/definitions"; import type { Notification } from "@homarr/integrations"; import { createIntegrationAsync } from "@homarr/integrations"; -import { createCachedIntegrationRequestHandler } from "./lib/cached-integration-request-handler"; +import { createIntegrationRequestHandler } from "./lib/integration-request-handler"; -export const notificationsRequestHandler = createCachedIntegrationRequestHandler< +export const notificationsRequestHandler = createIntegrationRequestHandler< Notification[], IntegrationKindByCategory<"notifications">, Record @@ -15,6 +13,4 @@ export const notificationsRequestHandler = createCachedIntegrationRequestHandler const integrationInstance = await createIntegrationAsync(integration); return await integrationInstance.getNotificationsAsync(); }, - cacheDuration: dayjs.duration(5, "minutes"), - queryKey: "notificationsJobStatus", }); diff --git a/packages/request-handler/src/paperless-ngx.ts b/packages/request-handler/src/paperless-ngx.ts index a3793658f..e6b088006 100644 --- a/packages/request-handler/src/paperless-ngx.ts +++ b/packages/request-handler/src/paperless-ngx.ts @@ -1,11 +1,9 @@ -import dayjs from "dayjs"; - import { createIntegrationAsync } from "@homarr/integrations"; import type { PaperlessNgxStats } from "@homarr/integrations"; -import { createCachedIntegrationRequestHandler } from "./lib/cached-integration-request-handler"; +import { createIntegrationRequestHandler } from "./lib/integration-request-handler"; -export const paperlessNgxStatsRequestHandler = createCachedIntegrationRequestHandler< +export const paperlessNgxStatsRequestHandler = createIntegrationRequestHandler< PaperlessNgxStats, "paperlessNgx", Record @@ -14,6 +12,4 @@ export const paperlessNgxStatsRequestHandler = createCachedIntegrationRequestHan const integrationInstance = await createIntegrationAsync(integration); return await integrationInstance.getStatsAsync(); }, - cacheDuration: dayjs.duration(15, "minute"), - queryKey: "paperless-ngx-stats", }); diff --git a/packages/request-handler/src/releases.ts b/packages/request-handler/src/releases.ts index 7bfd29348..8b67e9793 100644 --- a/packages/request-handler/src/releases.ts +++ b/packages/request-handler/src/releases.ts @@ -1,12 +1,10 @@ -import dayjs from "dayjs"; - import type { IntegrationKindByCategory } from "@homarr/definitions"; import type { ReleaseResponse, ReleasesRepository } from "@homarr/integrations"; import { createIntegrationAsync } from "@homarr/integrations"; -import { createCachedIntegrationRequestHandler } from "./lib/cached-integration-request-handler"; +import { createIntegrationRequestHandler } from "./lib/integration-request-handler"; -export const releasesRequestHandler = createCachedIntegrationRequestHandler< +export const releasesRequestHandler = createIntegrationRequestHandler< ReleaseResponse, IntegrationKindByCategory<"releasesProvider">, ReleasesRepository @@ -15,6 +13,4 @@ export const releasesRequestHandler = createCachedIntegrationRequestHandler< const instance = await createIntegrationAsync(integration); return instance.getLatestMatchingReleaseAsync(input.identifier, input.versionRegex); }, - cacheDuration: dayjs.duration(5, "minutes"), - queryKey: "repositoriesReleases", }); diff --git a/packages/request-handler/src/rss-feeds.ts b/packages/request-handler/src/rss-feeds.ts index 9eaf026ea..0597a325f 100644 --- a/packages/request-handler/src/rss-feeds.ts +++ b/packages/request-handler/src/rss-feeds.ts @@ -1,18 +1,15 @@ import type { FeedData, FeedEntry } from "@extractus/feed-extractor"; import { extract } from "@extractus/feed-extractor"; -import dayjs from "dayjs"; import { z } from "zod/v4"; import type { Modify } from "@homarr/common/types"; import { createLogger } from "@homarr/core/infrastructure/logs"; -import { createCachedWidgetRequestHandler } from "./lib/cached-widget-request-handler"; +import { createWidgetRequestHandler } from "./lib/widget-request-handler"; const logger = createLogger({ module: "rssFeedsRequestHandler" }); -export const rssFeedsRequestHandler = createCachedWidgetRequestHandler({ - queryKey: "rssFeedList", - widgetKind: "rssFeed", +export const rssFeedsRequestHandler = createWidgetRequestHandler({ async requestAsync(input: { url: string; count: number }) { const result = (await extract(input.url, { getExtraEntryFields: (feedEntry) => { @@ -31,7 +28,6 @@ export const rssFeedsRequestHandler = createCachedWidgetRequestHandler({ entries: result.entries?.map((entry) => ({ ...entry, feedUrl: input.url })).slice(0, input.count) ?? [], }; }, - cacheDuration: dayjs.duration(5, "minutes"), }); const attemptGetImageFromEntry = (feedUrl: string, entry: object) => { diff --git a/packages/request-handler/src/smart-home-entity-state.ts b/packages/request-handler/src/smart-home-entity-state.ts index 5fe02b2ac..3c8851522 100644 --- a/packages/request-handler/src/smart-home-entity-state.ts +++ b/packages/request-handler/src/smart-home-entity-state.ts @@ -1,11 +1,9 @@ -import dayjs from "dayjs"; - import type { IntegrationKindByCategory } from "@homarr/definitions"; import { createIntegrationAsync } from "@homarr/integrations"; -import { createCachedIntegrationRequestHandler } from "./lib/cached-integration-request-handler"; +import { createIntegrationRequestHandler } from "./lib/integration-request-handler"; -export const smartHomeEntityStateRequestHandler = createCachedIntegrationRequestHandler< +export const smartHomeEntityStateRequestHandler = createIntegrationRequestHandler< string, IntegrationKindByCategory<"smartHomeServer">, { entityId: string } @@ -20,6 +18,4 @@ export const smartHomeEntityStateRequestHandler = createCachedIntegrationRequest return result.data.state; }, - cacheDuration: dayjs.duration(1, "minute"), - queryKey: "smartHome-entityState", }); diff --git a/packages/request-handler/src/speedtest-tracker.ts b/packages/request-handler/src/speedtest-tracker.ts index 799d37f16..3f03f7187 100644 --- a/packages/request-handler/src/speedtest-tracker.ts +++ b/packages/request-handler/src/speedtest-tracker.ts @@ -1,11 +1,9 @@ -import dayjs from "dayjs"; - import { createIntegrationAsync } from "@homarr/integrations"; import type { SpeedtestTrackerDashboardData } from "@homarr/integrations/types"; -import { createCachedIntegrationRequestHandler } from "./lib/cached-integration-request-handler"; +import { createIntegrationRequestHandler } from "./lib/integration-request-handler"; -export const speedtestTrackerRequestHandler = createCachedIntegrationRequestHandler< +export const speedtestTrackerRequestHandler = createIntegrationRequestHandler< SpeedtestTrackerDashboardData, "speedtestTracker", Record @@ -14,6 +12,4 @@ export const speedtestTrackerRequestHandler = createCachedIntegrationRequestHand const integrationInstance = await createIntegrationAsync(integration); return await integrationInstance.getDashboardDataAsync(); }, - cacheDuration: dayjs.duration(10, "minutes"), - queryKey: "speedtestTrackerDashboard", }); diff --git a/packages/request-handler/src/stock-price.ts b/packages/request-handler/src/stock-price.ts index b0ca15e47..177b223aa 100644 --- a/packages/request-handler/src/stock-price.ts +++ b/packages/request-handler/src/stock-price.ts @@ -1,14 +1,11 @@ -import dayjs from "dayjs"; import { z } from "zod/v4"; import { fetchWithTrustedCertificatesAsync } from "@homarr/core/infrastructure/http"; import { withTimeoutAsync } from "@homarr/core/infrastructure/http/timeout"; -import { createCachedWidgetRequestHandler } from "./lib/cached-widget-request-handler"; +import { createWidgetRequestHandler } from "./lib/widget-request-handler"; -export const fetchStockPriceHandler = createCachedWidgetRequestHandler({ - queryKey: "fetchStockPriceResult", - widgetKind: "stockPrice", +export const fetchStockPriceHandler = createWidgetRequestHandler({ async requestAsync(input: { stock: string; timeRange: string; timeInterval: string }) { const response = await withTimeoutAsync(async (signal) => { return await fetchWithTrustedCertificatesAsync( @@ -42,7 +39,6 @@ export const fetchStockPriceHandler = createCachedWidgetRequestHandler({ shortName: firstResult.meta.shortName, }; }, - cacheDuration: dayjs.duration(5, "minutes"), }); const dataSchema = z diff --git a/packages/request-handler/src/tracearr.ts b/packages/request-handler/src/tracearr.ts index 8f593ac03..641bf2922 100644 --- a/packages/request-handler/src/tracearr.ts +++ b/packages/request-handler/src/tracearr.ts @@ -1,11 +1,9 @@ -import dayjs from "dayjs"; - import { createIntegrationAsync } from "@homarr/integrations"; import type { TracearrDashboardData } from "@homarr/integrations/types"; -import { createCachedIntegrationRequestHandler } from "./lib/cached-integration-request-handler"; +import { createIntegrationRequestHandler } from "./lib/integration-request-handler"; -export const tracearrRequestHandler = createCachedIntegrationRequestHandler< +export const tracearrRequestHandler = createIntegrationRequestHandler< TracearrDashboardData, "tracearr", Record @@ -14,6 +12,4 @@ export const tracearrRequestHandler = createCachedIntegrationRequestHandler< const integrationInstance = await createIntegrationAsync(integration); return await integrationInstance.getDashboardDataAsync(); }, - cacheDuration: dayjs.duration(5, "seconds"), - queryKey: "tracearrDashboard", }); diff --git a/packages/request-handler/src/ups.ts b/packages/request-handler/src/ups.ts index acc97eb6d..4ca17b5ee 100644 --- a/packages/request-handler/src/ups.ts +++ b/packages/request-handler/src/ups.ts @@ -1,12 +1,10 @@ -import dayjs from "dayjs"; - import type { IntegrationKindByCategory } from "@homarr/definitions"; import { createIntegrationAsync } from "@homarr/integrations"; import type { UpsSummary } from "@homarr/integrations/types"; -import { createCachedIntegrationRequestHandler } from "./lib/cached-integration-request-handler"; +import { createIntegrationRequestHandler } from "./lib/integration-request-handler"; -export const upsSummariesRequestHandler = createCachedIntegrationRequestHandler< +export const upsSummariesRequestHandler = createIntegrationRequestHandler< UpsSummary[], IntegrationKindByCategory<"ups">, Record @@ -15,6 +13,4 @@ export const upsSummariesRequestHandler = createCachedIntegrationRequestHandler< const integrationInstance = await createIntegrationAsync(integration); return await integrationInstance.getUpsSummariesAsync(); }, - cacheDuration: dayjs.duration(1, "minute"), - queryKey: "upsSummaries", }); diff --git a/packages/request-handler/src/uptime-kuma.ts b/packages/request-handler/src/uptime-kuma.ts index 39149c137..b9453eb76 100644 --- a/packages/request-handler/src/uptime-kuma.ts +++ b/packages/request-handler/src/uptime-kuma.ts @@ -1,11 +1,9 @@ -import dayjs from "dayjs"; - import { createIntegrationAsync } from "@homarr/integrations"; import type { UptimeKumaDashboardData } from "@homarr/integrations/types"; -import { createCachedIntegrationRequestHandler } from "./lib/cached-integration-request-handler"; +import { createIntegrationRequestHandler } from "./lib/integration-request-handler"; -export const uptimeKumaRequestHandler = createCachedIntegrationRequestHandler< +export const uptimeKumaRequestHandler = createIntegrationRequestHandler< UptimeKumaDashboardData, "uptimeKuma", Record @@ -14,6 +12,4 @@ export const uptimeKumaRequestHandler = createCachedIntegrationRequestHandler< const integrationInstance = await createIntegrationAsync(integration); return await integrationInstance.getDashboardDataAsync(); }, - cacheDuration: dayjs.duration(1, "minute"), - queryKey: "uptimeKumaDashboard", }); diff --git a/packages/request-handler/src/weather.ts b/packages/request-handler/src/weather.ts index eb4828048..5f5a097a4 100644 --- a/packages/request-handler/src/weather.ts +++ b/packages/request-handler/src/weather.ts @@ -1,14 +1,11 @@ -import dayjs from "dayjs"; import { z } from "zod"; import { fetchWithTrustedCertificatesAsync } from "@homarr/core/infrastructure/http"; import { withTimeoutAsync } from "@homarr/core/infrastructure/http/timeout"; -import { createCachedWidgetRequestHandler } from "./lib/cached-widget-request-handler"; +import { createWidgetRequestHandler } from "./lib/widget-request-handler"; -export const weatherRequestHandler = createCachedWidgetRequestHandler({ - queryKey: "weatherAtLocation", - widgetKind: "weather", +export const weatherRequestHandler = createWidgetRequestHandler({ async requestAsync(input: { latitude: number; longitude: number }) { const res = await withTimeoutAsync(async (signal) => { return await fetchWithTrustedCertificatesAsync( @@ -34,7 +31,6 @@ export const weatherRequestHandler = createCachedWidgetRequestHandler({ }), } satisfies Weather; }, - cacheDuration: dayjs.duration(1, "minute"), }); const atLocationOutput = z.object({