Repository navigation
#45 fix: liveness in-flight means the post hasn't returned, not that the thread is alive - #48
Merged
Merged
Conversation
…e next tick
Every check-in thread is held after its target returns: the next tick skipped
("previous check-in still in flight"), the CI flake reproduced without sleeps.
A thread that fails to start must not leave the heartbeat skipping for good.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d is alive The thread clears an explicit marker before handing its result to the loop, so a tick that follows at once no longer sees a finishing thread. Only the thread clears it, never the timeout path: a post cut off by asyncio.timeout still counts as in flight until it returns (#39 trap 1). A failed start() clears it too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… returns Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… owns Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 10, 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.
Refs #45 (closed after deploy and the live check).
Cause. A check-in thread hands its result to the loop (
call_soon_threadsafe) and then exits. The tick could finish, and a following tick that awaits nothing (stale/skipped) let the next one run, while that thread was still alive:is_alive()→ spurious skip. Red onmainthree times in two days.Fix (
src/processor/liveness.py): an explicit_in_flightmarker replaces_thread.is_alive().start(); cleared by the thread oncepostreturns, beforecall_soon_threadsafe;asyncio.timeoutstays in flight until it returns, so threads still never pile up (Liveness check-in for processor run (co-status monitor co-processor-live) #39 trap 1);start()clears it, or every later tick would skip.Tests (
tests/test_liveness.py):test_a_finished_check_in_whose_thread_lingers_does_not_skip_the_next_tick: holds each check-in thread after its target returns. Deterministic, no sleeps. Red before the fix (1 == 2, the skip warning), green after.test_a_thread_that_fails_to_start_does_not_wedge_the_heartbeat: guards the marker (mutation-checked: fails without theexceptclear).test_a_hung_status_is_cut_off_and_the_next_tick_is_skipped(existing) still passes: a post past the timeout still skips the next tick.tests/test_consumer.pyintegration test now assertsbeat._in_flight.Verification.
uv run pytest: 589 passed, 6 skipped (unreadable-secret denials, expected in a worktree).uv run pytest -m integration: 56 passed.tests/test_liveness.py×100 under 4 CPU burners on 2 vCPU: 100/100.After merge:
scripts/deploy.sh(touchessrc/). Live check:startinghasliveness: on …, thenliveness check-inwith no WARNING over the next ticks,co-processor-livestaysok.🤖 Generated with Claude Code