LiteBus
CatalogDispatch

Shared Transport Dispatchers

  • ID: dispatch.transport-core
  • Name: Shared transport dispatchers
  • Maturity: GA
  • Summary: Broker-neutral TransportInboxDispatcher and TransportOutboxDispatcher publish leased envelopes through ITransportPublisher with shared options and optional tenant routing.

What It Does

LiteBus.Inbox.Dispatch and LiteBus.Outbox.Dispatch host the shared transport dispatch implementation. Each dispatcher resolves the contract from the envelope, optionally decrypts the payload, optionally validates deserialization, resolves a transport route, builds publish headers, and calls ITransportPublisher.PublishAsync.

TransportInboxDispatchModule and TransportOutboxDispatchModule register the dispatcher and require a matching root transport module. Broker-specific Use*Dispatch extensions contribute only feature bridge wiring. Transport outbox modules expose DefaultHookFailurePolicy = CompleteDespiteHookFailure.

Route resolution order:

AxisPriority
InboxITenantRoutingStrategy if registered, else ResolveRoute delegate, else ContractName
OutboxITenantRoutingStrategy if registered, else non-empty Topic, else ResolveRoute delegate, else ContractName

Packages

PackageRole
LiteBus.Inbox.DispatchInbox transport dispatcher and module
LiteBus.Outbox.DispatchOutbox transport dispatcher and module
LiteBus.Transport.AbstractionsITransportPublisher, TransportPublishRequest
LiteBus.TransportTracing, shared header helpers
LiteBus.MessagingPayload protection, serializer integration

Requires

  • runtime.contract-registry (contract name/version to CLR type)
  • runtime.message-serialization
  • Matching root transport.* broker module registered through Add*Transport(...)
  • dispatch.registration

Invariants

  • Stored payload bytes are published as-is after optional unprotect; deserialization is for validation only when ValidatePayloadBeforeDispatch is true.
  • MessageId on the transport request is the envelope GUID string.
  • One explicitly selected root transport module is shared by dispatch and ingress.
  • Dispatch throws on transport failure; the processor owns retry and dead-letter state.

Non-Goals

  • Does not consume from brokers (ingress axis owns intake).
  • Does not deserialize and invoke mediators (in-process dispatch owns that path).
  • Does not persist terminal store outcomes (processor owns persistence after dispatch returns).

Public Surface

bus.AddKafkaTransport(new KafkaTransportOptions { BootstrapServers = "localhost:9092" });
bus.AddOutbox(outbox => outbox.UseKafkaDispatch(
    options =>
    {
        options.DefaultDestination = "orders.events";
        options.ValidatePayloadBeforeDispatch = true;
        options.ResolveRoute = envelope => envelope.Topic ?? envelope.ContractName;
    }));

TransportInboxDispatcher.DispatchAsync(InboxEnvelope, CancellationToken)

PackageLiteBus.Inbox.Dispatch
ImplementsIInboxDispatcher.DispatchAsync
FlowResolve contract to unprotect payload to optional deserialize validation to resolve route to start publish activity to ITransportPublisher.PublishAsync

Throws when contract resolution, validation, or transport publish fails. Does not catch transport exceptions.

TransportOutboxDispatcher.DispatchAsync(OutboxEnvelope, CancellationToken)

PackageLiteBus.Outbox.Dispatch
ImplementsIOutboxDispatcher.DispatchAsync
FlowSame as inbox transport dispatcher; route prefers envelope Topic before resolver and contract name

TransportInboxDispatchModule.Build(IModuleConfiguration)

PackageLiteBus.Inbox.Dispatch
RegistersTransportInboxDispatcherOptions singleton, IInboxDispatcher to TransportInboxDispatcher
DependenciesRequires the matching root transport module; duplicate dispatcher registration fails during composition

TransportOutboxDispatchModule.Build(IModuleConfiguration)

PackageLiteBus.Outbox.Dispatch
RegistersTransportOutboxDispatcherOptions singleton, IOutboxDispatcher to TransportOutboxDispatcher
DefaultHookFailurePolicyCompleteDespiteHookFailure (transport outbox default)

TransportInboxDispatcherOptions / TransportOutboxDispatcherOptions

PropertyDefaultRole
DefaultDestination""Exchange, topic, queue URL, or InMemory destination name
ContentTypeapplication/jsonWire MIME type
PersistenttrueBroker durability flag (AMQP)
MandatoryfalseFail publish when unroutable (AMQP)
ResolveRoutenullPer-envelope route override delegate
ValidatePayloadBeforeDispatchfalseDeserialize before publish to catch contract wiring errors

Optional Dependencies (Constructor Injection)

TypeRole
IInboxPayloadProtector / IOutboxPayloadProtectorDecrypt stored payload before publish
ITenantRoutingStrategyPer-tenant destination/route override

Observability

SignalConstant / nameTags / attributesWhen
Send activitysend {destination}Activity source LiteBus.Transport; required messaging operation tags plus destination, message id, conversation id, and broker-specific route tagsStarted by the concrete transport publisher around its SDK send call
Processor dispatch durationlitebus.inbox.processor.dispatch_duration / litebus.outbox.processor.dispatch_durationHistogram in msProcessor envelope handler wraps dispatch (includes transport and in-process paths)
Circuit breaker openlitebus.transport.circuit_breaker.openTag litebus.transport.broker (amqp, kafka, sqs, azure_service_bus, inmemory)Broker adapter records consecutive publish/connection failures
Circuit breaker failure countlitebus.transport.circuit_breaker.failure_countSame broker tagIncremented on counted publish failures
Processor pass counterslitebus.inbox.processor.succeeded / failed / dead_lettered; litebus.outbox.processor.published / failed / dead_letteredNone on dispatch axisIncremented after dispatch outcome is persisted

Trace context from envelope headers is copied onto TransportPublishRequest.Headers for downstream process {destination} correlation. No dispatch-specific meter exists beyond processor and transport layers.

Register transport tracing through AddLiteBusTransportInstrumentation() from LiteBus.Transport.Extensions.OpenTelemetry. Processor metrics require AddLiteBusInboxMetrics() / AddLiteBusOutboxMetrics().

Deep Docs

Test Coverage

Covered

Test methodProject
DispatchAsync_ShouldPublishEnvelopeThroughTransportLiteBus.Inbox.UnitTests (Dispatch/)
ProcessPendingAsync_ShouldPublishLeasedEnvelopeToKafkaTopicLiteBus.Durable.IntegrationTests (Dispatch/Inbox/Kafka/)
ProcessPendingAsync_ShouldPublishLeasedEnvelopeToSqsQueueLiteBus.Durable.IntegrationTests (Dispatch/Inbox/AwsSqs/)
ProcessPendingAsync_ShouldPublishLeasedEnvelopeToInMemoryDestinationLiteBus.Durable.IntegrationTests (Dispatch/Inbox/InMemory/)
ProcessPendingAsync_ShouldPublishLeasedEnvelopeToServiceBusQueueLiteBus.Durable.IntegrationTests (Dispatch/Inbox/AzureServiceBus/)
ProcessPendingAsync_ShouldPublishLeasedEnvelopeToAmqpQueueLiteBus.Durable.IntegrationTests (Dispatch/Inbox/Amqp/)
ProcessPendingAsync_ShouldPublishToAmqpAndMarkPostgreSqlEnvelopeCompletedLiteBus.Durable.IntegrationTests (Dispatch/Inbox/Amqp/)
DispatchAsync_ShouldPublishEnvelopeThroughTransportLiteBus.Outbox.UnitTests (Dispatch/)
DispatchAsync_when_validate_payload_disabled_should_publish_without_deserializingLiteBus.Outbox.UnitTests (Dispatch/)
DispatchAsync_when_validate_payload_enabled_should_throw_before_publishLiteBus.Outbox.UnitTests (Dispatch/)
ProcessPendingAsync_ShouldPublishEnvelopeToKafkaTopicLiteBus.Durable.IntegrationTests (Dispatch/Outbox/Kafka/)
ProcessPendingAsync_WhenTopicMissing_ShouldUseContractNameAsRouteLiteBus.Durable.IntegrationTests (Dispatch/Outbox/Kafka/, Dispatch/Outbox/AwsSqs/, Dispatch/Outbox/InMemory/, Dispatch/Outbox/AzureServiceBus/)
ProcessPendingAsync_WhenBrokerUnreachable_ShouldMarkFailedWithVisibleAfterLiteBus.Durable.IntegrationTests (Dispatch/Outbox/Kafka/, Dispatch/Outbox/AwsSqs/)
ProcessPendingAsync_WhenCircuitBreakerOpen_ShouldNotPublishLiteBus.Durable.IntegrationTests (Dispatch/Outbox/Kafka/, Dispatch/Outbox/AwsSqs/)
ProcessPendingAsync_ShouldPublishEnvelopeToAmqpQueueLiteBus.Durable.IntegrationTests (Dispatch/Outbox/Amqp/)
ProcessPendingAsync_ShouldPublishEnvelopeToInMemoryDestinationLiteBus.Durable.IntegrationTests (Dispatch/Outbox/InMemory/)
InboxDispatchExtensions_ShouldRegisterTransportDispatcherLiteBus.Durable.IntegrationTests (Registration/)
OutboxDispatchExtensions_ShouldRegisterTransportDispatcherLiteBus.Durable.IntegrationTests (Registration/)
UseAmqpDispatch_WithAmqpTransportModule_ShouldRegisterTransportOutboxDispatcherLiteBus.Durable.IntegrationTests (Dispatch/Outbox/Amqp/)

Untested

  • Inbox ValidatePayloadBeforeDispatch = true branch.
  • ITenantRoutingStrategy route selection on inbox and outbox paths.
  • Payload decryption branch for both dispatchers.
  • AMQP and Azure outbox unreachable-broker coverage parity.

Out-of-Scope

  • Broker consumption (ingress axis)
  • Deserializing and invoking in-process mediators (in-process dispatch axis)
  • Persisting terminal store outcomes after dispatch returns (processor and storage axes)

On this page