AimDb

Struct AimDb 

Source
pub struct AimDb<R: Spawn + 'static> { /* private fields */ }
Expand description

Producer-consumer database

A database instance with type-safe record registration and cross-record communication via the Emitter pattern. The type parameter R represents the runtime adapter (e.g., TokioAdapter, EmbassyAdapter).

See examples/ for usage.

§Examples

use aimdb_tokio_adapter::TokioAdapter;

let runtime = Arc::new(TokioAdapter);
let db: AimDb<TokioAdapter> = AimDbBuilder::new()
    .runtime(runtime)
    .register_record::<Temperature>(&TemperatureConfig)
    .build()?;

Implementations§

Source§

impl<R: Spawn + 'static> AimDb<R>

Source

pub async fn build_with( rt: Arc<R>, f: impl FnOnce(&mut AimDbBuilder<R>), ) -> DbResult<()>

Builds a database with a closure-based builder pattern

Source

pub fn spawn_task<F>(&self, future: F) -> DbResult<()>
where F: Future<Output = ()> + Send + 'static,

Spawns a task using the database’s runtime adapter

This method provides direct access to the runtime’s spawn capability.

§Arguments
  • future - The future to spawn
§Returns

DbResult<()> - Ok if the task was spawned successfully

Source

pub async fn produce<T>(&self, value: T) -> DbResult<()>
where T: Send + 'static + Debug + Clone,

Produces a value for a record type

Writes the value to the record’s buffer and triggers all consumers.

Source

pub fn subscribe<T>(&self) -> DbResult<Box<dyn BufferReader<T> + Send>>
where T: Send + Sync + 'static + Debug + Clone,

Subscribes to a record type’s buffer

Creates a subscription to the configured buffer for the given record type. Returns a boxed reader for receiving values asynchronously.

§Example
let mut reader = db.subscribe::<Temperature>()?;

loop {
    match reader.recv().await {
        Ok(temp) => println!("Temperature: {:.1}°C", temp.celsius),
        Err(_) => break,
    }
}
Source

pub fn producer<T>(&self) -> Producer<T, R>
where T: Send + 'static + Debug + Clone,

Creates a type-safe producer for a specific record type

Returns a Producer<T, R> that can only produce values of type T. This is the recommended way to pass database access to producer services, following the principle of least privilege.

§Example
let db = builder.build()?;
let temp_producer = db.producer::<Temperature>();

// Pass to service - it can only produce Temperature values
runtime.spawn(temperature_service(ctx, temp_producer)).unwrap();
Source

pub fn consumer<T>(&self) -> Consumer<T, R>
where T: Send + Sync + 'static + Debug + Clone,

Creates a type-safe consumer for a specific record type

Returns a Consumer<T, R> that can only subscribe to values of type T. This is the recommended way to pass database access to consumer services, following the principle of least privilege.

§Example
let db = builder.build()?;
let temp_consumer = db.consumer::<Temperature>();

// Pass to service - it can only consume Temperature values
runtime.spawn(temperature_monitor(ctx, temp_consumer)).unwrap();
Source

pub fn runtime(&self) -> &R

Returns a reference to the runtime adapter

Provides direct access to the concrete runtime type.

Source

pub fn list_records(&self) -> Vec<RecordMetadata>

Lists all registered records (std only)

Returns metadata for all registered records, useful for remote access introspection. Available only when the std feature is enabled.

§Example
let records = db.list_records();
for record in records {
    println!("Record: {} ({})", record.name, record.type_id);
}
Source

pub fn try_latest_as_json(&self, record_name: &str) -> Option<Value>

Try to get record’s latest value as JSON by name (std only)

Convenience wrapper around AimDbInner::try_latest_as_json().

§Arguments
  • record_name - The full Rust type name (e.g., “server::Temperature”)
§Returns

Some(JsonValue) with current value, or None if unavailable

Source

pub fn set_record_from_json( &self, record_name: &str, json_value: Value, ) -> DbResult<()>

Sets a record value from JSON (remote access API)

Deserializes JSON and produces the value to the record’s buffer.

SAFETY: Enforces “No Producer Override” rule - only works for configuration records without active producers.

§Arguments
  • record_name - Full Rust type name
  • json_value - JSON value to set
§Returns

Ok(()) on success, error if record not found, has producers, or deserialization fails

§Example (internal use)
db.set_record_from_json("AppConfig", json!({"debug": true}))?;
Source

pub fn subscribe_record_updates( &self, type_id: TypeId, queue_size: usize, ) -> DbResult<(Receiver<Value>, Sender<()>)>

Subscribe to record updates as JSON stream (std only)

Creates a subscription to a record’s buffer and forwards updates as JSON to a bounded channel. This is used internally by the remote access protocol for implementing record.subscribe.

§Architecture

Spawns a consumer task that:

  1. Subscribes to the record’s buffer using the existing buffer API
  2. Reads values as they arrive
  3. Serializes each value to JSON
  4. Sends JSON values to a bounded channel (with backpressure handling)
  5. Terminates when either:
    • The cancel signal is received (unsubscribe)
    • The channel receiver is dropped (client disconnected)
§Arguments
  • type_id - TypeId of the record to subscribe to
  • queue_size - Size of the bounded channel for this subscription
§Returns

Ok((receiver, cancel_tx)) where:

  • receiver: Bounded channel receiver for JSON values
  • cancel_tx: One-shot sender to cancel the subscription

Err if:

  • Record not found for the given TypeId
  • Record not configured with .with_serialization()
  • Failed to subscribe to buffer
§Example (internal use)
let type_id = TypeId::of::<Temperature>();
let (mut rx, cancel_tx) = db.subscribe_record_updates(type_id, 100)?;

// Read events
while let Some(json_value) = rx.recv().await {
    // Forward to client...
}

// Cancel subscription
let _ = cancel_tx.send(());

Trait Implementations§

Source§

impl<R: Spawn + 'static> Clone for AimDb<R>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

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

Performs copy-assignment from source. Read more

Auto Trait Implementations§

§

impl<R> Freeze for AimDb<R>

§

impl<R> !RefUnwindSafe for AimDb<R>

§

impl<R> Send for AimDb<R>

§

impl<R> Sync for AimDb<R>

§

impl<R> Unpin for AimDb<R>

§

impl<R> !UnwindSafe for AimDb<R>

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