Ingress behaviours wrapped around every processor — the queue arm of the
transport-neutral behaviour chain shared with the websocket, scheduler,
and messaging plugins (IIngressBehavior in @setu-ts/common).
Each behaviour observes an IngressContext carrying kind: 'queue', the
job name as name, the delivered IJob as payload, and attempt
equal to IJob.attempts, and runs in declared order ahead of the
processor. A behaviour that returns without calling next()
short-circuits: the processor never sees the job and the job is
acknowledged. A behaviour that throws follows the processor's own failure
path — requeue with backoff, and ProcessOptions.onFailed plus the
dead-letter on the final attempt. Every processor registration is
wrapped, imperative process() calls included, so a mixed application
cannot leave a handler unchained.
With no behaviours configured, dispatch is byte-identical to the pre-chain behaviour: the processor is handed the job directly, with no chain allocated.
When an entry is a FACTORY, dispatch is HELD until onInit has resolved
the whole chain, so nothing reaches a handler through a partial one. That
gate covers every registration — this plugin's declared entries and any a
later plugin makes imperatively through the resolved capability — which
is why no registration's timing has to change. It is released once and
costs nothing thereafter.
Instance entries are handed to the service at register(); factory
entries are resolved in the onInit phase and a throwing factory rejects
start() naming QueuePlugin({ behaviors }) and the entry's index in
THIS declared array.