Solid arrows below are the message travelling forward through the pipeline, in priority order; dashed arrows are the result on its way back. A result doesn't exist until MessageHandlerMiddleware resolves the handler, asks the wired strategy which method to call, and invokes it. The result returns directly to the caller from there. Notice no dashed arrow ever touches earlier middleware, since it has no part on that side.

GitHub renders Mermaid diagrams as scalable SVG, so you can zoom in (browser zoom, or pinch/scroll on the diagram) for a closer look. Each diagram below is also wrapped in a collapsible <details> block and laid out top-to-bottom so it stays readable without needing to scroll sideways.

Overview

Expand/collapse diagram
flowchart TD
    App([Application]) -->|handle message| Bus[MessageBus]
    Bus -->|handle message| Pipe[MiddlewarePipe]
    Pipe -->|process message, next| MW[Registered middleware]
    MW -->|next.handle message| HandlerMW[MessageHandlerMiddleware]
    HandlerMW -->|resolve message| Resolver[MessageHandlerResolver]
    HandlerMW -->|handlerMethod message| Strategy[Strategy]
    HandlerMW -->|invoke method| Handler[Command/QueryHandler]
    Handler -.->|Result| HandlerMW
    HandlerMW -.->|Result| Pipe
    Pipe -.->|Result| Bus
    Bus -.->|Result| App

MessageHandlerMiddleware is just the last entry in the pipeline (lowest default priority), so any middleware you register runs before the handler is resolved.

Custom middleware example

Using the LoggingMiddleware from Writing custom middleware, registered at priority 10 (above MessageHandlerMiddleware's default priority of 1):

Expand/collapse diagram
flowchart TD
    Bus[MessageBus] -->|process CreateUser, next| Log[LoggingMiddleware<br/>priority 10]
    Log -->|next.handle message| HandlerMW[MessageHandlerMiddleware<br/>priority 1, runs last]
    HandlerMW -->|resolve + handlerMethod| Resolver[Resolver + Strategy]
    HandlerMW -->|invoke method| Handler[CreateUserHandler]
    Handler -.->|CommandResult| HandlerMW
    HandlerMW -.->|CommandResult| Bus