Repository navigation
Wait for a stopped polling loop before a restart starts a new one - #55
Merged
Merged
Conversation
…e [patch] RestartCoreAsync only stopped and awaited the old PollingTask when ShouldPoll was still true. After Stop(), the old loop could still be inside its delay; the restart set ShouldPoll again, so the old loop woke up and kept running beside the new one, doubling the action rate. Each further Stop/Restart pair could add another orphaned loop. The restart now always stops and awaits the previous loop. TryRun also checks and claims ActionTask under the lock, so two callers can never both start the action. Fixes #52 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TX4nouJvSXNs7eSvDP13qU
|
This was referenced Sep 27, 2026
matt-edmondson
deleted the
claude/intervalaction-52-restart-after-stop
branch
September 27, 2026 15:05
This was referenced Sep 28, 2026
This was referenced Oct 5, 2026
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.



Fixes #52
What was wrong
RestartCoreAsyncstopped and awaited the oldPollingTaskonly whenShouldPollwas still true. AfterStop(),ShouldPollis already false, but the old loop can still be insideTask.Delay(PollingInterval). The restart skipped the wait, setShouldPoll = trueand started a second loop. When the old loop woke, it sawShouldPoll == trueand kept going with nothing referencing it. The action then ran at double rate, and each laterStop()/Restart()pair could leak another loop.Change
RestartCoreAsyncnow always callsStop()and awaits the previousPollingTaskbefore it setsShouldPollagain.Stop()is idempotent, and awaiting an already-completed task is free, so the path where the loop was still polling is unchanged.TryRunnow checks and claimsActionTaskwhile holdingLock, as the issue triage suggested. Two callers can then never both see the slot empty and each start the action.Lockis not held while the action runs; the action task takes it on its own thread, only briefly, to setLastRunTime.Tests
RestartRightAfterStopLeavesOnlyOnePollingLoop. It callsStart(), waits 50 ms, then callsStop()and immediatelyawait RestartAsync(). It asserts that the pre-restartPollingTaskhas completed and has been replaced. Over 10 polling intervals, it also asserts that the action ran no more often than a single loop allows. The bound comes from a measured stopwatch rather than a fixed count, so a slow runner doesn't make it flaky.🤖 Generated with Claude Code
https://claude.ai/code/session_01TX4nouJvSXNs7eSvDP13qU
Generated by Claude Code