fix(pulse/imessage): block startIMessage until stop, ending supervisor restart loop#1277
Open
janrenz wants to merge 1 commit into
Open
fix(pulse/imessage): block startIMessage until stop, ending supervisor restart loop#1277janrenz wants to merge 1 commit into
janrenz wants to merge 1 commit into
Conversation
…r restart loop startIMessage sets up the setInterval poll timer and then returns immediately. The supervisor in pulse.ts treats that return as a clean exit and re-invokes the module every 10 seconds, where the running-flag guard catches the second call and logs 'iMessage module already running, ignoring start request'. The poll loop itself works correctly throughout — this is pure log spam, plus an unnecessary every-10s call overhead — but it's the same shape of bug the telegram module solved by awaiting bot.start() (see modules/telegram.ts:344-348 comment). Fix mirrors that pattern: at end of startIMessage, await a Promise whose resolve() is captured in a module-scoped stopResolve. stopIMessage releases it after clearing the timer and persisting the cursor. With this, supervisor sees startIMessage as long-running and stops the 10s restart cycle. Reproduces on any healthy install with Full Disk Access granted and an allowed_handles list. Observable in pulse-stdout.log as alternating 'imessage exited cleanly, restarting in 10s' / 'iMessage module already running, ignoring start request' lines every 10s.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Pulse/modules/imessage.ts:startIMessage()sets up the SQLite pollsetIntervaland then returns immediately. The supervisor inpulse.ts:supervise()treats the resolved promise as a clean exit:Every 10 seconds it re-invokes
startIMessage(), where therunningguard catches the duplicate call and emits a warn.pulse-stdout.logends up with this pattern forever after the module successfully starts:The poll itself works correctly throughout — message ingestion isn't affected — but every 10s there's needless work plus log noise that drowns out real events.
Why this pattern is unique to imessage
modules/telegram.ts:345already documents the same shape and how it avoided the bug:iMessage uses a bare
setIntervalinstead of an awaited polling primitive, so the same protection was missing.Fix (+15 lines, one file)
let stopResolve: (() => void) | null = nullstartIMessage: aftersetInterval(...)and thepolling every Xmslog,await new Promise<void>(resolve => { stopResolve = resolve })stopIMessage: afterrunning = false, release the captured resolverWith this, the supervisor sees
startIMessageas long-running. The 10s restart cycle goes away.Repro
bun.PULSE.toml[imessage]enabled with at least oneallowed_handlesentry.tail -f ~/.claude/PAI/Pulse/logs/pulse-stdout.log | grep imessageshows the alternating start/exited lines every 10s.After fix: a single
iMessage module started→polling every 3000msthen silence (until a real inbound message or shutdown).Notes
stopIMessage()already idempotent onrunning=false; the new resolver release follows the same guard.telegrammodule path where the modulereturns early on missing bot token — that produces the same 10s log spam. Out of scope for this PR; happy to follow up.Found while wiring up iMessage on a fresh v5.0.0 install. Local fix verified: 0
already runningwarnings over 25s observation window after Pulse restart, vs. 3 in the same window before the fix.