Skip to content

Conversation

@Meijuh
Copy link

@Meijuh Meijuh commented Dec 24, 2025

This PR adds support for four non-blocking Resilience4j-style semaphore bulkheads with an adaptive concurrency limit (determined by a provided Limiter). Tasks are put on Queue(s) and then dispatched by calling threads or threads that complete dispatched tasks.

There are four bulkhead implementations:

  1. RoundRobinDispatcherBulkhead: a parallel dispatcher for unrestricted contexts, does not preserve FIFO order.
  2. FifoParallelDispatcherBulkhead: a parallel dispatcher for Void contexts; maintains FIFO order.
  3. FifoSerialDispatcherBulkhead: a serial dispatcher for unrestricted contexts preserving FIFO order.
  4. EnumContextPartialFifoOrderBulkhead: a parallel dispatcher for Enum contexts preserving a partial FIFO order (i.e., FIFO per context instance is maintained).

The work on this PR is not complete. In order to complete it, I would like to know if you are willing to maintain it, and whether you feel the contribution works as intended and is generally useful. One key aspect in the review should be whether there is guaranteed progress dispatching (e.g., pertaining to maxDispatchPerCall).

I think the contribution is useful as the current code base either provides blocking behavior (with the usual downsides), or non-queueing behavior that could cause high tail latencies due to required retries that worsen the execution order of tasks. This work addresses both concerns.

ToDo:

  • Add sensible defaults to builders, e.g., AbstractDispatcherBulkhead.AbstractBuilder.
  • Add monitoring capabilities; I can do this after Add Micrometer support #226 is merged.
  • Add more unit tests.
  • Potentially add simulations (using JUnit, like BlockingAdaptiveExecutorSimulation).
  • Extend the README.md with usage information.
  • Apply Checkstyle formatting (the current checkstyle.xml config file is too old for me to run in IDEA).
  • Add more Javadoc, especially to Builder methods.
  • Ideally, interfaces such as Bulkhead are located in an api module, (e.g., in com.netflix.concurrency-limits:concurrency-limits-api). For consistency, I put it in the core module, moving all interfaces to a new api module might be a good idea. And also, this might be possible in a backwards compatible way by setting a Gradle api dependency on every subproject that uses the new api subproject?
  • Also ideally, this project is migrated to Java > 8 so that I can implement deadlines, instead of merely mentioning timeouts in the Javadoc of Bulkhead#executeCompletionStage(...).
  • I've added an interface LowCardinalityContextBulkhead, and one implementation EnumContextPartialFifoOrderBulkhead; it might make sense to add a generic implementation for any context type with low cardinality, based on a ConcurrentMap, that creates bulkheads on-the-fly.

If you think there is a use case for a LIFO backlog, please let me know; I could refactor the code a bit and implement one with a deque.

@Meijuh Meijuh force-pushed the bulkhead branch 2 times, most recently from 47b28d3 to 43db602 Compare December 24, 2025 14:25
@Meijuh Meijuh changed the title Add non-blocking FIFO dispatcher bulkhead Add non-blocking dispatcher bulkheads Dec 25, 2025
@Meijuh Meijuh changed the title Add non-blocking dispatcher bulkheads Add non-blocking bulkheads Dec 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant