Skip to main content

SharedDb

Struct SharedDb 

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

Shared handle to an on-disk GraphDb. Clone is cheap and shares state.

§Group-commit write path

SharedDb::submit_batch routes mutations through a group-commit queue. A background drain thread batches concurrent submissions under a single WAL fsync, yielding throughput that scales with concurrency.

§Direct write path

SharedDb::write gives exclusive &mut GraphDb access for callers that need complex multi-step mutations (e.g. Cypher write queries). It acquires the WAL mutex first, then the RwLock write guard, satisfying the lock-order discipline described in the module doc.

§Event-sink deadlock

GraphDb::set_event_sink runs inside log_then_apply while the write guard is held. A sink must never call SharedDb::read or SharedDb::write on the same handle.

Implementations§

Source§

impl SharedDb

Source

pub fn open(dir: &Path) -> Result<Self>

Source

pub fn open_with_test_sync( dir: &Path, sync: impl Fn(&Path) -> Result<()> + Send + Sync + 'static, ) -> Result<Self>

Open with an injectable WAL sync function.

Allows tests to inject fsync failures through the live drain thread without requiring real filesystem manipulation. Not intended for production use; the test_sync name signals its purpose.

Source

pub fn read(&self) -> impl Deref<Target = GraphDb<RealFs>> + '_

Shared read access. Many readers may hold this concurrently.

Readers never acquire the WAL mutex — their p95 latency is unaffected by concurrent write or fsync activity.

§Deadlock warning

Do not hold a returned guard while calling any method on the same SharedDb; the RwLock is not re-entrant; doing so deadlocks.

Source

pub fn write(&self) -> WriteGuard<'_>

Exclusive write access.

Acquires the WAL mutex first, then the RwLock write guard, satisfying the lock order required by the fsync-failure contract (see module doc). The returned [WriteGuard] releases the RwLock before the WAL mutex on drop.

§Deadlock warning

Do not hold a returned guard while calling any method on the same SharedDb; the RwLock is not re-entrant; doing so deadlocks.

Source

pub fn reader(&self) -> ReaderSnapshot

Capture a lock-free ReaderSnapshot of the current db state.

Acquires the read lock only long enough to clone a handful of Arc handles. Subsequent reads on the returned snapshot are lock-free.

Source

pub fn submit_batch(&self, ops: Vec<BatchOp>) -> Result<(usize, usize)>

Enqueue a mutation batch for the group-committing writer.

Blocks until the containing group is durably committed (one WAL fsync per group under Strict policy). Submissions from concurrent callers are coalesced into groups of up to 256 items.

§Durability semantics

Under Strict policy (the default):

  • Each submission becomes a separate WAL Batch frame.
  • All frames in a group share one fsync — the caller unblocks only after that fsync.
  • Fsync failure: the drain thread truncates the WAL back to the pre-group offset and marks the database degraded. All submitters in the failed group and all subsequent callers receive Err. Data that was already in readers’ snapshots (observed between write-lock release and truncation) is not rolled back — equivalent to the Relaxed window for in-flight readers. Reopen the database to recover.
  • A crash between group fsyncs loses the entire unfsynced group, but never tears an individual submission (CRC-protected frame boundaries).

Under Relaxed policy (set via db.write().set_fsync_policy):

  • WAL frames are appended but NOT synced; caller unblocks after apply.
§Event ordering

Under Strict / Batched policy, subscription events fire AFTER the group fsync (durability before notification). Under Relaxed, events fire immediately after apply.

§FIFO ordering

Submissions from the same caller arrive FIFO at the queue. Across concurrent callers, drain order within a group is arbitrary, but each submission’s commit sequence is monotonically increasing.

§Returns

(nodes_inserted, edges_inserted) on success. An all-noop batch returns (0, 0).

Source

pub fn submit_batch_cas( &self, preconds: Vec<Precondition>, ops: Vec<BatchOp>, ) -> Result<(usize, usize)>

Like [submit_batch] but with compare-and-set preconditions.

The preconditions are evaluated by the drain thread under the same write guard as the batch apply — there is no TOCTOU window. If any precondition fails, the entire batch is rejected with core_storage::GraphError::CasConflict and no WAL frame is written.

See crate::Precondition for the full semantics.

Source

pub fn submit_batch_authz( &self, role: String, ops: Vec<BatchOp>, ) -> Result<(usize, usize)>

Like [submit_batch] but with role-scoped write authorization.

The drain thread resolves mask_for_role + scope under the same write guard as the mutation (§5 lock discipline: authz BEFORE any CAS preconditions, BEFORE the WAL write).

  • Role with write: NoneGraphError::RoleWriteDenied (endpoint not permitted) — maps to HTTP 403.
  • Scope / visibility violations inside the batch → GraphError::RoleWriteDenied with the appropriate §4.3 reason string.

All-or-nothing semantics: a single denied op rejects the entire batch with no WAL frame written.

Trait Implementations§

Source§

impl Clone for SharedDb

Source§

fn clone(&self) -> SharedDb

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

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

Source§

type ArchivedMetadata = ()

The archived version of the pointer metadata for this type.
Source§

fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata

Converts some archived metadata to the pointer metadata for itself.
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> 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, 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> LayoutRaw for T

Source§

fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>

Returns the layout of the type.
Source§

impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
where T: SharedNiching<N1, N2>, N1: Niching<T>, N2: Niching<T>,

Source§

unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool

Returns whether the given value has been niched. Read more
Source§

fn resolve_niched(out: Place<NichedOption<T, N1>>)

Writes data to out indicating that a T is niched.
Source§

impl<T> Pointee for T

Source§

type Metadata = ()

The metadata type for pointers and references to this type.
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, <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.