LiteBus
CatalogStorage

EF Core Shared Infrastructure

  • ID: storage.efcore.shared-infra
  • Name: EF Core shared infrastructure
  • Maturity: GA
  • Summary: Provider-specific lease SQL, bulk update helpers, and relational model utilities for EF-backed durable stores.

What It Does

LiteBus.Storage.EntityFrameworkCore supplies cross-axis EF primitives: provider detection (EfCoreStorageProvider), provider-specific lease SQL (PostgreSQL FOR UPDATE SKIP LOCKED, SQL Server, MySQL/Pomelo), serializable SQLite lease transactions, SQLite UTC-tick timestamp mapping, relational table qualification, JSON text normalization, bulk update capability probes, and shared durable store operation helpers. Inbox and outbox EF adapters use these types internally; applications typically interact through axis-specific model extensions and store options.

Public Surface

Consumer Contracts

TypeRole
EfCoreStorageProviderPostgreSQL, SQL Server, MySQL, SQLite, InMemory detection
EfCoreRelationalLeaseExecutorExecutes provider lease SQL against a DbContext
EfCorePostgreSqlLeaseSql / EfCoreSqlServerLeaseSql / EfCoreMySqlLeaseSqlLease statement templates
EfCoreDurableStoreOperationsShared state transition helpers
EfCoreBulkUpdateCapabilitiesProvider bulk update feature detection
EfCoreRelationalModelColumnTypesPayload and trace column type mapping
EfCoreJsonTextNormalizerJSON serialization alignment for relational providers
EfCoreProviderResolverResolve provider from DbContext

Invocation

APITypical caller
EfCoreRelationalLeaseExecutorEfCoreInboxStore / EfCoreOutboxStore lease paths
EfCoreDurableStoreOperationsPersist, mark failed, dead-letter transitions
EfCoreRelationalModelColumnTypesModel configuration extensions
EfCoreProviderResolverStore construction and lease SQL selection

Registration

  • Not registered directly; consumed by inbox/outbox EF storage feature bridges.
  • Provider detection runs against an operation context created by the application's IDbContextFactory<TContext>.

Configuration

Option surfacePurpose
EF provider packageDetermines lease SQL and column types (Npgsql, SQL Server, Pomelo)
Store options SchemaName / TableNameMust match fluent model configuration
Provider hint on model extensionsSelects text storage for payload and provider-specific storage for trace context

Extension Points

  • Custom EF store adapters may reuse lease executor and durable operation helpers from this package.
  • Unsupported providers throw EfCoreStorageNotSupportedException at resolve time.

Packages

PackageDependency role
LiteBus.Storage.EntityFrameworkCoreTechnology adapter

Requires

  • EF Core relational provider package used by the application (Npgsql.EntityFrameworkCore.PostgreSQL, SQL Server, Pomelo, etc.)
  • Axis EF storage adapter (LiteBus.Inbox.Storage.EntityFrameworkCore or LiteBus.Outbox.Storage.EntityFrameworkCore)

Invariants

  • Lease SQL requires a supported relational provider. SQLite leasing runs inside a serializable transaction, which serializes claims across store instances through the database write lock.
  • MySQL leasing uses READ COMMITTED, the axis IX_LiteBus_*_CreatedAt index, and direct primary-key updates so concurrent workers claim disjoint ordered batches without range-lock starvation.
  • Store options SchemaName and TableName must match the EF model configuration used in migrations.
  • Payload and trace context columns map to text so payload protection can return opaque ciphertext.

Non-Goals

  • Does not register DbContext or run migrations.
  • Does not replace raw Npgsql inbox/outbox stores for apps that prefer ADO.NET-only persistence.
  • Does not implement saga EF storage (not shipped).

Observability

No dedicated meters in this package. Processor and queue metrics come from axis packages when a processor is enabled.

MeterInstrumentTypeWhen observedTagsStorage coupling
LiteBus.Inboxlitebus.inbox.queue.depthObservable gaugeOpenTelemetry scrapelitebus.inbox.statusEF inbox store implements diagnostics role
LiteBus.Inboxlitebus.inbox.processor.leases_acquiredCounterEach processor pass:Lease SQL from this package acquires rows
LiteBus.Inboxlitebus.inbox.processor.persist_skippedCounterTerminal persist with lost lease:EfCoreDurableStoreOperations skip path
LiteBus.Inboxlitebus.inbox.processor.persist_rejectedCounterCompeting persist rejected:Optimistic lease guard
LiteBus.Outboxlitebus.outbox.queue.depthObservable gaugeOpenTelemetry scrapelitebus.outbox.statusEF outbox store implements diagnostics role
LiteBus.Outboxlitebus.outbox.processor.leases_acquiredCounterEach processor pass:Lease SQL from this package
LiteBus.Outboxlitebus.outbox.processor.persist_skippedCounterTerminal persist with lost lease:Shared persist helpers
LiteBus.Outboxlitebus.outbox.processor.persist_rejectedCounterCompeting persist rejected:Optimistic lease guard

Instrument names are public constants on LiteBusInboxTelemetry and LiteBusOutboxTelemetry.

Deep Docs

Test Coverage

Covered

EfCoreStorageExceptionTests.EfCoreProviderResolver_throws_EfCoreStorageNotSupportedException_for_unknown_provider

  • Use case: Reject unknown EF provider in resolver
  • Test kind: Unit
  • Description: DbContext with unsupported provider
  • Behavior: EfCoreProviderResolver resolve
  • Expected outcome: EfCoreStorageNotSupportedException thrown
  • Remarks: LiteBus.Storage.EntityFrameworkCore.UnitTests

EfCoreInboxStorePostgreSqlContractTests (Inherits InboxStoreContractTests)

  • Use case: PostgreSQL EF inbox lease and append contract parity
  • Test kind: Contract (integration)
  • Description: Full inbox contract suite against EF Npgsql store
  • Behavior: All inherited contract tests run on PostgreSQL EF
  • Expected outcome: Same outcomes as abstract contract tests
  • Remarks: LiteBus.Inbox.Storage.EntityFrameworkCore.IntegrationTests

EfCoreInboxStoreSqlServerContractTests (Inherits InboxStoreContractTests)

  • Use case: SQL Server EF inbox contract parity
  • Test kind: Contract (integration)
  • Description: Full inbox contract suite against EF SQL Server store
  • Behavior: Inherited contract tests on SQL Server
  • Expected outcome: Same outcomes as abstract contract tests
  • Remarks: LiteBus.Inbox.Storage.EntityFrameworkCore.IntegrationTests

EfCoreOutboxStorePostgreSqlContractTests (Inherits OutboxStoreContractTests)

  • Use case: PostgreSQL EF outbox lease and append contract parity
  • Test kind: Contract (integration)
  • Description: Full outbox contract suite against EF Npgsql store
  • Behavior: Inherited contract tests on PostgreSQL EF
  • Expected outcome: Same outcomes as abstract contract tests
  • Remarks: LiteBus.Outbox.Storage.EntityFrameworkCore.IntegrationTests

EfCoreOutboxStoreSqlServerContractTests (Inherits OutboxStoreContractTests)

  • Use case: SQL Server EF outbox contract parity
  • Test kind: Contract (integration)
  • Description: Full outbox contract suite against EF SQL Server store
  • Behavior: Inherited contract tests on SQL Server
  • Expected outcome: Same outcomes as abstract contract tests
  • Remarks: LiteBus.Outbox.Storage.EntityFrameworkCore.IntegrationTests

EfCoreInboxStoreContractTests (Inherits InboxStoreContractTests)

  • Use case: In-memory EF inbox contract parity
  • Test kind: Contract (unit)
  • Description: Full inbox contract suite against EF in-memory provider
  • Behavior: Inherited contract tests
  • Expected outcome: Same outcomes as abstract contract tests
  • Remarks: LiteBus.Inbox.Storage.EntityFrameworkCore.UnitTests

EfCoreOutboxStoreContractTests (Inherits OutboxStoreContractTests)

  • Use case: In-memory EF outbox contract parity
  • Test kind: Contract (unit)
  • Description: Full outbox contract suite against EF in-memory provider
  • Behavior: Inherited contract tests
  • Expected outcome: Same outcomes as abstract contract tests
  • Remarks: LiteBus.Outbox.Storage.EntityFrameworkCore.UnitTests

EfCoreInboxStoreParityTests.LeasePendingAsync_FiltersByTenantId

  • Use case: Lease filters by tenant id (inbox)
  • Test kind: Unit
  • Description: Pending rows for multiple tenants
  • Behavior: LeasePendingAsync with tenant filter
  • Expected outcome: Only matching tenant rows leased
  • Remarks: Exercises shared lease executor; LiteBus.Inbox.Storage.EntityFrameworkCore.UnitTests

EfCoreInboxStoreParityTests.LeasePendingAsync_ReclaimsStaleNullLeaseAfterLeaseDuration

  • Use case: Reclaim stale null lease after duration (inbox)
  • Test kind: Unit
  • Description: Row with expired null lease owner
  • Behavior: Lease after lease duration elapsed
  • Expected outcome: Row reclaimed
  • Remarks: LiteBus.Inbox.Storage.EntityFrameworkCore.UnitTests

EfCoreInboxStoreParityTests.AddBatchAsync_DeduplicatesWithinBatchByIdAndIdempotencyKey

  • Use case: Batch deduplication by id and idempotency key (inbox)
  • Test kind: Unit
  • Description: Batch with duplicate ids and idempotency keys
  • Behavior: AddBatchAsync
  • Expected outcome: Within-batch dedup applied
  • Remarks: LiteBus.Inbox.Storage.EntityFrameworkCore.UnitTests

EfCoreInboxStoreParityTests.PersistAsync_ReturnsSkippedCountWhenLeaseIsLost

  • Use case: Persist reports skipped count when lease lost (inbox)
  • Test kind: Unit
  • Description: Persist after lease stolen by another worker
  • Behavior: PersistAsync with lost lease token
  • Expected outcome: Skipped count reported; row unchanged
  • Remarks: Uses EfCoreDurableStoreOperations; LiteBus.Inbox.Storage.EntityFrameworkCore.UnitTests

EfCoreOutboxStoreParityTests.LeasePendingAsync_FiltersByTenantId

  • Use case: Lease filters by tenant id (outbox)
  • Test kind: Unit
  • Description: Pending outbox rows for multiple tenants
  • Behavior: LeasePendingAsync with tenant filter
  • Expected outcome: Only matching tenant rows leased
  • Remarks: LiteBus.Outbox.Storage.EntityFrameworkCore.UnitTests

EfCoreOutboxStoreParityTests.LeasePendingAsync_ReclaimsStaleNullLeaseAfterLeaseDuration

  • Use case: Reclaim stale null lease after duration (outbox)
  • Test kind: Unit
  • Description: Outbox row with expired null lease
  • Behavior: Lease after duration elapsed
  • Expected outcome: Row reclaimed
  • Remarks: LiteBus.Outbox.Storage.EntityFrameworkCore.UnitTests

EfCoreOutboxStoreParityTests.AddBatchAsync_DeduplicatesWithinBatchByIdAndIdempotencyKey

  • Use case: Batch deduplication by id and idempotency key (outbox)
  • Test kind: Unit
  • Description: Batch with duplicate ids and keys
  • Behavior: Batch enqueue
  • Expected outcome: Within-batch dedup applied
  • Remarks: LiteBus.Outbox.Storage.EntityFrameworkCore.UnitTests

EfCoreOutboxStoreParityTests.PersistAsync_ReturnsSkippedCountWhenLeaseIsLost

  • Use case: Persist reports skipped count when lease lost (outbox)
  • Test kind: Unit
  • Description: Persist after lease lost
  • Behavior: PersistAsync with invalid lease
  • Expected outcome: Skipped count returned
  • Remarks: LiteBus.Outbox.Storage.EntityFrameworkCore.UnitTests

EfCoreOutboxStoreConcurrencyTests.PersistAsync_WhenTwoWorkersPersistSameEnvelopeConcurrently_ShouldApplyExactlyOnce

  • Use case: Concurrent persist applies exactly once (outbox)
  • Test kind: Integration
  • Description: Two workers persist same leased envelope
  • Behavior: Concurrent PersistAsync
  • Expected outcome: Exactly one terminal update applied
  • Remarks: LiteBus.Outbox.Storage.EntityFrameworkCore.IntegrationTests

Untested

  • Dedicated unit tests per provider lease SQL template file (coverage is indirect through contract and integration suites).
  • SQLite throughput under sustained multi-process writes; provider contracts cover concurrent claims across independent contexts on one file.

Out-of-Scope

  • Automatic EF migrations or EnsureCreated from shared infrastructure.
  • Saga EF storage (not shipped).
  • Replacing raw Npgsql inbox/outbox stores for ADO-only deployments.

On this page

EF Core Shared InfrastructureWhat It DoesPublic SurfaceConsumer ContractsInvocationRegistrationConfigurationExtension PointsPackagesRequiresInvariantsNon-GoalsObservabilityDeep DocsTest CoverageCoveredEfCoreStorageExceptionTests.EfCoreProviderResolver_throws_EfCoreStorageNotSupportedException_for_unknown_providerEfCoreInboxStorePostgreSqlContractTests (Inherits InboxStoreContractTests)EfCoreInboxStoreSqlServerContractTests (Inherits InboxStoreContractTests)EfCoreOutboxStorePostgreSqlContractTests (Inherits OutboxStoreContractTests)EfCoreOutboxStoreSqlServerContractTests (Inherits OutboxStoreContractTests)EfCoreInboxStoreContractTests (Inherits InboxStoreContractTests)EfCoreOutboxStoreContractTests (Inherits OutboxStoreContractTests)EfCoreInboxStoreParityTests.LeasePendingAsync_FiltersByTenantIdEfCoreInboxStoreParityTests.LeasePendingAsync_ReclaimsStaleNullLeaseAfterLeaseDurationEfCoreInboxStoreParityTests.AddBatchAsync_DeduplicatesWithinBatchByIdAndIdempotencyKeyEfCoreInboxStoreParityTests.PersistAsync_ReturnsSkippedCountWhenLeaseIsLostEfCoreOutboxStoreParityTests.LeasePendingAsync_FiltersByTenantIdEfCoreOutboxStoreParityTests.LeasePendingAsync_ReclaimsStaleNullLeaseAfterLeaseDurationEfCoreOutboxStoreParityTests.AddBatchAsync_DeduplicatesWithinBatchByIdAndIdempotencyKeyEfCoreOutboxStoreParityTests.PersistAsync_ReturnsSkippedCountWhenLeaseIsLostEfCoreOutboxStoreConcurrencyTests.PersistAsync_WhenTwoWorkersPersistSameEnvelopeConcurrently_ShouldApplyExactlyOnceUntestedOut-of-Scope