Skip to main content

Tuning

Struct Tuning 

Source
#[non_exhaustive]
pub struct Tuning { pub cadence: CadencePolicy, pub clock: Option<Arc<dyn Clock>>, pub wal_autocheckpoint: WalCheckpointPolicy, pub writer_cache_size: Option<i32>, pub reader_cache_size: Option<i32>, pub future_stamps: FutureStampPolicy, }
Expand description

Everything Database::open_tuned can be told, in one growable struct (0.12.12, W5.1, D-155).

§Why a struct rather than a fourth constructor

There were three — Database::open, Database::open_with_cadence, Database::open_with_clock — and each new knob added one more, with the combinatorics of the ones before it. 0.13.0 alone wanted three knobs (wal_autocheckpoint, and a page cache each for the writer and the readers), which is the point at which the naming stops being possible.

Setters plus #[non_exhaustive] are the whole design (0.15.13, W15.3, C-11, D-255). They make a new knob an additive change: callers write Tuning::default().cadence(..), and the fields that arrive after them are the ones they did not ask about. That is not a hypothetical — W5.1 shipped this struct with two fields, and W5.3/W5.4 added three more without touching a caller.

§Why the attribute needed the setters, and why 0.5.1’s answer was the

other one

D-155 specified #[non_exhaustive] for this struct and then could not ship it, on a fact that is still true: a #[non_exhaustive] struct cannot be built with literal syntax outside its own crate at all, and the functional-update form is literal syntax, so Tuning { cadence, ..Default::default() } is E0639 for every external caller — the exact expression the attribute was there to protect. (The rule differs from #[non_exhaustive] on an enum, which only forces a wildcard arm; CadencePolicy has kept it for that reason since W4.2.) D-155 named the two ways to have both — a builder with setters, or plain Default — and chose Default, because the field-literal form is the legible one.

What changed is not the argument but the deadline. Default alone leaves the growth additive only for callers who wrote ..Default::default(); a caller who wrote the exhaustive literal breaks on the next field. Before 1.0 that is a compile error with an obvious fix. After it, it is a major version — and this struct is the one in the crate whose whole documented purpose is to keep acquiring fields. So the release that is still allowed to break callers pays D-155’s other price and writes the setters, which is the half of its own analysis it declined at the time.

The fields stay pub and stay readable, and on a value you own they stay assignable: let mut t = Tuning::default(); t.cadence = ..; compiles outside this crate exactly as it did. What the attribute forbids is the literal, which is the one form that enumerates every field and therefore the one form a new field can break.

§The three constructors stay

They delegate here and are not deprecated. open(path) is the right call for most callers and should not acquire a warning for being the common case; the consolidation is about where the next knob goes, not about moving anyone.

let db = Database::open_tuned(
    "graph.db",
    Tuning::default().cadence(CadencePolicy::Disabled),
)
.await?;

Fields (Non-exhaustive)§

This struct is marked as non-exhaustive
Non-exhaustive structs could have additional fields added in future. Therefore, non-exhaustive structs cannot be constructed in external crates using the traditional Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.
§cadence: CadencePolicy

What the snapshot cadence should do. Defaults to SnapshotCadence::default, as Database::open does.

§clock: Option<Arc<dyn Clock>>

A clock to stamp recorded_at with, for tests (§5.1.2, D-062). None is SystemClock. Floored against the database exactly as Database::open_with_clock describes — read that before injecting one against a non-empty file.

§wal_autocheckpoint: WalCheckpointPolicy

When SQLite checkpoints the WAL on its own (0.12.14, W5.3, F-30).

Applied to the write connection, which is the only connection in this crate that commits, and therefore the only one whose autocheckpoint setting can ever fire. Pair WalCheckpointPolicy::Disabled with an explicit Database::checkpoint or the WAL grows without bound.

§writer_cache_size: Option<i32>

Page cache for the write connection, as SQLite’s cache_size (0.12.15, W5.4).

None leaves SQLite’s default of −2000, which is −2000 kibibytes, or 2 MB. Negative values are KiB and positive values are pages — that is SQLite’s convention and it is preserved rather than smoothed over, because a caller who knows the pragma should not have to discover that this crate redefined it. Some(-64_000) is 64 MB; Some(64_000) is 64,000 pages, which at the 4 KiB page size this crate gets is 256 MB.

The writer wants a large cache: it is one connection, it holds the write lock while it works, and every page it has to re-read from disk is time no other writer can use.

§Unlike the two above, None here is not a policy enum

Because SQLite’s default is a value rather than a mechanism. Absence still means “leave it alone” — it just happens that leaving this alone is expressible as not running a pragma, where leaving the automatic checkpointer alone required saying which of two things “alone” meant.

§reader_cache_size: Option<i32>

Page cache for every read-only connection: the shared Database::read_conn, the snapshot cadence’s own connection, and (since W5.5) each Database::diagnostic_conn (0.12.15, W5.4).

Same units as Self::writer_cache_size, and the same None.

Split from the writer’s because the profiles are opposite and one number cannot serve both. There is exactly one writer and it is long-lived, so its cache is a fixed cost paid once. Read-only connections are plural — the shared reader and the cadence’s — so a large value here is multiplied by however many exist, which is the wrong size for the one connection that holds the write lock.

The multiplier used to be unbounded and is not since 0.15.14 (W15.4, D-256): diagnostic_conn minted a connection per call, so a caller in a loop multiplied this number by their own call count. There is one such connection per Database now, so the count is three.

§future_stamps: FutureStampPolicy

What to do about a stored recorded_at in the future (0.13.5, W7.4, §3.4).

The clock floors itself at MAX(recorded_at) so stamps stay strictly increasing across restarts, which means one row from the future becomes this process’s floor and every stamp it issues inherits it — into rows the next open reads back. Defaults to refusing beyond crate::DEFAULT_FUTURE_STAMP_TOLERANCE, a day.

Like Self::wal_autocheckpoint and unlike the two cache sizes, this is a policy enum rather than an Option, for D-155’s reason: it guards an invariant, and a None that switches it off would switch it off for every caller who never heard of it.

Implementations§

Source§

impl Tuning

Source

pub fn cadence(self, cadence: CadencePolicy) -> Self

What the snapshot cadence should do — the cadence field.

Source

pub fn clock(self, clock: Arc<dyn Clock>) -> Self

Inject a clock — the clock field.

Takes the clock rather than an Option, because None is what Tuning::default already holds and a setter whose argument can undo itself invites clock(None) as a way of saying nothing. Database::open_with_clock documents the flooring this is subject to; read it before injecting one against a non-empty file.

Source

pub fn wal_autocheckpoint(self, policy: WalCheckpointPolicy) -> Self

When SQLite checkpoints the WAL on its own — the wal_autocheckpoint field.

Source

pub fn writer_cache_size(self, size: i32) -> Self

Page cache for the write connection, in SQLite’s units — the writer_cache_size field, which documents why negative means KiB and positive means pages.

Source

pub fn reader_cache_size(self, size: i32) -> Self

Page cache for every read-only connection — the reader_cache_size field, which documents why this is not the same number as the writer’s.

Source

pub fn future_stamps(self, policy: FutureStampPolicy) -> Self

What to do about a stored recorded_at in the future — the future_stamps field.

Trait Implementations§

Source§

impl Clone for Tuning

Source§

fn clone(&self) -> Tuning

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Tuning

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Tuning

Source§

fn default() -> Tuning

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoRequest<T> for T

Source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more