mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-30 13:20:54 +01:00
fix(server): retain warnings for scheduled health failures
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
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([]);
|
||||
});
|
||||
|
||||
});
|
||||
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user