[object Object]

← back to Marketing Command Center

copy: consolidate onto shared lib/fetch-timeout.js (drop duplicate helper)

0c84eb55de9914a389d447c17b962cbc87668766 · 2026-08-17 06:13:09 -0700 · Steve Abrams

Files touched

Diff

commit 0c84eb55de9914a389d447c17b962cbc87668766
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Mon Aug 17 06:13:09 2026 -0700

    copy: consolidate onto shared lib/fetch-timeout.js (drop duplicate helper)
---
 modules/copy/index.js | 19 +++++++------------
 1 file changed, 7 insertions(+), 12 deletions(-)

diff --git a/modules/copy/index.js b/modules/copy/index.js
index 353a192..78046f0 100644
--- a/modules/copy/index.js
+++ b/modules/copy/index.js
@@ -13,6 +13,7 @@
 // No outbound sends here — this only DRAFTS copy. CAN-SPAM footer is flagged as
 // a required manual add for the 'email' kind (compliance lives in brand.js).
 const brand = require('../../lib/brand.js');
+const { fetchWithTimeout: sharedFetchWithTimeout } = require('../../lib/fetch-timeout.js');
 
 const KINDS = [
   { id: 'subject-lines', label: 'Email subject lines' },
@@ -205,19 +206,13 @@ function userPromptFor(ctx, n) {
 
 // fetch() with a hard timeout. Node's fetch has NO default timeout, so a stalled
 // upstream (Anthropic/Gemini) would hang the POST /generate|/score request
-// forever, spinning the user's button. Aborts after LLM_TIMEOUT_MS and throws an
-// AbortError the existing callers already catch (→ 500 for generate, heuristic
-// fallback for score).
+// forever, spinning the user's button. Shared AbortController logic lives in
+// lib/fetch-timeout.js; we keep copy's own COPY_LLM_TIMEOUT_MS default so this
+// module stays independently tunable. The thrown AbortError is caught by the
+// existing callers (→ 500 for generate, heuristic fallback for score).
 const LLM_TIMEOUT_MS = Number(process.env.COPY_LLM_TIMEOUT_MS) || 45000;
-async function fetchWithTimeout(url, opts = {}, ms = LLM_TIMEOUT_MS) {
-  const ctrl = new AbortController();
-  const timer = setTimeout(() => ctrl.abort(), ms);
-  try {
-    return await fetch(url, { ...opts, signal: ctrl.signal });
-  } finally {
-    clearTimeout(timer);
-  }
-}
+const fetchWithTimeout = (url, opts = {}, ms = LLM_TIMEOUT_MS) =>
+  sharedFetchWithTimeout(url, opts, ms);
 
 async function llmGenerate(ctx, n) {
   const key = process.env.ANTHROPIC_API_KEY;

← f6af2dd auto-data-snapshot: 2026-08-16T09:54:36 (1 data files) — pub  ·  back to Marketing Command Center  ·  ig-activity: IG Posts panel — show all fleet IG posts + per- 4fd1cb4 →