Problem statement
Design a worker dispatch registry: a component where handlers register for named job types and each submitted job is routed to its handler and run concurrently, under a per-type concurrency limit. It is typed routing, distinct from a generic thread pool and from a broadcast event bus, one job goes to exactly one handler.
Operating context. One process. At startup, handlers register under a job-type key, each with a maximum concurrency. A caller submits a job carrying its type; the registry looks up the handler and schedules it on a worker, respecting the per-type cap, while excess jobs queue until a slot frees. Handlers can be deregistered: in-flight jobs finish but new submissions for that type are refused. Submits and registrations happen concurrently.
Out of scope. Distributed job routing or message brokers, the thread-pool internals (assume an executor is injected), retry/backoff policy, persistence of the job queue, and priority scheduling within a single type.
What to produce. The class model (the registry, a handler registration, the per-type dispatch/concurrency gate, and the job envelope), the public API, and two state machines, a job (submitted, queued, running, done or failed) and a registration (active, draining, removed). Be explicit about how routing plus the per-type limit stay correct under concurrent submit and register, and how a submit that races a deregister is never routed to a half-removed handler.
Functional requirements
- Register a handler for a job type with a per-type maximum concurrency, rejecting a duplicate type.
- submit(job) routes the job to its type's handler and schedules it on a worker.
- Enforce the per-type concurrency cap so excess jobs queue until a running slot frees.
- Deregister a handler, refusing new submissions for that type while letting in-flight jobs finish.
- Report the per-type in-flight and queued counts.
- Reject or signal failure for a submission whose type has no registered handler.
Non-functional requirements
- Routing invariant: a job runs on exactly the handler registered for its type, or fails cleanly if none exists.
- The per-type in-flight count never exceeds its configured cap under concurrent submits.
- Registry mutations are safe against concurrent submits, so no job is routed to a half-removed handler.
- submit and lookup are O(1) on average via a type-to-handler map.
- The executor is injected and pluggable; the registry owns routing, not thread management.
- Deterministically testable with a synchronous executor, so routing and the cap are observable without real threads.
Topics
- System Design LLD
- Concurrency Dispatch
- Concurrency Thread-Safety
- Patterns Registry
- Oop Interface-Design