When Floodgate.withValue owns the recursive lock, events enqueued in parallel might be left unprocessed until another enqueue attempt.
This is because Floodgate.process(_:for:) assumes that, when the call is reentrant, the lock owner is already running an event drain loop. This holds true when Floodgate.process(_:for:) recursively calls itself. But this doesn't hold true when Floodgate.process(_:for:) is the indirect caller of Floodgate.process(_:for:).
This PR refactored the code path, and makes sure that all reducerLock holder fulfills their obligation to drain the event queue after having held the lock.
Included a test case that fails on develop and 2.0.0-beta1.
When
Floodgate.withValue
owns the recursive lock, events enqueued in parallel might be left unprocessed until another enqueue attempt.This is because
Floodgate.process(_:for:)
assumes that, when the call is reentrant, the lock owner is already running an event drain loop. This holds true whenFloodgate.process(_:for:)
recursively calls itself. But this doesn't hold true whenFloodgate.process(_:for:)
is the indirect caller ofFloodgate.process(_:for:)
.This PR refactored the code path, and makes sure that all
reducerLock
holder fulfills their obligation to drain the event queue after having held the lock.Included a test case that fails on
develop
and2.0.0-beta1
.