◐ Shell
clean mode source ↗

Fix reactive data loader hanging on backpressured publishers (#273) by zenios · Pull Request #279 · graphql-java/java-dataloader

@zenios

…-java#273)

The reactive subscribers (`AbstractBatchSubscriber` and friends) requested
`keys.size()` from the upstream publisher exactly once in `onSubscribe` and
then waited for `onComplete` to finalise the batch.

A reactive publisher only emits while it has outstanding demand. So a
publisher that emits values lazily as more demand arrives - for example one
that emits an entry not matching any requested key before the entry that
does - consumes that single window of demand and then blocks. The matching
value is never requested, the per-key future never completes, and the data
loader hangs forever.

This change makes the subscribers manage demand properly:

  * track the outstanding demand and re-request another window whenever it
    drains to zero, repeating until the publisher completes or errors;
  * once a result has been received for every key there is nothing left to
    wait for, so cancel the upstream subscription and complete ourselves
    rather than blocking on a publisher that may never call `onComplete`.

Adds `ReactiveBackpressureTest` reproducing the hang for both the list and
mapped publisher data loaders; both tests time out against the old code and
pass with the fix.