From 56aab8dfd0ef06bfb6c29d78b332fbe9c65cb900 Mon Sep 17 00:00:00 2001 From: Brent Rager Date: Tue, 2 Jun 2026 18:07:06 -0400 Subject: [PATCH] SMOODEV-1527: Fix eso-refresher keep-alive (don't unref the interval) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- .changeset/eso-refresher-keepalive.md | 5 +++++ src/eso-refresher/index.ts | 8 ++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 .changeset/eso-refresher-keepalive.md diff --git a/.changeset/eso-refresher-keepalive.md b/.changeset/eso-refresher-keepalive.md new file mode 100644 index 0000000..8cbca4e --- /dev/null +++ b/.changeset/eso-refresher-keepalive.md @@ -0,0 +1,5 @@ +--- +'@smooai/config': patch +--- + +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. diff --git a/src/eso-refresher/index.ts b/src/eso-refresher/index.ts index 47e26e3..62e80d7 100644 --- a/src/eso-refresher/index.ts +++ b/src/eso-refresher/index.ts @@ -147,8 +147,12 @@ export interface EsoRefresherHandle { function defaultScheduler(fn: () => void, ms: number): { clear: () => void } { const t = setInterval(fn, ms); - // Don't keep the event loop alive solely for the timer in tests/CLI teardown. - if (typeof t.unref === 'function') t.unref(); + // SMOODEV-1527: do NOT unref() — the interval is what keeps the daemon's + // event loop alive. A pending `await new Promise(() => {})` in main() does + // NOT hold the loop open by itself, so unref'ing here let the process exit 0 + // right after the initial mint → CrashLoopBackOff. Tests inject their own + // scheduler, so this only affects the real CLI/sidecar (where we WANT it + // to keep running). `stop()` still calls clear() for clean shutdown. return { clear: () => clearInterval(t) }; }