Skip to content

Commit 4aed829

Browse files
brentragerclaude
andauthored
SMOODEV-1527: eso-refresher keep-alive — don't unref the interval (land stranded fix) (#125)
* SMOODEV-1527: Fix eso-refresher keep-alive (don't unref the interval) The refresher exited 0 right after its initial mint+write — it unref'd the interval timer, and the 'await new Promise(() => {})' keep-alive in main() does NOT hold Node's event loop open on its own. Result: the sidecar CrashLoopBackOff'd (re-minting on each restart, which masked it, but it's not a stable daemon). Don't unref the production interval — it's what keeps the loop alive. Tests inject their own scheduler, so they're unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * SMOODEV-1527: fix stale keep-alive comment at the main() hold point Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LE7V35vzRiHyxBFE8wAxb4 --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent f2007b1 commit 4aed829

2 files changed

Lines changed: 13 additions & 3 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@smooai/config': patch
3+
---
4+
5+
SMOODEV-1527: Fix the eso-refresher exiting immediately after its initial mint (it `unref()`'d the interval timer, and a pending `await new Promise(() => {})` doesn't hold Node's event loop open — so the process exited 0 → CrashLoopBackOff). The production interval now keeps the daemon alive; tests inject their own scheduler so they're unaffected.

src/eso-refresher/index.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,12 @@ export interface EsoRefresherHandle {
147147

148148
function defaultScheduler(fn: () => void, ms: number): { clear: () => void } {
149149
const t = setInterval(fn, ms);
150-
// Don't keep the event loop alive solely for the timer in tests/CLI teardown.
151-
if (typeof t.unref === 'function') t.unref();
150+
// SMOODEV-1527: do NOT unref() — the interval is what keeps the daemon's
151+
// event loop alive. A pending `await new Promise(() => {})` in main() does
152+
// NOT hold the loop open by itself, so unref'ing here let the process exit 0
153+
// right after the initial mint → CrashLoopBackOff. Tests inject their own
154+
// scheduler, so this only affects the real CLI/sidecar (where we WANT it
155+
// to keep running). `stop()` still calls clear() for clean shutdown.
152156
return { clear: () => clearInterval(t) };
153157
}
154158

@@ -245,6 +249,7 @@ export async function main(): Promise<void> {
245249
process.on('SIGTERM', () => shutdown('SIGTERM'));
246250
process.on('SIGINT', () => shutdown('SIGINT'));
247251

248-
// Keep alive — the interval timer is unref'd, so hold the loop open explicitly.
252+
// The ref'd interval (SMOODEV-1527) is what actually holds the event loop
253+
// open; this pending promise only keeps main() from returning.
249254
await new Promise<never>(() => {});
250255
}

0 commit comments

Comments
 (0)