Add fetch timeout and unify logging on stdout
- Abort the Anthropic fire request after FIRE_TIMEOUT_MS instead of letting it hang indefinitely with no outcome logged. - Log info and error levels both to stdout (JSON has a level field already) so a single log stream/tail shows the full picture instead of splitting across stdout/stderr, which was hiding forward failures from anyone only watching one of the two. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -17,3 +17,7 @@ ROUTINE_TOKEN=sk-ant-oat01-changeme
|
|||||||
|
|
||||||
# TTL en milisegundos para el dedup en memoria de entregas de Gitea (X-Gitea-Delivery)
|
# TTL en milisegundos para el dedup en memoria de entregas de Gitea (X-Gitea-Delivery)
|
||||||
DEDUP_TTL_MS=300000
|
DEDUP_TTL_MS=300000
|
||||||
|
|
||||||
|
# Timeout en milisegundos para la llamada a la API de Anthropic (evita que se
|
||||||
|
# quede colgada indefinidamente si no hay salida a internet)
|
||||||
|
FIRE_TIMEOUT_MS=10000
|
||||||
|
|||||||
15
server.js
15
server.js
@@ -10,6 +10,7 @@ const {
|
|||||||
ROUTINE_ID,
|
ROUTINE_ID,
|
||||||
ROUTINE_TOKEN,
|
ROUTINE_TOKEN,
|
||||||
DEDUP_TTL_MS = String(5 * 60 * 1000),
|
DEDUP_TTL_MS = String(5 * 60 * 1000),
|
||||||
|
FIRE_TIMEOUT_MS = String(10 * 1000),
|
||||||
} = process.env;
|
} = process.env;
|
||||||
|
|
||||||
for (const [name, value] of Object.entries({
|
for (const [name, value] of Object.entries({
|
||||||
@@ -29,14 +30,16 @@ const ANTHROPIC_BETA_HEADER = 'experimental-cc-routine-2026-04-01';
|
|||||||
const ANTHROPIC_VERSION = '2023-06-01';
|
const ANTHROPIC_VERSION = '2023-06-01';
|
||||||
const MAX_TEXT_LENGTH = 65536;
|
const MAX_TEXT_LENGTH = 65536;
|
||||||
const dedupTtlMs = Number(DEDUP_TTL_MS);
|
const dedupTtlMs = Number(DEDUP_TTL_MS);
|
||||||
|
const fireTimeoutMs = Number(FIRE_TIMEOUT_MS);
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
app.disable('x-powered-by');
|
app.disable('x-powered-by');
|
||||||
|
|
||||||
function log(level, fields) {
|
function log(level, fields) {
|
||||||
const line = { level, timestamp: new Date().toISOString(), ...fields };
|
const line = { level, timestamp: new Date().toISOString(), ...fields };
|
||||||
const out = level === 'error' ? console.error : console.log;
|
// Todo por stdout a propósito: así un solo `tail`/log driver ve info y
|
||||||
out(JSON.stringify(line));
|
// error juntos, sin depender de que algo separe stdout/stderr aguas abajo.
|
||||||
|
console.log(JSON.stringify(line));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constant-time string comparison. Returns false (without leaking length
|
// Constant-time string comparison. Returns false (without leaking length
|
||||||
@@ -141,6 +144,8 @@ function buildText(event, payload) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function fireRoutine(text, deliveryId, event) {
|
async function fireRoutine(text, deliveryId, event) {
|
||||||
|
const controller = new AbortController();
|
||||||
|
const timeout = setTimeout(() => controller.abort(), fireTimeoutMs);
|
||||||
try {
|
try {
|
||||||
const res = await fetch(ANTHROPIC_FIRE_URL, {
|
const res = await fetch(ANTHROPIC_FIRE_URL, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -151,6 +156,7 @@ async function fireRoutine(text, deliveryId, event) {
|
|||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
body: JSON.stringify({ text }),
|
body: JSON.stringify({ text }),
|
||||||
|
signal: controller.signal,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
@@ -165,7 +171,10 @@ async function fireRoutine(text, deliveryId, event) {
|
|||||||
}
|
}
|
||||||
log('error', fields);
|
log('error', fields);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log('error', { deliveryId, event, result: 'fetch_failed', error: err.message });
|
const reason = err.name === 'AbortError' ? 'timeout' : err.message;
|
||||||
|
log('error', { deliveryId, event, result: 'fetch_failed', error: reason });
|
||||||
|
} finally {
|
||||||
|
clearTimeout(timeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user