Expand description
Datasource contracts: tenant-scoped pools + read/write splitting.
The framework defines the shape of data access; the app implements it
with SQLx, SeaORM, or anything else — the same boundary rule that keeps
OAuth providers and session stores app-side. core/ is untouched: the
registry is an ordinary DI singleton.
§Hot-path guarantees
DataSourceRegistryis frozen at boot: tenant→pool lookup is an immutableHashMapread. No locks.- Replica selection inside a
DataSourceimplementation should be a singleAtomicUsizeround-robin — never a locked list. ReadAfterWritePinis oneAtomicBoolper request, used to route post-write reads to the primary (replica-lag protection).
§Read-after-write rule
Within one request, after the first Write acquisition every subsequent
Read must go to the primary — a replica may not have replayed the write
yet. Handlers opt in by creating a ReadAfterWritePin and passing it to
DataSourceRegistry::acquire:
ⓘ
let pin = ReadAfterWritePin::new();
let ds = registry.for_tenant(ctx.tenant());
let w = registry.acquire(ds, AccessIntent::Write, &pin).await?; // pins
let r = registry.acquire(ds, AccessIntent::Read, &pin).await?; // → primaryModules§
- db
- Unified database facade — one handle, three ecosystems.
- drivers
- Driver adapters — each behind its Cargo feature.
- migrate
- Migration runner uses the SQLx query facade; SeaORM/Diesel ledger support arrives with their facade methods. Database migration lifecycle — versioned, checksummed, lock-guarded.
- outbox
- Transactional Outbox — reliable event publishing without dual writes.
- tx
- Request-scoped transactions for
#[Transactional].
Structs§
- Data
Error - Classified datasource failure — callers can finally distinguish “retry somewhere else” from “this will never work”, which retry policies, circuit breakers, and replica failover need.
- Data
Source Registry - Frozen tenant→datasource map. Built once at boot, provided via DI, read lock-free on every request.
- Read
After Write Pin - Per-request replica-lag protection: once any
Writeis acquired through this pin, all subsequentReads are upgraded to the primary.
Enums§
- Access
Intent - Whether the caller intends to read or mutate.
- Data
Error Kind - Failure classes.
#[non_exhaustive]: match with a_arm.
Traits§
- Data
Source - One logical database: a primary plus optional read replicas.