feat(sync): let a producer report whether a publish can still land - #236
Merged
Conversation
A facade built on this crate has to answer "can I still publish?" for its own callers, and could not. `fork::generation` and `fork::forked_since` are crate-private, and asking the `AimDbHandle` is not open to an FFI door that keeps it behind a lock: answering while a shutdown holds that lock is how a caller's interpreter lock deadlocks against its own teardown. `SyncProducer::check()` answers it from the one component reachable without that lock, which is also why a publish never queues behind a shutdown. The body is `self.runtime()?.check()` — the check `set()` already performs, so this cannot report open while a publish would be refused. Two lines, because #235 had already put every route in behind a single check. What this commits to in semver is the question, not the mechanism. Exposing the generation pair instead would pin stamp-and-compare, which is the objection 2bcc5a3 raised when it withdrew them. The caller it wanted to design against now exists — weather-station's `StationHandle::is_closed` — and its requirement is specific: cheap, and never the mutex. The note on `fork::generation` claiming no such layer exists is corrected to point at the supported route. Tests: `check_reports_what_a_publish_would_find` covers the attached and detached arms. The forked-child test now asserts `check()` agrees with the two publishes beside it, which is the property a facade depends on. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The method is two lines; the doc comment, changelog entry and test comments around it were not. Each said the same thing three ways — that a facade cannot ask the handle because its shutdown holds the lock, and that publishing the generation pair would pin stamp-and-compare in semver. Kept one statement of each, at the place it belongs, and dropped the retellings. No behaviour change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GJYfHcnx2CSjmfKDrtoYCA
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.
Why
A facade built on
aimdb-synchas to answer "can I still publish?" for its own callers, and today it cannot.fork::generationandfork::forked_sinceare crate-private, and asking theAimDbHandleis not open to an FFI door that keeps it behind a lock — answering while a shutdown holds that lock is exactly how a caller's interpreter lock deadlocks against its own teardown. That is the lock-ordering rule the Python door established.So the question had no supported route.
aimdb-weather-mesh'sStationHandle::is_closedreached foraimdb_sync::fork::*instead, and stopped compiling when #235 made the module private.What
One method on
SyncProducer:Two lines, because #235 had already put every route in behind a single check.
Ok(()), orRuntimeShutdown/ForkedChild.It answers from the one component reachable without the handle's lock — which is also why a publish never queues behind a shutdown. And it is the check
set()already performs, not a second one beside it, so it cannot report open while a publish would be refused.On exposing
forkinsteadNot done, deliberately. What this commits to in semver is the question, not the mechanism. Publishing the generation pair would pin stamp-and-compare — the objection
2bcc5a3raised when it withdrew them mid-PR.That commit deferred the decision for want of a real caller to design against. The caller exists now, and its requirement is specific: cheap, and never the mutex.
check()is designed against it. The note onfork::generationclaiming no such layer exists is corrected to point at the supported route.Tests
check_reports_what_a_publish_would_find— usable while attached,RuntimeShutdownafter detach, and the same verdictset()reaches.check()agrees with the two publishes beside it. That agreement is the property a facade depends on.Verification
aimdb-sync: 58 tests green (was 57), plus--no-default-featuresand--features data-contracts.cargo fmt --checkand clippy clean on all three feature configurations.aimdb-weather-mesh(make spike-cpp), all four checks of the fork round green.Merge order
aimdb-dev/aimdb-weather-meshhas a companion PR that consumes this. This one lands first — that one does not compile without it.🤖 Generated with Claude Code