feat(backups): configure backup webhook timeout
Some checks failed
Release Workflow / determine-release-type (push) Has been cancelled
Release Workflow / checks (push) Has been cancelled
Release Workflow / e2e-tests (push) Has been cancelled
Release Workflow / build-images (push) Has been cancelled
Release Workflow / publish-release (push) Has been cancelled
Release Workflow / request-docs-version-update (push) Has been cancelled
Some checks failed
Release Workflow / determine-release-type (push) Has been cancelled
Release Workflow / checks (push) Has been cancelled
Release Workflow / e2e-tests (push) Has been cancelled
Release Workflow / build-images (push) Has been cancelled
Release Workflow / publish-release (push) Has been cancelled
Release Workflow / request-docs-version-update (push) Has been cancelled
This commit is contained in:
parent
38f5a669ae
commit
8772d4796e
10 changed files with 19 additions and 5 deletions
|
|
@ -45,6 +45,7 @@ describe("parseConfig", () => {
|
|||
ENABLE_DEV_PANEL: "true",
|
||||
SERVER_IP: "0.0.0.0",
|
||||
SERVER_IDLE_TIMEOUT: "120",
|
||||
WEBHOOK_TIMEOUT: "90",
|
||||
PORT: "8080",
|
||||
APP_VERSION: "1.2.3",
|
||||
MIGRATIONS_PATH: "/tmp/migrations",
|
||||
|
|
@ -57,6 +58,7 @@ describe("parseConfig", () => {
|
|||
environment: "development",
|
||||
serverIp: "0.0.0.0",
|
||||
serverIdleTimeout: 120,
|
||||
webhookTimeout: 90,
|
||||
resticHostname: "configured-restic-host",
|
||||
port: 8080,
|
||||
migrationsPath: "/tmp/migrations",
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ const envSchema = z
|
|||
NODE_ENV: z.enum(["development", "production", "test"]).default("production"),
|
||||
SERVER_IP: z.string().default("localhost"),
|
||||
SERVER_IDLE_TIMEOUT: z.coerce.number().int().default(60),
|
||||
WEBHOOK_TIMEOUT: z.coerce.number().int().default(60),
|
||||
RESTIC_HOSTNAME: z.string().optional(),
|
||||
PORT: z.coerce.number().int().default(4096),
|
||||
MIGRATIONS_PATH: z.string().optional(),
|
||||
|
|
@ -122,6 +123,7 @@ const envSchema = z
|
|||
environment: s.NODE_ENV,
|
||||
serverIp: s.SERVER_IP,
|
||||
serverIdleTimeout: s.SERVER_IDLE_TIMEOUT,
|
||||
webhookTimeout: s.WEBHOOK_TIMEOUT,
|
||||
resticHostname: s.RESTIC_HOSTNAME || getResticHostname(),
|
||||
port: s.PORT,
|
||||
migrationsPath: s.MIGRATIONS_PATH,
|
||||
|
|
|
|||
|
|
@ -146,6 +146,7 @@ test("close emits a synthetic backup.cancelled for a queued backup", () => {
|
|||
},
|
||||
webhooks: { pre: null, post: null },
|
||||
webhookAllowedOrigins: [],
|
||||
webhookTimeoutMs: 60_000,
|
||||
}),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ const createBackupRunPayload = async ({
|
|||
},
|
||||
webhooks: schedule.backupWebhooks ?? { pre: null, post: null },
|
||||
webhookAllowedOrigins: config.webhookAllowedOrigins,
|
||||
webhookTimeoutMs: config.webhookTimeout * 1000,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -82,6 +83,7 @@ const executeBackupWithoutAgent = async (
|
|||
options: payload.options,
|
||||
webhooks: payload.webhooks,
|
||||
webhookAllowedOrigins: payload.webhookAllowedOrigins,
|
||||
webhookTimeoutMs: payload.webhookTimeoutMs,
|
||||
signal,
|
||||
onProgress,
|
||||
formatError: toErrorDetails,
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ test("emits backup.failed when a backup command hits a restic error", async () =
|
|||
},
|
||||
webhooks: { pre: null, post: null },
|
||||
webhookAllowedOrigins: [],
|
||||
webhookTimeoutMs: 60_000,
|
||||
}),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ const createRunPayload = (overrides: Partial<BackupRunPayload> = {}) =>
|
|||
},
|
||||
webhooks: { pre: null, post: null },
|
||||
webhookAllowedOrigins: ["http://localhost:8080"],
|
||||
webhookTimeoutMs: 60_000,
|
||||
...overrides,
|
||||
});
|
||||
|
||||
|
|
@ -337,6 +338,7 @@ test("waits for running-job registration before returning to the processor loop"
|
|||
},
|
||||
webhooks: { pre: null, post: null },
|
||||
webhookAllowedOrigins: [],
|
||||
webhookTimeoutMs: 60_000,
|
||||
});
|
||||
const cancelPayload = fromPartial<BackupCancelPayload>({
|
||||
jobId: "job-1",
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ export const handleBackupRunCommand = (context: ControllerCommandContext, payloa
|
|||
options: payload.options,
|
||||
webhooks: payload.webhooks,
|
||||
webhookAllowedOrigins: payload.webhookAllowedOrigins,
|
||||
webhookTimeoutMs: payload.webhookTimeoutMs,
|
||||
signal: abortController.signal,
|
||||
onProgress: (progress) => {
|
||||
void Runtime.runPromise(
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ const backupRunSchema = z.object({
|
|||
runtime: backupRuntimeSchema,
|
||||
webhooks: backupWebhooksSchema,
|
||||
webhookAllowedOrigins: z.array(z.string()),
|
||||
webhookTimeoutMs: z.number(),
|
||||
}),
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ const runWithHooks = <TResult>(
|
|||
options: {},
|
||||
webhooks: { pre: null, post: null },
|
||||
webhookAllowedOrigins: ["http://localhost:8080"],
|
||||
webhookTimeoutMs: 60_000,
|
||||
signal: defaultSignal(),
|
||||
...options,
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import { z } from "zod";
|
|||
import type { CompressionMode, RepositoryConfig, ResticBackupProgressDto } from "../restic/index.js";
|
||||
import { toErrorDetails, toMessage } from "../utils/index.js";
|
||||
|
||||
const DEFAULT_BACKUP_WEBHOOK_TIMEOUT_MS = 10_000;
|
||||
const MAX_BACKUP_WEBHOOK_BODY_BYTES = 64 * 1024;
|
||||
const MAX_BACKUP_WEBHOOK_HEADERS = 32;
|
||||
const MAX_BACKUP_WEBHOOK_HEADER_BYTES = 8 * 1024;
|
||||
|
|
@ -82,6 +81,7 @@ type BackupLifecycleOptions<TResult> = {
|
|||
options: BackupOptions;
|
||||
webhooks: BackupWebhooks;
|
||||
webhookAllowedOrigins: readonly string[];
|
||||
webhookTimeoutMs: number;
|
||||
signal: AbortSignal;
|
||||
onProgress?: (progress: ResticBackupProgressDto) => void;
|
||||
formatError?: (error: unknown) => string;
|
||||
|
|
@ -190,7 +190,7 @@ const runBackupWebhook = (
|
|||
formatError: (error: unknown) => string;
|
||||
allowedOrigins: readonly string[];
|
||||
signal?: AbortSignal;
|
||||
timeoutMs?: number;
|
||||
timeoutMs: number;
|
||||
},
|
||||
) =>
|
||||
Effect.suspend(() => {
|
||||
|
|
@ -198,8 +198,7 @@ const runBackupWebhook = (
|
|||
return Effect.succeed(null);
|
||||
}
|
||||
|
||||
const timeoutMs = options.timeoutMs ?? DEFAULT_BACKUP_WEBHOOK_TIMEOUT_MS;
|
||||
const controller = createAbortController(timeoutMs, options.signal);
|
||||
const controller = createAbortController(options.timeoutMs, options.signal);
|
||||
|
||||
return Effect.tryPromise({
|
||||
try: async () => {
|
||||
|
|
@ -256,6 +255,7 @@ export const runBackupLifecycle = <TResult>({
|
|||
options,
|
||||
webhooks,
|
||||
webhookAllowedOrigins,
|
||||
webhookTimeoutMs,
|
||||
signal,
|
||||
onProgress,
|
||||
formatError = toErrorDetails,
|
||||
|
|
@ -268,6 +268,7 @@ export const runBackupLifecycle = <TResult>({
|
|||
{
|
||||
formatError,
|
||||
allowedOrigins: webhookAllowedOrigins,
|
||||
timeoutMs: webhookTimeoutMs,
|
||||
signal,
|
||||
},
|
||||
);
|
||||
|
|
@ -312,7 +313,7 @@ export const runBackupLifecycle = <TResult>({
|
|||
status: backupResult.hookStatus,
|
||||
error: backupResult.hookError,
|
||||
},
|
||||
{ formatError, allowedOrigins: webhookAllowedOrigins },
|
||||
{ formatError, allowedOrigins: webhookAllowedOrigins, timeoutMs: webhookTimeoutMs },
|
||||
);
|
||||
|
||||
if (signal.aborted) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue