Skip to main content

DatabaseBackend

Trait DatabaseBackend 

Source
pub trait DatabaseBackend:
    Send
    + Sync
    + Debug
    + 'static {
Show 17 methods // Required methods fn engine_id(&self) -> &'static str; fn capabilities(&self) -> BackendCapabilities; fn execute_compiled_query<'life0, 'life1, 'async_trait>( &'life0 self, compiled: &'life1 CompiledQuery, ) -> Pin<Box<dyn Future<Output = Result<Vec<Value>, Error>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait; fn get_record<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, table: &'life1 str, id: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<Option<Value>, Error>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait; fn create_record<'life0, 'life1, 'async_trait>( &'life0 self, table: &'life1 str, content: Value, ) -> Pin<Box<dyn Future<Output = Result<Value, Error>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait; fn update_record<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, table: &'life1 str, id: &'life2 str, content: Value, ) -> Pin<Box<dyn Future<Output = Result<Value, Error>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait; fn upsert_record<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, table: &'life1 str, id: &'life2 str, content: Value, ) -> Pin<Box<dyn Future<Output = Result<Value, Error>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait; fn delete_record<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, table: &'life1 str, id: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait; fn relate_edge<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, from: &'life1 RecordId, edge_table: &'life2 str, to: &'life3 RecordId, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, Self: 'async_trait; fn unrelate_edge<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, from: &'life1 RecordId, edge_table: &'life2 str, to: &'life3 RecordId, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, Self: 'async_trait; fn get_edge_targets<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, from: &'life1 RecordId, edge_table: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<Vec<RecordId>, Error>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait; // Provided methods fn use_namespace<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, ns: &'life1 str, db_name: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait { ... } fn ensure_schemaless_table<'life0, 'life1, 'async_trait>( &'life0 self, table: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait { ... } fn merge_record<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, table: &'life1 str, id: &'life2 str, patch: Value, ) -> Pin<Box<dyn Future<Output = Result<Value, Error>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait { ... } fn define_unique_index<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, table: &'life1 str, field: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait { ... } fn ttl_capability(&self) -> BackendTtlCapability { ... } fn apply_ttl_policy<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, _table: &'life1 str, _policy: &'life2 SchemaTtlPolicy, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait { ... }
}
Expand description

Storage engine behind Valence: CRUD, compiled queries, and graph edges.

valence-core defines this trait only — no engine SDKs. Third-party adapters implement it in separate crates and register instances on crate::ValenceBuilder.

ConcernContract
engine_idOpen slug (not a closed enum)
capabilitiesMerge/graph support + telemetry label
CRUD / queries / edges / TTLPer-method contracts below

Router keys combine a logical name with engine_id via crate::router_key().

§Implementing a published adapter

  1. Depend on valence-core only (+ async-trait, etc.).
  2. impl DatabaseBackend and export pub const ENGINE_ID: &str.
  3. Export a schema evaluator, e.g. pub const PRIMARY: DatabaseFromEngine = Database::from_engine("primary", ENGINE_ID).
  4. Optional: XBackend::builder() with explicit setters; from_env_defaults() fills unset fields only.
  5. Host wires with .add_backend("primary", Arc::new(adapter)) — no facade feature.

Reference: examples/acme-valence-backend-stub.

§Examples

use std::sync::Arc;
use valence_backend_mem::{InMemoryBackend, ENGINE_ID};
use valence_core::{DatabaseBackend, Valence};

let backend = Arc::new(InMemoryBackend::new());
assert_eq!(backend.engine_id(), ENGINE_ID);
let valence = Valence::builder()
    .add_backend("default", backend)
    .build()
    .expect("build");
assert_eq!(
    valence.active_backend().unwrap().engine_id(),
    ENGINE_ID
);

Required Methods§

Source

fn engine_id(&self) -> &'static str

Stable open engine slug for router keys (see crate::router_key()).

First-party constants live in crate::KnownEngines for ergonomics — that is not a closed set; third-party crates define their own slugs.

Source

fn capabilities(&self) -> BackendCapabilities

Adapter capabilities for contract tests and telemetry.

Source

fn execute_compiled_query<'life0, 'life1, 'async_trait>( &'life0 self, compiled: &'life1 CompiledQuery, ) -> Pin<Box<dyn Future<Output = Result<Vec<Value>, Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Execute a compiled admin/query statement and return JSON rows.

Contract: must honor parameter binding in compiled; empty result sets return Ok(vec![]).

Source

fn get_record<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, table: &'life1 str, id: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<Option<Value>, Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait,

Fetch one record by primary key.

Contract: returns Ok(None) when the row does not exist.

Source

fn create_record<'life0, 'life1, 'async_trait>( &'life0 self, table: &'life1 str, content: Value, ) -> Pin<Box<dyn Future<Output = Result<Value, Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Insert a new record; content must include any required fields.

Contract: returns the persisted row (including server-assigned fields when applicable).

Source

fn update_record<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, table: &'life1 str, id: &'life2 str, content: Value, ) -> Pin<Box<dyn Future<Output = Result<Value, Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait,

Replace an existing record by id.

Contract: returns the updated row; errors when the id is missing unless the adapter supports upsert semantics via Self::upsert_record.

Source

fn upsert_record<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, table: &'life1 str, id: &'life2 str, content: Value, ) -> Pin<Box<dyn Future<Output = Result<Value, Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait,

Create or replace a record by explicit id.

Source

fn delete_record<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, table: &'life1 str, id: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait,

Delete one record by primary key.

Contract: succeeds when the row is already absent (idempotent delete).

Source

fn relate_edge<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, from: &'life1 RecordId, edge_table: &'life2 str, to: &'life3 RecordId, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, Self: 'async_trait,

Create a directed graph edge from from to to through edge_table.

Source

fn unrelate_edge<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, from: &'life1 RecordId, edge_table: &'life2 str, to: &'life3 RecordId, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, Self: 'async_trait,

Remove a directed graph edge.

Contract: idempotent when the edge does not exist.

Source

fn get_edge_targets<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, from: &'life1 RecordId, edge_table: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<Vec<RecordId>, Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait,

List target record ids reachable via outgoing edges in edge_table.

Provided Methods§

Source

fn use_namespace<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, ns: &'life1 str, db_name: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait,

Select namespace/database on engines that support multi-tenant routing.

Contract: default implementation is a no-op; remote adapters may override.

Source

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

Ensure a schemaless table exists before first write.

Contract: default implementation is a no-op; adapters may create tables lazily elsewhere.

Source

fn merge_record<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, table: &'life1 str, id: &'life2 str, patch: Value, ) -> Pin<Box<dyn Future<Output = Result<Value, Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait,

Patch an existing record with a partial JSON object.

Contract: default returns Error::Internal — override when BackendCapabilities::supports_merge is true.

Source

fn define_unique_index<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, table: &'life1 str, field: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait,

Define a unique index on table.field when the engine supports DDL.

Contract: default returns Error::Internal.

Source

fn ttl_capability(&self) -> BackendTtlCapability

Whether this adapter can apply schema TTL policies natively.

Source

fn apply_ttl_policy<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, _table: &'life1 str, _policy: &'life2 SchemaTtlPolicy, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait,

Apply a schema TTL policy to table when supported.

Contract: default is a no-op.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementations on Foreign Types§

Source§

impl DatabaseBackend for FleetRedisBackend

Source§

fn engine_id(&self) -> &'static str

Source§

fn capabilities(&self) -> BackendCapabilities

Source§

fn execute_compiled_query<'life0, 'life1, 'async_trait>( &'life0 self, compiled: &'life1 CompiledQuery, ) -> Pin<Box<dyn Future<Output = Result<Vec<Value>, Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, FleetRedisBackend: 'async_trait,

Source§

fn ensure_schemaless_table<'life0, 'life1, 'async_trait>( &'life0 self, table: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, FleetRedisBackend: 'async_trait,

Source§

fn get_record<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, table: &'life1 str, id: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<Option<Value>, Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, FleetRedisBackend: 'async_trait,

Source§

fn create_record<'life0, 'life1, 'async_trait>( &'life0 self, table: &'life1 str, content: Value, ) -> Pin<Box<dyn Future<Output = Result<Value, Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, FleetRedisBackend: 'async_trait,

Source§

fn update_record<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, table: &'life1 str, id: &'life2 str, content: Value, ) -> Pin<Box<dyn Future<Output = Result<Value, Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, FleetRedisBackend: 'async_trait,

Source§

fn merge_record<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, table: &'life1 str, id: &'life2 str, patch: Value, ) -> Pin<Box<dyn Future<Output = Result<Value, Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, FleetRedisBackend: 'async_trait,

Source§

fn upsert_record<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, table: &'life1 str, id: &'life2 str, content: Value, ) -> Pin<Box<dyn Future<Output = Result<Value, Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, FleetRedisBackend: 'async_trait,

Source§

fn delete_record<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, table: &'life1 str, id: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, FleetRedisBackend: 'async_trait,

Source§

fn relate_edge<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, from: &'life1 RecordId, edge_table: &'life2 str, to: &'life3 RecordId, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, FleetRedisBackend: 'async_trait,

Source§

fn unrelate_edge<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, from: &'life1 RecordId, edge_table: &'life2 str, to: &'life3 RecordId, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, FleetRedisBackend: 'async_trait,

Source§

fn get_edge_targets<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, from: &'life1 RecordId, edge_table: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<Vec<RecordId>, Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, FleetRedisBackend: 'async_trait,

Source§

fn define_unique_index<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, table: &'life1 str, field: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, FleetRedisBackend: 'async_trait,

Implementors§