fix(coach/trigger-tuner): crash after ~1h — runOnce is sync, not a Promise
The live bot died overnight with:
TypeError: runOnce(...).catch is not a function
at trigger-tuner.js:42 → [supervisor] child exited code=1
attach() wrapped the timer body as `runOnce().catch(...)` but
runOnce() returns a plain {ok, flagged, ...} object (pure SQL, no
await). The first tuner tick (60min after spawn) threw → killed the
whole bot process. Never surfaced before because the bot rarely ran
uninterrupted for a full hour during development.
Fix: guard the synchronous call with try/catch, matching how
persona/chatter.js already does its sync tick. (postmortem.drainOnce
and reflect.runOnce ARE async, so their .catch is correct — audited.)
Regression test added: captures the setInterval callback and invokes
it synchronously, asserting it does not throw.
Tests: 397 green.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -39,7 +39,15 @@ export function attach({ intervalMs = TUNE_INTERVAL_MS } = {}) {
|
||||
return;
|
||||
}
|
||||
_timer = setInterval(() => {
|
||||
runOnce().catch((e) => warn("tuner", `tick err: ${e?.message ?? e}`));
|
||||
// runOnce is synchronous (pure SQL, no await) — must NOT call
|
||||
// .catch on its plain-object return. A try/catch here is the
|
||||
// correct guard. (This exact bug crashed the live bot after
|
||||
// ~1h uptime when the first tuner tick fired.)
|
||||
try {
|
||||
runOnce();
|
||||
} catch (e) {
|
||||
warn("tuner", `tick err: ${e?.message ?? e}`);
|
||||
}
|
||||
}, intervalMs);
|
||||
_timer.unref?.();
|
||||
info("tuner", `attached; tune every ${Math.round(intervalMs / 60000)} min`);
|
||||
|
||||
Reference in New Issue
Block a user