Pipeline
Overview
Section titled “Overview”The bus’s pipeline is the four-stage chain that every message passes through on its way out (outgoing) and on its way back in (beforeConsuming, afterConsuming, onConsumedSuccessfully). You add Filter and Middleware registrations to stages via bus.use(stage, ...items); items run in the order described below.
Import
Section titled “Import”import type { PipelineStage } from '@serviceconnect/core';PipelineStage
Section titled “PipelineStage”export type PipelineStage = | 'outgoing' | 'beforeConsuming' | 'afterConsuming' | 'onConsumedSuccessfully';'outgoing'— runs before a message leaves the producer. Stamp headers, redact bodies, refuse sends that violate policy. A filter returningStophere throwsOutgoingFiltersBlockedErrorat the call site.'beforeConsuming'— runs immediately before the handler. Reject unauthorised messages, set up logging context, time the handler. A filter returningStophere ends inbound processing for that envelope without invoking the handler.'afterConsuming'— runs after the handler returns or throws. Use atry/finallyin middleware to capture timing or errors regardless of outcome.'onConsumedSuccessfully'— runs only after a successful handler. Emit “processed” metrics, commit downstream side-effects that should not happen on failure.
use(stage: PipelineStage, ...items: Array<FilterRegistration | MiddlewareRegistration>): this;bus.use(...) appends one or more FilterRegistration / MiddlewareRegistration entries to the named stage. The call returns the bus so registrations can be chained. Items wrapped by asFilter and asMiddleware are accepted in any order.
Example
Section titled “Example”import { FilterAction, asFilter, asMiddleware } from '@serviceconnect/core';
bus.use( 'beforeConsuming', asMiddleware(async (context, next) => { const start = Date.now(); try { await next(); } finally { metrics.observe(Date.now() - start); } }), asFilter((envelope) => { return envelope.headers.tenant ? FilterAction.Continue : FilterAction.Stop; }),);The order in the call is middleware first, filter second — but the filter still runs first. If the tenant header is missing, the filter returns Stop and the timing middleware is skipped entirely.