2.0 KiB
Prompt
Get PR #490 primed and landed. Continue after rebasing, but keep the review and fix pass focused.
Response
The mutable {} default is safe because msgspec.Struct creates a fresh dictionary per instance. A separate concurrency defect remains: two tasks can call receive() through one BroadcastReceiver, and the second call overwrites the only _wait_scope. Closing that receiver can then leave the first task blocked indefinitely.
git diff -- tractor/trionics/_broadcast.py tests/test_task_broadcasting.py
Added a per-receiver in-progress guard that raises trio.BusyResourceError for an overlapping receive. Added a regression test that blocks the first receive, verifies the second call is rejected, and releases the source to prove the first call still works. The complete broadcast test file passes: 28 tests in 4.57 seconds.
Follow-up prompt
Clarify that the guard is per receiver, preserves lossless consumer semantics, and document the contract on the public method, type, and surrounding guide.
Follow-up response
git diff -- tractor/trionics/_broadcast.py docs/guide/streaming.rst
Documented that each BroadcastReceiver owns one logical cursor, each concurrent consumer needs its own subscribed receiver, overlapping calls on one handle raise BusyResourceError, and strict lag handling never skips values silently.
Second follow-up prompt
Explain that the polling loop waits until the background receive is blocked before making the concurrent call, and include the first consumer task’s runtime information in the busy exception.
Second follow-up response
Replaced the boolean guard with the active trio.lowlevel.Task, added its name and representation to BusyResourceError, named the fixture task for a deterministic assertion, and documented the checkpoint-loop interleaving directly above the poll.