Development Documentation (main branch) - For stable release docs, see docs.rs/eidetica
Skip to main content

SqlxBackend

Struct SqlxBackend 

Source
pub struct SqlxBackend { /* private fields */ }
Expand description

SQL-based backend implementing BackendImpl using sqlx.

This backend supports both SQLite and PostgreSQL through sqlx’s AnyPool.

§Concurrency

SqlxBackend is Send + Sync as required by BackendImpl. The underlying sqlx pool handles connection pooling and thread safety. Each backend owns its persistent storage namespace exclusively for its lifetime. Share one backend through the Eidetica service rather than opening the same storage directly.

§Test Isolation

For PostgreSQL, each backend instance can use its own schema for test isolation. Use connect_postgres_isolated() to create an isolated backend for testing.

ⓘ
use eidetica::backend::database::SqlxBackend;

fn cannot_escape_pool(backend: SqlxBackend) {
    let _ = backend.pool();
}

Implementations§

Source§

impl SqlxBackend

Source

pub fn kind(&self) -> DbKind

Get the database kind.

Source

pub fn is_sqlite(&self) -> bool

Check if this backend is using SQLite.

Source

pub fn is_postgres(&self) -> bool

Check if this backend is using PostgreSQL.

Source§

impl SqlxBackend

Register a one-shot pause gate for the given staging namespace.

The next stage_store_state_records call for this namespace signals the gate after validating its token and waits (bounded) for StoreStateStagePause::release before writing any records. Returns the gate the test drives.

Source§

impl SqlxBackend

Source

pub async fn open_sqlite<P: AsRef<Path>>(path: P) -> Result<Self>

Open a SQLite database at the given path.

Creates the database file and schema if they don’t exist.

§Arguments
  • path - Path to the SQLite database file
§Example
ⓘ
use eidetica::backend::database::sql::SqlxBackend;

#[tokio::main]
async fn main() {
    let backend = SqlxBackend::open_sqlite("my_database.db").await.unwrap();
}
Source

pub async fn connect_sqlite(url: &str) -> Result<Self>

Connect to a SQLite database using a connection URL.

§Arguments
  • url - SQLite connection URL (e.g., “sqlite:./my.db”)
Source

pub async fn sqlite_in_memory() -> Result<Self>

Create an in-memory SQLite database (async).

The database exists only for the lifetime of this backend instance. Useful for testing.

§Example
ⓘ
use eidetica::backend::database::sql::SqlxBackend;

#[tokio::main]
async fn main() {
    let backend = SqlxBackend::sqlite_in_memory().await.unwrap();
}
Source§

impl SqlxBackend

Source

pub async fn connect_postgres(url: &str) -> Result<Self>

Connect to a PostgreSQL database using a connection URL.

This connects to the default (public) schema. For test isolation, use connect_postgres_isolated() instead.

§Arguments
  • url - PostgreSQL connection URL (e.g., “postgres://user:pass@localhost/dbname”)
§Example
ⓘ
use eidetica::backend::database::sql::SqlxBackend;

let backend = SqlxBackend::connect_postgres("postgres://localhost/eidetica").await.unwrap();
Source

pub async fn connect_postgres_isolated(url: &str) -> Result<Self>

Connect to a PostgreSQL database with test isolation.

Creates a unique schema for this backend instance, ensuring tests don’t interfere with each other when run in parallel.

§Arguments
  • url - PostgreSQL connection URL (e.g., “postgres://user:pass@localhost/dbname”)
§Example
ⓘ
use eidetica::backend::database::sql::SqlxBackend;

let backend = SqlxBackend::connect_postgres_isolated("postgres://localhost/eidetica").await.unwrap();
// This backend uses its own isolated schema

Trait Implementations§

Source§

impl BackendImpl for SqlxBackend

Source§

fn resolve_store_state<'life0, 'life1, 'async_trait>( &'life0 self, request: &'life1 StoreStateRequest, ) -> Pin<Box<dyn Future<Output = Result<Option<RecordView>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Look up the published cached state for an exact request. Private builds are never returned.
Source§

fn begin_store_state_staging<'life0, 'async_trait>( &'life0 self, request: StoreStateRequest, ) -> Pin<Box<dyn Future<Output = Result<StagingToken>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Start a private build for a later atomic publish. The build is invisible to readers until published.
Source§

fn stage_store_state_records<'life0, 'life1, 'async_trait>( &'life0 self, token: &'life1 StagingToken, records: RecordMutations, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Add a chunk of records to a private build.
Source§

fn publish_store_state<'life0, 'async_trait>( &'life0 self, token: StagingToken, ) -> Pin<Box<dyn Future<Output = Result<RecordView>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Atomically publish a finished build as the cached state for its target. Read more
Source§

fn abort_store_state<'life0, 'async_trait>( &'life0 self, token: StagingToken, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Discard a private build. Aborting an already-published token is harmless.
Source§

fn store_state_record_get<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, view: &'life1 RecordView, key: &'life2 [u8], ) -> Pin<Box<dyn Future<Output = Result<Option<Vec<u8>>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Read one exact record from published records. A missing key reads as None, never an error.
Source§

fn store_state_record_scan<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, view: &'life1 RecordView, range: &'life2 RecordRange, after: Option<&'life3 [u8]>, limit: usize, ) -> Pin<Box<dyn Future<Output = Result<RecordPage>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Read one ordered page of records. A limit of zero yields an empty page with no continuation. A view that no longer identifies published records errors with InvalidStoreStateView, never an empty page.
Source§

fn clear_derived_store_state<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Clear cached derived state. Authoritative state and private builds are untouched.
Source§

fn reset_local_verification<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Explicit offline reset of local trust decisions and disposable Store state. Preserves immutable Entries and authoritative Store state. Unsupported backends fail without a partial reset.
Source§

fn get<'life0, 'life1, 'async_trait>( &'life0 self, id: &'life1 ID, ) -> Pin<Box<dyn Future<Output = Result<Entry>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Retrieves an entry by its unique content-addressable ID. Read more
Source§

fn get_verification_status<'life0, 'life1, 'async_trait>( &'life0 self, id: &'life1 ID, ) -> Pin<Box<dyn Future<Output = Result<VerificationStatus>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Gets the verification status of an entry. Read more
Source§

fn put<'life0, 'async_trait>( &'life0 self, entry: Entry, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Stores an entry. Read more
Source§

fn update_verification_status<'life0, 'life1, 'async_trait>( &'life0 self, id: &'life1 ID, verification_status: VerificationStatus, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Updates the verification status of an existing entry. Read more
Source§

fn get_entries_by_verification_status<'life0, 'async_trait>( &'life0 self, status: VerificationStatus, ) -> Pin<Box<dyn Future<Output = Result<Vec<ID>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Gets all entries with a specific verification status. Read more
Source§

fn snapshot<'life0, 'life1, 'async_trait>( &'life0 self, tree: &'life1 ID, ) -> Pin<Box<dyn Future<Output = Result<Snapshot>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Returns the current Snapshot of tree — its sorted, deduplicated set of DAG tips. Read more
Source§

fn store_snapshot<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, tree: &'life1 ID, store: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<Snapshot>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Returns the snapshot of a specific store within a given tree. Read more
Source§

fn store_snapshot_at<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, tree: &'life1 ID, store: &'life2 str, main_snapshot: &'life3 Snapshot, ) -> Pin<Box<dyn Future<Output = Result<Snapshot>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Returns the store snapshot as of a specific main-tree snapshot. Read more
Source§

fn all_roots<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<Vec<ID>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Retrieves the IDs of all top-level root entries stored in the backend. Read more
Source§

fn find_merge_base<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, tree: &'life1 ID, store: &'life2 str, entry_ids: &'life3 [ID], ) -> Pin<Box<dyn Future<Output = Result<Option<ID>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Finds the merge base (common dominator) of the given entry IDs within a store. Read more
Source§

fn as_any(&self) -> &dyn Any

Returns a reference to the backend instance as a dynamic Any type. Read more
Source§

fn get_tree<'life0, 'life1, 'async_trait>( &'life0 self, tree: &'life1 ID, ) -> Pin<Box<dyn Future<Output = Result<Vec<Entry>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Retrieves all entries belonging to a specific tree, sorted topologically. Read more
Source§

fn get_store<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, tree: &'life1 ID, store: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<Vec<Entry>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Retrieves all entries belonging to a specific store within a tree, sorted topologically. Read more
Source§

fn get_tree_from_tips<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, tree: &'life1 ID, tips: &'life2 [ID], ) -> Pin<Box<dyn Future<Output = Result<Vec<Entry>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Retrieves all entries belonging to a specific tree up to the given tips, sorted topologically. Read more
Source§

fn store_at<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, tree: &'life1 ID, store: &'life2 str, snapshot: &'life3 Snapshot, ) -> Pin<Box<dyn Future<Output = Result<Vec<Entry>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Retrieves all entries belonging to a specific store at the given snapshot, sorted topologically. Read more
Source§

fn get_sorted_store_parents<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, tree_id: &'life1 ID, entry_id: &'life2 ID, store: &'life3 str, ) -> Pin<Box<dyn Future<Output = Result<Vec<ID>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Get the store parent IDs for a specific entry and store, sorted by height then ID. Read more
Source§

fn get_path_from_to<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>( &'life0 self, tree_id: &'life1 ID, store: &'life2 str, from_id: Option<&'life3 ID>, to_ids: &'life4 [ID], ) -> Pin<Box<dyn Future<Output = Result<Vec<ID>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, 'life4: 'async_trait,

Gets all entries between one entry and multiple target entries (exclusive of start, inclusive of targets). Read more
Source§

fn get_instance_metadata<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<Option<InstanceMetadata>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Get the instance metadata. Read more
Source§

fn set_instance_metadata<'life0, 'life1, 'async_trait>( &'life0 self, metadata: &'life1 InstanceMetadata, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Set the instance metadata. Read more
Source§

fn get_instance_secrets<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<Option<InstanceSecrets>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Get the instance secrets (private key material). Read more
Source§

fn set_instance_secrets<'life0, 'life1, 'async_trait>( &'life0 self, secrets: &'life1 InstanceSecrets, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Set the instance secrets (private key material). Read more
Source§

fn check_targets_reachable_from<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, tree: &'life1 ID, from: &'life2 [ID], targets: &'life3 [ID], ) -> Pin<Box<dyn Future<Output = Result<Reachability>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Within tree, decide whether every entry in targets is an ancestor-or-equal of some entry in from — i.e. whether the from snapshot is at-or-ahead-of the targets snapshot. Read more
Source§

impl Drop for SqlxBackend

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. 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<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

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

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

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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

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

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

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

Source§

type Error = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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.
§

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

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

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
§

fn with_current_subscriber(self) -> WithDispatch<Self>

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

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

§

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

§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

§

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