Skip to content

Middleware ​

Message read middleware runs between the bus reading a message from the transport and dispatching it to handlers. It wraps the handling of each message, so it can run code before and after it. This page shows two common uses.

A middleware is a function that gets the message as the transport read it and a next function. Calling next() runs the next middleware, and then the handlers. Register middleware with withMessageReadMiddleware(); several run in the order they're registered. It also runs for messages passed to a receiver.

Timing messages ​

Telemetry such as AWS X-Ray, New Relic or Datadog can profile message handling with middleware. That helps find the messages that take longest to handle, and would benefit from tuning.

ts
const timeMessages: Middleware<TransportMessage<unknown>> = async (
  message,
  next
) => {
  const start = performance.now()
  // Dispatches the message to the next middleware, and then its handlers
  await next()
  console.log('Message handled', {
    messageName: message.domainMessage.$name,
    durationMs: Math.round(performance.now() - start)
  })
}

const bus = Bus.configure()
  .withMessageTypes(messageTypes)
  .withMessageReadMiddleware(timeMessages)
  .build()

Adding context to logs ​

Middleware can also give every log written while handling a message the context of that message, such as its correlation id. Run next() inside an AsyncLocalStorage, and have your logger read the store:

ts
interface LogContext {
  correlationId: string | undefined
  messageName: string
}

/**
 * Holds the context of the message being handled, for the logger to add to
 * every log written while handling it
 */
export const logContext = new AsyncLocalStorage<LogContext>()

Bus.configure().withMessageReadMiddleware(async (message, next) =>
  logContext.run(
    {
      correlationId: message.attributes.correlationId,
      messageName: message.domainMessage.$name
    },
    next
  )
)

Outside middleware, code that a handler calls can read the message being handled with bus.getHandlingContext().

See also ​

Released under the MIT License.