pub struct DatabaseConfig {Show 17 fields
pub url: Option<String>,
pub primary_url: Option<String>,
pub replica_url: Option<String>,
pub pool_size: usize,
pub primary_pool_size: Option<usize>,
pub replica_pool_size: Option<usize>,
pub replica_fallback: ReplicaFallback,
pub read_your_writes: ReadYourWrites,
pub pin_after_write_secs: u64,
pub connect_timeout_secs: u64,
pub startup_wait_secs: u64,
pub auto_migrate_in_production: bool,
pub statement_timeout: Option<Duration>,
pub slow_query_threshold: Duration,
pub shards: Vec<ShardConfig>,
pub directory_shard_router: bool,
pub max_connections_warn_threshold: usize,
}Expand description
Database connection configuration.
When url is None (the default), the application runs without a
database – useful for static-site or API-gateway use cases. Set a
Postgres URL to enable the connection pool and the Db
extractor.
§Defaults
| Field | Default |
|---|---|
url | None |
primary_url | None |
replica_url | None |
pool_size | 10 |
primary_pool_size | None |
replica_pool_size | None |
replica_fallback | fail_readiness |
connect_timeout_secs | 5 |
auto_migrate_in_production | false |
shards | [] |
§Examples
use autumn_web::config::DatabaseConfig;
let db = DatabaseConfig::default();
assert!(db.url.is_none());
assert_eq!(db.pool_size, 10);Fields§
§url: Option<String>Postgres connection URL. None means no database is configured.
Compatibility alias for the primary/write role. New multi-role
deployments should prefer primary_url.
When present, must start with postgres:// or postgresql://, or be
a libpq-style keyword/value connection string
(host=db user=app dbname=app sslmode=require).
primary_url: Option<String>Postgres URL for the primary/write role.
All writes, transactions, advisory locks, and migrations use this role.
When unset, url remains the single-primary fallback.
replica_url: Option<String>Optional Postgres URL for the read/replica role.
Read-only paths may use this pool when configured. If omitted, read paths use the primary role.
pool_size: usizeMaximum number of connections in the pool. Default: 10.
Compatibility/default pool size used for both roles unless a role-specific size is set.
primary_pool_size: Option<usize>Optional primary/write role pool size.
replica_pool_size: Option<usize>Optional read/replica role pool size.
replica_fallback: ReplicaFallbackDeterministic behavior for configured replicas that cannot safely serve reads. Default: fail readiness.
read_your_writes: ReadYourWritesPost-write read pinning strategy. Default: off (no pinning).
Set to request to pin reads to the primary for the remainder of the
request after the first write. Set to session to additionally pin
reads across requests via a signed cookie.
Override via AUTUMN_DATABASE__READ_YOUR_WRITES.
pin_after_write_secs: u64Duration (seconds) for cross-request session pins.
Only used when read_your_writes = "session". A signed autumn.ryw
cookie pins the client’s reads to the primary for this many seconds
after a write. Default: 5.
Override via AUTUMN_DATABASE__PIN_AFTER_WRITE_SECS.
connect_timeout_secs: u64Seconds to wait while acquiring a pooled connection, including
creating a new connection when the pool grows.
Default: 5.
startup_wait_secs: u64Bounded startup wait (seconds) for the database to become reachable
before the migrator fails. 0 (the default) disables the wait and
preserves the current fail-fast behaviour — a single connection attempt,
no retry. Set a non-zero value (e.g. 60) to have autumn migrate
retry with capped exponential backoff until either the database accepts
connections or the window elapses.
Override via AUTUMN_DATABASE__STARTUP_WAIT_SECS.
auto_migrate_in_production: boolWhen true, permits automatic migration application while running with
prod/production profile. Default: false.
Keep this disabled for multi-replica production fleets and use an
explicit migration job (autumn migrate) instead.
statement_timeout: Option<Duration>Optional database statement timeout.
slow_query_threshold: DurationSlow query threshold. Default: 500ms.
shards: Vec<ShardConfig>Horizontal shards, declared as [[database.shards]] entries.
Empty (the default) means the application is unsharded and only the
url/primary_url/replica_url roles above apply. When non-empty,
those top-level roles become the control topology — framework
state (jobs, scheduler locks, sessions, feature flags) lives there
while tenant data is routed across the shards. See ShardConfig.
directory_shard_router: boolRoute tenants through the control-plane _autumn_shard_directory table
(a DirectoryShardRouter)
instead of pure slot-hash routing. Default: false.
Tenants with a directory row are pinned to the named shard; everyone
else falls back to the hash router. Usually set via
AppBuilder::with_directory_shard_router.
Ignored when no shards are configured or an explicit
with_shard_router is set.
max_connections_warn_threshold: usizeEmit a startup warning when the aggregate maximum connection count
across the control topology and every shard pool reaches this value.
Default: 100.
Pool sizes multiply across shards: an N-shard fleet with a pool size
of 20 opens up to 20 * N connections, which can exhaust Postgres’s
max_connections (default 100) long before the app looks busy. This
threshold surfaces that footgun at boot. Set to 0 to disable.
Implementations§
Source§impl DatabaseConfig
impl DatabaseConfig
Sourcepub fn effective_primary_url(&self) -> Option<&str>
pub fn effective_primary_url(&self) -> Option<&str>
Resolved primary/write database URL.
Sourcepub fn effective_primary_pool_size(&self) -> usize
pub fn effective_primary_pool_size(&self) -> usize
Resolved primary/write role pool size.
Sourcepub fn effective_replica_pool_size(&self) -> usize
pub fn effective_replica_pool_size(&self) -> usize
Resolved read/replica role pool size.
Sourcepub const fn has_shards(&self) -> bool
pub const fn has_shards(&self) -> bool
Whether any [[database.shards]] entries are configured.
Sourcepub fn resolved_slot_map(&self) -> Result<Vec<usize>, ConfigError>
pub fn resolved_slot_map(&self) -> Result<Vec<usize>, ConfigError>
Resolve the slot→shard map: element s is the index (into
shards) of the shard that owns slot s.
This is the single source of truth for slot assignment, used by both
configuration validation and runtime
ShardSet construction:
- When no shard declares
slots, the slot space is auto-split into contiguous even ranges by declaration order. - When every shard declares
slots, the explicit assignments are used and must cover0..SLOT_COUNTexactly once. - Mixing declared and undeclared
slotsis an error.
§Errors
Returns ConfigError::Validation for mixed declarations,
malformed/out-of-range/duplicate slots, or incomplete coverage.
Sourcepub fn shards_auto_split(&self) -> bool
pub fn shards_auto_split(&self) -> bool
Whether all shards are using auto-split (no shard declares slots).
Returns false when no shards are configured or any shard has an
explicit slots declaration. Mixed declarations already error in
resolved_slot_map, so this is a simple
all-or-none check.
Sourcepub fn resolved_shard_assignments(
&self,
) -> Result<Vec<ShardSlotAssignment>, ConfigError>
pub fn resolved_shard_assignments( &self, ) -> Result<Vec<ShardSlotAssignment>, ConfigError>
Resolve the per-shard slot assignment as compact range strings.
Inverts resolved_slot_map (slot→shard-index)
into per-shard slot lists rendered via the same compact range notation
used in slot-map error messages. Agrees with runtime routing by
construction: the output derives from the same slot map that builds the
live ShardSet.
§Errors
Propagates any ConfigError from resolved_slot_map.
Trait Implementations§
Source§impl Clone for DatabaseConfig
impl Clone for DatabaseConfig
Source§fn clone(&self) -> DatabaseConfig
fn clone(&self) -> DatabaseConfig
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for DatabaseConfig
impl Debug for DatabaseConfig
Source§impl Default for DatabaseConfig
impl Default for DatabaseConfig
Source§impl<'de> Deserialize<'de> for DatabaseConfig
impl<'de> Deserialize<'de> for DatabaseConfig
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Auto Trait Implementations§
impl Freeze for DatabaseConfig
impl RefUnwindSafe for DatabaseConfig
impl Send for DatabaseConfig
impl Sync for DatabaseConfig
impl Unpin for DatabaseConfig
impl UnsafeUnpin for DatabaseConfig
impl UnwindSafe for DatabaseConfig
Blanket Implementations§
Source§impl<T> AggregateExpressionMethods for T
impl<T> AggregateExpressionMethods for T
Source§fn aggregate_distinct(self) -> Self::Outputwhere
Self: DistinctDsl,
fn aggregate_distinct(self) -> Self::Outputwhere
Self: DistinctDsl,
DISTINCT modifier for aggregate functions Read moreSource§fn aggregate_all(self) -> Self::Outputwhere
Self: AllDsl,
fn aggregate_all(self) -> Self::Outputwhere
Self: AllDsl,
ALL modifier for aggregate functions Read moreSource§fn aggregate_filter<P>(self, f: P) -> Self::Output
fn aggregate_filter<P>(self, f: P) -> Self::Output
Source§fn aggregate_order<O>(self, o: O) -> Self::Outputwhere
Self: OrderAggregateDsl<O>,
fn aggregate_order<O>(self, o: O) -> Self::Outputwhere
Self: OrderAggregateDsl<O>,
Source§impl<T> AutumnDependents for Twhere
T: ?Sized,
impl<T> AutumnDependents for Twhere
T: ?Sized,
Source§fn dependents() -> &'static [RuntimeDependentSpec]
fn dependents() -> &'static [RuntimeDependentSpec]
#[model] overrides via an inherent shadow when dependents exist.Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoSql for T
impl<T> IntoSql for T
Source§fn into_sql<T>(self) -> Self::Expression
fn into_sql<T>(self) -> Self::Expression
self to an expression for Diesel’s query builder. Read moreSource§fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expression
fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expression
&self to an expression for Diesel’s query builder. Read moreSource§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<T> RepositoryHooksClone for Twhere
T: Clone,
impl<T> RepositoryHooksClone for Twhere
T: Clone,
Source§fn autumn_clone(&self) -> T
fn autumn_clone(&self) -> T
Source§impl<T> RepositoryHooksDefault for Twhere
T: Default,
impl<T> RepositoryHooksDefault for Twhere
T: Default,
Source§fn autumn_default() -> T
fn autumn_default() -> T
Source§impl<T, Conn> RunQueryDsl<Conn> for T
impl<T, Conn> RunQueryDsl<Conn> for T
Source§fn execute<'conn, 'query>(
self,
conn: &'conn mut Conn,
) -> <Conn as AsyncConnectionCore>::ExecuteFuture<'conn, 'query>
fn execute<'conn, 'query>( self, conn: &'conn mut Conn, ) -> <Conn as AsyncConnectionCore>::ExecuteFuture<'conn, 'query>
Source§fn load<'query, 'conn, U>(
self,
conn: &'conn mut Conn,
) -> AndThen<Self::LoadFuture<'conn>, TryCollect<Self::Stream<'conn>, Vec<U>>>
fn load<'query, 'conn, U>( self, conn: &'conn mut Conn, ) -> AndThen<Self::LoadFuture<'conn>, TryCollect<Self::Stream<'conn>, Vec<U>>>
Source§fn load_stream<'conn, 'query, U>(
self,
conn: &'conn mut Conn,
) -> Self::LoadFuture<'conn>where
Conn: AsyncConnectionCore,
U: 'conn,
Self: LoadQuery<'query, Conn, U> + 'query,
fn load_stream<'conn, 'query, U>(
self,
conn: &'conn mut Conn,
) -> Self::LoadFuture<'conn>where
Conn: AsyncConnectionCore,
U: 'conn,
Self: LoadQuery<'query, Conn, U> + 'query,
Stream] with the returned rows. Read moreSource§fn get_result<'query, 'conn, U>(
self,
conn: &'conn mut Conn,
) -> AndThen<Self::LoadFuture<'conn>, LoadNext<Pin<Box<Self::Stream<'conn>>>>>
fn get_result<'query, 'conn, U>( self, conn: &'conn mut Conn, ) -> AndThen<Self::LoadFuture<'conn>, LoadNext<Pin<Box<Self::Stream<'conn>>>>>
Source§fn get_results<'query, 'conn, U>(
self,
conn: &'conn mut Conn,
) -> AndThen<Self::LoadFuture<'conn>, TryCollect<Self::Stream<'conn>, Vec<U>>>
fn get_results<'query, 'conn, U>( self, conn: &'conn mut Conn, ) -> AndThen<Self::LoadFuture<'conn>, TryCollect<Self::Stream<'conn>, Vec<U>>>
Vec with the affected rows. Read moreSource§impl<T> Scoped for T
impl<T> Scoped for T
Source§fn scope(ctx: &PolicyContext) -> ScopeQuery<'_, Self>
fn scope(ctx: &PolicyContext) -> ScopeQuery<'_, Self>
ScopeQuery for this type. Resolves the
registered scope at .load() time, not here.