Skip to main content

Asset Publishing and Outbox

Summary

Asset events are staged in a transactional outbox on save and drained by a registered background relay through the shared outbox processor and event bus.

Audience

Engineering, integration, QA, architecture, and security reviewers.

Reference Content

Outbox row (OutboxMessage)

FieldPurpose
IdRow identity (GUID)
EventIdIntegration-event identity (GUID)
EventTypeContract type name (for example AssetAssigned)
PayloadJsonSerialized contract (classified; not exposed here)
OccurredAtUtcEvent time
ProcessedOnUtcSet when published
StatusPending, Processing, Processed, or Failed
RetryCountIncremented on each failed publish
ErrorMessageLast publish error text
CorrelationIdCorrelation for tracing
TenantIdGUID tenant (nullable for asset events)
SourceServiceasset-service

Staging (in the write transaction)

AssetDbContext.SaveChangesAsync calls DispatchDomainEventsToOutbox before base.SaveChangesAsync. For each tracked aggregate with pending domain events, every event is mapped to a contract, the completeness guard runs, and the serialized row is added to OutboxMessages. The aggregate's domain events are then cleared. The outbox rows commit atomically with the aggregate, audit, and timeline changes in one local transaction.

Relay (after commit)

OutboxRelayHostedService is a registered hosted service. Every 10 seconds it opens a scope, resolves IOutboxProcessor, and calls ProcessPendingAsync(50, ...). AssetOutboxMessageStore.GetPendingAsync returns rows whose Status is Pending or Failed, ordered by OccurredAtUtc, capped at the batch size.

For each row the processor calls RabbitMqEventBus.PublishAsync:

  • On success, MarkProcessedAsync sets Status = Processed, stamps ProcessedOnUtc, and clears the error.
  • On a false result or an exception, MarkFailedAsync sets Status = Failed, increments RetryCount, and records the error. The row is retried on the next pass.

Diagnostics

Outbox rows are readable through the asset outbox diagnostics endpoint (documented in the API section), which projects row metadata for inspection. This is a read path only.

Verified boundaries

  • A publish failure never blocks the request that wrote the row; the row simply remains eligible for a later pass.
  • Broker delivery depends on broker availability and configuration and is not verified here.
  • There is no verified retry ceiling, dead-letter path, or outbox cleanup. See Retry and failure and Event limitations.

Source References

  • microservices/src/asset-service/Infrastructure/AssetDbContext.cs
  • microservices/src/asset-service/Messaging/OutboxRelayHostedService.cs
  • microservices/src/shared-kernel/Messaging/OutboxProcessor.cs
  • microservices/src/shared-kernel/Outbox/OutboxMessage.cs
  • microservices/src/asset-service/Infrastructure/Persistence.cs

See Also

Keywords

  • Transactional outbox
  • Hosted relay
  • Outbox processor

Revision Information

  • Status: Draft
  • Last reviewed: 2026-07-17
  • Review cycle: Quarterly