LiteBus
CatalogDispatch

Inbox In-Process Command Dispatch

  • ID: dispatch.inbox.in-process
  • Name: Inbox in-process command dispatch
  • Maturity: GA
  • Summary: Deserialize leased inbox envelopes and execute them through ICommandMediator.SendAsync in the same process as the processor.

What It Does

CommandInboxDispatcher implements IInboxDispatcher. It resolves the contract, unprotects and deserializes the payload, verifies the message implements ICommand, and sends through the command mediator. Mediation settings mark inbox replay via InboxExecutionContextKeys.IsInboxExecution and copy trace metadata from the envelope.

This is the default inbox dispatch path for monolithic services: accept into storage (or via ingress), then run handlers locally when the processor leases the row. No external broker is involved on the dispatch hop.

Packages

PackageRole
LiteBus.Inbox.Dispatch.InProcessDispatcher and registration
LiteBus.Commands.AbstractionsICommand, ICommandMediator
LiteBus.Inbox.AbstractionsIInboxDispatcher, envelopes

Requires

  • durable-core.inbox
  • mediator.commands (AddCommands before or with inbox)
  • runtime.contract-registry
  • dispatch.registration

Invariants

  • Only ICommand payloads succeed; other contract types throw InvalidOperationException.
  • Commands with results (ICommand<TResult>) must not be accepted into inbox (LB1004); dispatch assumes fire-and-forget command shape at accept time.
  • After-dispatch hook failures default to dead-letter even when dispatch succeeded.
  • At-least-once: handler must be idempotent or use accept-time idempotency keys.

Non-Goals

  • Does not publish to external brokers (use transport inbox dispatch).
  • Does not dispatch events through IEventMediator (planned separately; see Roadmap).
  • Does not return command results to the accept caller.

Public Surface

services.AddLiteBus(litebus =>
{
    litebus.AddCommands(commands => { /* handlers */ });
    litebus.AddInbox(inbox =>
    {
        inbox.EnableInboxProcessor();
        inbox.UseInProcessDispatch();
    });
});

InboxModuleBuilder.UseInProcessDispatch()

PackageLiteBus.Inbox.Dispatch.InProcess
RegistersCommandInboxDispatchModule to CommandInboxDispatcher

CommandInboxDispatcher.DispatchAsync(InboxEnvelope, CancellationToken)

PackageLiteBus.Inbox.Dispatch.InProcess
FlowResolve contract to unprotect to deserialize to verify ICommand to build CommandMediationSettings to ICommandMediator.SendAsync
Mediation items setInboxExecutionContextKeys.IsInboxExecution, MessageId, ContractName, and trace metadata via MessageProcessorDiagnostics.ApplyTraceMetadata

Optional constructor dependency: IInboxPayloadProtector for encrypted payloads.

CommandInboxDispatchModule.Build(IModuleConfiguration)

Registers IInboxDispatcher to CommandInboxDispatcher. Throws when a second dispatcher is already registered.

Observability

SignalWhen
litebus.inbox.processor.dispatch_durationProcessor histogram around DispatchAsync
litebus.inbox.processor.succeeded / failed / dead_letteredAfter dispatch and terminal persist
Command pipeline tracingFollows mediator instrumentation when command module registers handlers with diagnostic hooks; no inbox-dispatch-specific activity source
No transport send spanIn-process path does not touch the transport layer

Register inbox processor metrics through AddLiteBusInboxMetrics(). Command-specific spans depend on application or future mediator OpenTelemetry packages.

Analyzers

  • LB1004: Result commands cannot be accepted into inbox.
  • LB1007 / LB1017: Contract registration for handled command types.
  • LB1014: Processor without dispatcher.

Deep Docs

Test Coverage

Covered

Test methodProject
DispatchAsync_ShouldExecuteCommandThroughMediatorLiteBus.Inbox.UnitTests (Dispatch/InProcess/)
DispatchAsync_WhenMessageIsNotACommand_ShouldThrowInvalidOperationExceptionLiteBus.Inbox.UnitTests (Dispatch/InProcess/)
DispatchAsync_ShouldSetIsInboxExecutionAndCopyTraceMetadataLiteBus.Inbox.UnitTests (Dispatch/InProcess/)
DispatchAsync_WhenCancellationRequested_ShouldPassCancelledTokenToMediatorLiteBus.Inbox.UnitTests (Dispatch/InProcess/)
ProcessPendingAsync_ShouldExecuteScheduledCommandThroughPostgreSqlStoreLiteBus.Storage.IntegrationTests (PostgreSql/)
ProcessPendingAsync_WhenHandlerFails_ShouldMarkFailedWithVisibleAfterLiteBus.Storage.IntegrationTests (PostgreSql/)
NestedConfiguration_ShouldAcceptAndProcessCommandLiteBus.Inbox.UnitTests
AddInboxInProcessDispatcher_ShouldRegisterCommandInboxDispatcherLiteBus.Inbox.UnitTests (Dispatch/InProcess/)
AddInboxInProcessDispatcher_WhenCalledTwice_ShouldThrowLiteBus.Inbox.UnitTests (Dispatch/InProcess/)
AddInboxInProcessDispatcher_WhenAnotherDispatcherRegistered_ShouldThrowLiteBus.Inbox.UnitTests (Dispatch/InProcess/)

Untested

  • Full host-level behavior that branches on InboxExecutionContextKeys.IsInboxExecution.
  • Payload decryption branch with IInboxPayloadProtector.

Out-of-Scope

  • Publishing to external brokers (transport inbox dispatch)
  • Dispatching events through IEventMediator on the inbox axis (planned separately)
  • Returning command results to the accept caller

On this page