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.
Must do 6
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.