fix(server): retain warnings for scheduled health failures

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-10-25 00:40:05 -05:00
1 parent 2ca12f8063
commit da40899606
4 files changed
+35 -2

No files matched your search

@@ -1,3 +1,4 @@
import { logger } from "../middleware/logger.js";
import { instanceSettingsService } from "../services/instance-settings.js";
import { deleteCompany } from "../services/company-deletion.js";
import { notifyChatConnectionHealth } from "../services/chat-channels/connection-health-notifications.js";
@@ -257,4 +258,26 @@ const support = external ? { supported: true } : await getEmbeddedPostgresTestSu
await vi.advanceTimersByTimeAsync(1_800_000); expect(probe).toHaveBeenCalledOnce();
});
it("warns for a persisted failed probe without retrying before its saved deadline", async () => {
const warnings = vi.spyOn(logger, "warn").mockImplementation(() => undefined);
const requests = vi.fn(async () => new Response("private-provider-response", { status: 503 }));
const tools = toolAccessService(db, {
remoteHttpEndpointLookup: async () => [{ address: "8.8.8.8", family: 4 }], remoteHttpRequest: requests,
});
const row = await connection({ config: { url: "https://health.example.test/mcp" } });
await start(tools.scheduledHealth);
const [stored] = await db.select().from(toolConnections).where(eq(toolConnections.id, row.id));
expect(stored.healthCheckedAt).not.toBeNull();
expect(warnings).toHaveBeenCalledWith(
{ companyId, connectionId: row.id }, "Scheduled tool connection health check failed",
);
expect(JSON.stringify(warnings.mock.calls)).not.toContain("private-provider-response");
const due = stored.healthCheckedAt!.getTime() + 900_000;
await idleAt(due);
const before = requests.mock.calls.length;
await vi.advanceTimersByTimeAsync(180_000);
expect(requests).toHaveBeenCalledTimes(before);
expect(errors).toEqual([]);
});
});
-1
View File
@@ -1892,7 +1892,6 @@ async function startServerWithDatabaseTeardown(
logger.error({ err }, "status-card scheduler tick failed");
}));
if (isIdleTaskDrainActive() || heartbeatSchedulerStopped) return;
if (isIdleTaskDrainActive() || heartbeatSchedulerStopped) return;
if (!(await heartbeat.resolveSchedulingSuppression()).suppressed) {
// Periodically reap orphaned runs (5-min staleness threshold) and make sure
@@ -1,3 +1,4 @@
import { logger } from "../../../middleware/logger.js";
import { and, eq, ne, sql } from "drizzle-orm";
import { toolApplications, toolConnections, type Db } from "@paperclipai/db";
import { isConnectorFeatureEnabled } from "@paperclipai/shared";
@@ -39,7 +40,10 @@ export function connectionHealthSchedule(db: Db, checkHealth: ConnectionHealth["
if (!before || before.dueAt > Date.now()) return before ?? null;
let failure: unknown;
try { await checkHealth(id, { actorType: "system", actorId: "tool_health_sweep" }); }
catch (error) { failure = error; }
catch (error) {
failure = error;
logger.warn({ companyId: before.companyId, connectionId: id }, "Scheduled tool connection health check failed");
}
const [after] = await load(before.companyId, id);
if (failure && after && after.dueAt <= Date.now()) throw failure;
return after ?? null;