CatalogStorage
Inbox PostgreSQL Adapter
- ID:
storage.inbox.adapter.postgresql - Package:
LiteBus.Inbox.Storage.PostgreSql(feature bridge) - Shared dependency:
LiteBus.Storage.PostgreSql(technology adapter) - Summary: A single
PostgreSqlInboxStoreinstance implements inbox append, processing, and operations store roles on PostgreSQL.
Interface Methods
| Interface | Methods used in adapter |
|---|---|
IInboxStore | AddAsync, AddBatchAsync |
IInboxLeaseStore | LeasePendingAsync, RenewLeaseAsync (via ILeaseRenewable) |
IInboxStateWriter | PersistAsync |
IInboxDeadLetterStore | RequeueAsync |
IInboxRetentionStore | DeleteCompletedOlderThanAsync |
IInboxDiagnosticsStore | GetStatusCountsAsync, GetSchemaInfoAsync |
IInboxMessageQuery and IInboxPurgeStore | QueryAsync, PurgeAsync |
ITransactionalInboxStore | AddAsync, AddBatchAsync on existing Npgsql transaction |
SQL Behavior
- Table: configurable, defaults to
public.litebus_inbox_messages. - Insert path uses
ON CONFLICT DO NOTHING RETURNING; returned rows reportAccepted, while conflict lookups reportAlreadyAccepted. - Retention delete uses
COALESCE(completed_at, created_at) < @older_than. - Dead-letter replay uses
UPDATE ... SET status = pending, visible_after = NULL, attempt_count = 0. - Status diagnostics uses grouped count query:
SELECT status, COUNT(*) FROM ... GROUP BY status.
Concurrency Model
- Leasing uses
FOR UPDATE SKIP LOCKEDto claim disjoint rows across workers. - Lease ownership is recorded with
lease_ownerandlease_expires_at. - State writes are lease-guarded; stale workers return skipped/rejected persist counts.
- Expired leases are reclaimable, which gives at-least-once execution behavior.
- Payload is stored as text so configured encryptors can return opaque ciphertext. Existing tables created with a JSONB payload column require an application migration before encrypted writes use the text parameter type.
Indexes
Schema v1 creates and validates:
- Unique idempotency index:
(tenant_id, idempotency_key)with filteridempotency_key IS NOT NULL. - Lease scan index:
(status, visible_after, lease_expires_at, created_at). - Primary key:
message_id. - Optional insert trigger and function for
NOTIFYwake-ups.
Observability
- Queue depth gauge:
litebus.inbox.queue.depthwith taglitebus.inbox.status. - Processor counters and histograms are fed by lease and state transitions (
leases_acquired,dispatch_duration,succeeded,failed,dead_lettered,persist_skipped,persist_rejected). - Cleanup error counter:
litebus.inbox.cleanup.errors. - Schema probe:
inbox.postgresql.schemavalidates columns and indexes.
Test Coverage
LiteBus.Storage.IntegrationTests (PostgreSql/)
PostgreSqlInboxStoreTests(contract inheritance): append, lease, persist, replay, retention, diagnostics.PostgreSqlInboxEndToEndTests: full processor pass and retry/dead-letter transitions.PostgreSqlInboxProcessorLeaseStressTests: parallel workers with one terminal result per message.PostgreSqlInboxWorkSignalNotifyTestsandPostgreSqlInboxWorkSignalTests: LISTEN/NOTIFY wake and reconnect.PostgreSqlInboxTransactionalIntegrationTests: commit and rollback behavior with shared transaction.PostgreSqlModuleRegistrationTests: confirms all inbox role interfaces resolve from one singleton.
LiteBus.Storage.UnitTests
PostgreSqlTransactionalParticipantTests: active-transaction requirement and fallback policy.PostgreSqlSchemaInspectorTestsandPostgreSqlTableReferenceTests: schema/version/index helper behavior used by diagnostics.