CatalogStorage
Append Store Role
- ID:
storage.role.append - Summary: Writes inbox acceptance rows and outbox enqueue rows, including idempotency behavior.
Interface Methods
| Role | Methods |
|---|---|
IInboxStore | AddAsync, AddBatchAsync |
IOutboxStore | AddAsync, AddBatchAsync |
ITransactionalInboxStore | transactional variants of append methods |
ITransactionalOutboxStore | transactional variants of append methods |
SQL Behavior
- PostgreSQL append uses insert with
ON CONFLICT DO NOTHING. - When conflict occurs, the adapter returns the existing row with
AlreadyAcceptedorAlreadyEnqueuedinstead of creating a duplicate. - Tenant-scoped idempotency is enforced by filtered unique index on
(tenant_id, idempotency_key). - Batch append preserves request ordering in the returned append-result list. A later slot that duplicates an earlier slot reports the existing outcome.
Concurrency Model
- Concurrent append calls are safe because primary key and idempotency unique indexes resolve duplicates.
- Batch append still applies dedup behavior per envelope slot.
- Transactional mode can bind writes to caller transaction (manual or ambient participant).
Index Interaction
message_idprimary key prevents duplicate message identifiers.- Inbox and outbox idempotency unique indexes enforce per-tenant dedup.
- Outbox topic index is append-adjacent because
topicis written at append time for publish routing.
Observability
- No dedicated append counter at storage layer.
- Append impact appears in queue-depth gauges on next diagnostics pass:
litebus.inbox.queue.depthlitebus.outbox.queue.depth
Test Coverage
LiteBus.Storage.UnitTests
- Inherited store contract tests validate duplicate message IDs, idempotency keys, ordered batch results, and later-slot duplicate outcomes for all adapters.
- EF transactional unit tests verify staged append behavior before
SaveChanges.
LiteBus.Storage.IntegrationTests (PostgreSql/)
PostgreSqlInboxStoreTestsandPostgreSqlOutboxStoreTests: append contract parity.PostgreSqlTransactionalWritersIntegrationTests: ambient and manual transactional append.PostgreSqlReliableMessagingEndToEndTests: append-to-process flow with duplicate delivery scenario.
Concrete Example
When a command with the same tenant and idempotency key is accepted twice, the second append call returns InboxAppendResult(firstEnvelope, AlreadyAccepted). Processor logic then sees one pending message, not two.