pub struct SqliteStoreConfig {
pub pool_size: u32,
pub read_pool_size: u32,
pub cache_size_kib: u32,
pub mmap_size: Option<u64>,
pub busy_timeout: Duration,
pub synchronous: Synchronous,
pub thread_pool: Option<Arc<ScheduledThreadPool>>,
pub connection_init: Option<ConnectionInitHook>,
}Expand description
Per-store connection tuning. Default is a low-memory profile sized for one
SqliteStore per WhatsApp session on a single process: a single pooled connection
(operations are serialized internally, so a second would only idle) sharing one
process-wide r2d2 thread pool, with a 512 KiB page cache. Raise pool_size for real
concurrent DB access — it drives both the pool and the internal serialization in
lockstep — or cache_size_kib for a hotter/larger DB; pass a thread_pool to control
r2d2’s management threads (e.g. share your own across crates).
Fields§
§pool_size: u32Max concurrent operations: r2d2 max_size AND the internal semaphore permits,
kept in lockstep. Clamped to at least 1.
Raising this makes writes concurrent, which SQLite does not want: two
deferred transactions that both read and then write deadlock on the
upgrade, and busy_timeout cannot break it. Leave it at 1 and reach for
read_pool_size instead — that is the knob for
concurrency, and it is safe because WAL readers never contend for the
write lock.
read_pool_size: u32Extra connections reserved for read-only work, each free to run while a
write holds the write permit. 0 (default) keeps every operation on the
single queue, exactly as before this knob existed.
WAL supports many concurrent readers alongside one writer, but that was
unreachable while one pool_size governed both the pool and the
serialization semaphore: the setting that would admit readers also
admitted concurrent writers. These connections are additional — the write
path keeps its own, so a burst of readers can never starve the writer.
Costs one connection’s page cache (cache_size_kib)
each, which is why it is off by default in a process holding many
per-session stores.
cache_size_kib: u32PRAGMA cache_size, in KiB per connection.
mmap_size: Option<u64>PRAGMA mmap_size, in bytes. None (default) leaves mmap off — the
current behavior. When set, pages are read through a reclaimable,
file-backed memory map instead of the heap page cache, which helps a
process holding many small per-session DBs (the mapped pages are
OS-reclaimable, unlike heap cache bytes).
Caveat: mmap I/O covers reads of the main database file; in WAL mode
(this store’s default) writes still go through the WAL, and a checkpoint
briefly falls back to non-mmap I/O. 0 disables mmap the same as None.
busy_timeout: DurationPRAGMA busy_timeout.
synchronous: SynchronousPRAGMA synchronous.
thread_pool: Option<Arc<ScheduledThreadPool>>r2d2 connection-management thread pool. None shares one process-wide pool so many
stores don’t each spawn their own threads.
connection_init: Option<ConnectionInitHook>Optional hook run first on every new pooled connection, before the store’s own
pragmas, WAL setup, and migrations. See ConnectionInitHook for the contract;
set via SqliteStoreConfig::with_connection_init.
Implementations§
Source§impl SqliteStoreConfig
impl SqliteStoreConfig
Sourcepub fn with_read_pool_size(self, n: u32) -> Self
pub fn with_read_pool_size(self, n: u32) -> Self
Reserve n connections for read-only work, so reads stop queueing
behind the write permit. See read_pool_size
for what it costs and why raising pool_size is not the same thing.
Sourcepub fn with_mmap_size(self, bytes: u64) -> Self
pub fn with_mmap_size(self, bytes: u64) -> Self
Set PRAGMA mmap_size (bytes), enabling file-backed memory-mapped reads.
Builder-style so new optional knobs don’t force struct-literal churn;
pass 0 to keep mmap off. See the SqliteStoreConfig::mmap_size caveat.
Sourcepub fn with_connection_init<F>(self, hook: F) -> Self
pub fn with_connection_init<F>(self, hook: F) -> Self
Install a per-connection init hook, run before the store’s pragmas, WAL setup,
and migrations on every pooled connection (see ConnectionInitHook).
The canonical use is SQLCipher keying, where the key must be applied — and ideally verified — before anything else touches the database:
use diesel::prelude::*;
let config = SqliteStoreConfig::default().with_connection_init(move |conn| {
diesel::sql_query("PRAGMA key = 'my-passphrase';").execute(conn)?;
// Verify the key: this fails on a wrongly-keyed database.
diesel::sql_query("SELECT count(*) FROM sqlite_master;").execute(conn)?;
Ok(())
});Linking a SQLCipher-enabled SQLite is the caller’s responsibility: disable this
crate’s default bundled-sqlite feature and depend on libsqlite3-sys with a
SQLCipher build (e.g. its bundled-sqlcipher feature) instead.
Trait Implementations§
Source§impl Clone for SqliteStoreConfig
impl Clone for SqliteStoreConfig
Source§fn clone(&self) -> SqliteStoreConfig
fn clone(&self) -> SqliteStoreConfig
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl !RefUnwindSafe for SqliteStoreConfig
impl !UnwindSafe for SqliteStoreConfig
impl Freeze for SqliteStoreConfig
impl Send for SqliteStoreConfig
impl Sync for SqliteStoreConfig
impl Unpin for SqliteStoreConfig
impl UnsafeUnpin for SqliteStoreConfig
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> 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
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
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<T> ErasedDestructor for Twhere
T: 'static,
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 more