We hit the ClosedQueueError from #5654 on 2.6.5, which includes the #5656 fix - so it looks like the fix doesn't cover at least one code path. In our case the error isn't harmless: losing the ensure-block push means the run's accounting never balances, and the whole request hangs indefinitely.
Versions:
- graphql 2.6.5
- async 2.42.0
- Rails 8.1.3 with
config.active_support.isolation_level = :fiber
- Ruby 3.4, unicorn (single-threaded workers)
A fan-out-heavy query spawns ~40 concurrent source/job tasks for us, which starves the ActiveRecord connection pool and produces 5s ActiveRecord::ConnectionTimeoutErrors inside source fetches. A task that gets woken from one of those waits after its round's queues have already been closed then fails the run.finished_tasks.push($! || task) in the ensure of spawn_source_task:
Async::Queue::ClosedError: Cannot enqueue items to a closed queue!
async-2.42.0/lib/async/queue.rb:65 in 'Async::Queue#push'
graphql-2.6.5/lib/graphql/dataloader/async_dataloader.rb:351 in 'block (2 levels) in GraphQL::Dataloader::AsyncDataloader#spawn_source_task'
async-2.42.0/lib/async/task.rb:224 in 'block in Async::Task#run'
After that the run never completes - the root task waits forever and the reactor sits idle. We watched it for over two minutes with periodic backtrace dumps of the main thread, all identical:
async-2.42.0/lib/async/scheduler.rb:456:in 'IO::Event::Selector::EPoll#select'
...
async-2.42.0/lib/kernel/sync.rb:30:in 'Kernel#Sync'
graphql-2.6.5/lib/graphql/dataloader/async_dataloader.rb:197:in 'GraphQL::Dataloader::AsyncDataloader#run'
graphql-2.6.5/lib/graphql/execution/interpreter.rb:86:in 'block in GraphQL::Execution::Interpreter.run_all'
The race is timing-dependent: the exact same query against the same data sometimes completes in ~5s with the connection timeouts collected as field errors, and sometimes wedges as above. In production (unicorn with a 30s worker timeout) the wedged requests get killed silently, which is what we were originally debugging.
I don't have a minimal script, but the reproduction shape is: any query whose source fan-out exceeds the AR pool size produces late-finishing tasks via checkout timeouts, and each late task rolls the dice on this race - it triggers within a couple of attempts on our data. Happy to run patches or provide more diagnostics against our reproduction.
Pinning back to 2.6.3 avoids the problem entirely (verified A/B on the same environment).
We hit the
ClosedQueueErrorfrom #5654 on 2.6.5, which includes the #5656 fix - so it looks like the fix doesn't cover at least one code path. In our case the error isn't harmless: losing theensure-block push means the run's accounting never balances, and the whole request hangs indefinitely.Versions:
config.active_support.isolation_level = :fiberA fan-out-heavy query spawns ~40 concurrent source/job tasks for us, which starves the ActiveRecord connection pool and produces 5s
ActiveRecord::ConnectionTimeoutErrors inside source fetches. A task that gets woken from one of those waits after its round's queues have already been closed then fails therun.finished_tasks.push($! || task)in theensureofspawn_source_task:After that the run never completes - the root task waits forever and the reactor sits idle. We watched it for over two minutes with periodic backtrace dumps of the main thread, all identical:
The race is timing-dependent: the exact same query against the same data sometimes completes in ~5s with the connection timeouts collected as field errors, and sometimes wedges as above. In production (unicorn with a 30s worker timeout) the wedged requests get killed silently, which is what we were originally debugging.
I don't have a minimal script, but the reproduction shape is: any query whose source fan-out exceeds the AR pool size produces late-finishing tasks via checkout timeouts, and each late task rolls the dice on this race - it triggers within a couple of attempts on our data. Happy to run patches or provide more diagnostics against our reproduction.
Pinning back to 2.6.3 avoids the problem entirely (verified A/B on the same environment).