mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-07-30 19:46:17 +00:00
drainPeerInitiatedUniStreamsIntoBlackHole_keeps_connection_alive passed in isolation but flaked under parallel load with the audit-4 #3 "slow consumer overflowed incoming channel" teardown. Root cause: the test ran the black-hole drainer on the shared Dispatchers.Default pool. The drainer only has to keep the 64-deep per-stream incomingChannel drained, but when the rest of the JVM test suite saturates every Default worker thread the drainer coroutine can be denied a scheduling slot long enough for the synchronous feed loop to push more than 64 chunks ahead of it, tripping the slow-consumer teardown. The fixed-delay yields (delay(1) every 16 chunks) do not help when all pool threads are pinned. Fix: run the drainer on the runBlocking coroutine's own single-threaded event loop (CoroutineScope(coroutineContext + SupervisorJob())) and pace the feed loop with cooperative yield() instead of wall-clock delays. Each yield deterministically runs the drainer's queued channel-receive continuation before the producer resumes, so the buffer never approaches its bound regardless of machine load. The drain contract under test (parser trySend -> incomingChannel -> collect -> discard) is exercised identically; only the scheduling is pinned. Verified with a temporary reproduction that pins every Default worker thread: the old Default-scheduled drainer overflows to CLOSED while the confined drainer stays CONNECTED under the same saturation. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MGZt6D298kGv2XgAi3Uuaj