Skip to main content

AimDbBuilder

Struct AimDbBuilder 

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

Database builder for producer-consumer pattern

Provides a fluent API for constructing databases with type-safe record registration. Set the runtime via .runtime(); a missing runtime is reported by build() like any other configuration mistake.

Implementations§

Source§

impl AimDbBuilder

Source

pub fn new() -> Self

Creates a new database builder without a runtime

Call .runtime() to set the runtime adapter.

Source

pub fn runtime(self, rt: Arc<impl RuntimeOps + 'static>) -> Self

Sets the runtime adapter.

Accepts any adapter implementing the dyn-safe RuntimeOps capability surface (TokioAdapter, EmbassyAdapter, WasmAdapter); the builder stores it as a value — no runtime type parameter.

Source

pub fn extensions(&self) -> &Extensions

Returns a shared reference to the extension storage.

External crates use this to retrieve state stored via extensions_mut().

Source

pub fn extensions_mut(&mut self) -> &mut Extensions

Returns a mutable reference to the extension storage.

Use this inside AimDbBuilderPersistExt (or similar) to store typed state that .persist() and AimDbQueryExt will later retrieve.

Source

pub fn on_start<F, Fut>(&mut self, f: F) -> &mut Self
where F: FnOnce(RuntimeContext) -> Fut + Send + 'static, Fut: Future<Output = ()> + Send + 'static,

Registers a task to be spawned after build() completes.

The closure receives the RuntimeContext and must return a future that runs for as long as needed (e.g. an infinite cleanup loop). Tasks are spawned in registration order, after all record tasks and connectors have been started.

Source

pub fn with_connector(self, builder: impl ConnectorBuilder + 'static) -> Self

Registers a connector builder, invoked during build.

This single entry point registers two kinds of connector — both implement ConnectorBuilder and are driven the same way:

  1. Data-plane links (MQTT / KNX / WebSocket): a record opts in with link_to("<scheme>://<topic>") / link_from(...), and the connector mirrors that record to/from the external topic. The connector’s scheme is what those links match against.
  2. Remote-access session connectors (UDS / serial / TCP): these expose AimDB itself over a transport so peers can introspect/subscribe/write.
    • The client half (e.g. UdsClient) dials a peer and does use link_to/link_from under its scheme — just like (1), the scheme is "uds" by default instead of "mqtt".
    • The server half (e.g. UdsServer) accepts connections and takes no links — registering it is how a server stands up remote access (this replaces the old with_remote_access(config)).
§Examples

Illustrative (not compiled: the connector types live in downstream crates aimdb-core cannot depend on):

ⓘ
// (1) data-plane link to an MQTT topic
let mut b = AimDbBuilder::new().runtime(rt)
    .with_connector(MqttConnector::new("mqtt://broker.local:1883"));
b.configure::<Temperature>("commands.temp", |r| {
    r.link_from("mqtt://commands/temp").with_deserializer(parse).finish();
});
b.build().await?;

// (2a) remote-access SERVER — no links, just expose this db over UDS
AimDbBuilder::new().runtime(rt)
    .with_connector(UdsServer::from_config(remote_config))
    .build().await?;

// (2b) remote-access CLIENT — mirror a record to a peer over UDS
let mut b = AimDbBuilder::new().runtime(rt)
    .with_connector(UdsClient::new("/run/aimdb.sock"));
b.configure::<Temp>("temp", |r| { r.with_remote_access().link_to("uds://temp"); });
b.build().await?;
Source

pub fn configure<T>( &mut self, key: impl RecordKey, f: impl FnOnce(&mut RecordRegistrar<'_, T>), ) -> &mut Self
where T: Send + Sync + 'static + Debug + Clone,

Configures a record type manually with a unique key

The key uniquely identifies this record instance. Multiple records of the same type can exist with different keys (e.g., “sensor.temperature.room1” and “sensor.temperature.room2”).

§Arguments
  • key - A unique identifier for this record. Can be a string literal, StringKey, or any type implementing RecordKey (including user-defined enum keys).
  • f - Configuration closure
Source

pub async fn run(self) -> DbResult<()>

Builds the database and drives every collected future to completion.

Convenience wrapper for the common case: call build(), then immediately runner.run().await. The database handle is dropped on exit.

For programmatic access to the handle (manual subscriptions, holding the AimDb for other uses), prefer build() directly.

§Returns

DbResult<()> — Ok once the database starts; the call then blocks until every future the runner is driving has completed (typically forever).

Source

pub async fn build(self) -> DbResult<(AimDb, AimDbRunner)>

Builds the database and returns a (handle, runner) pair.

build() collects every future the database needs to drive (producer services, consumer taps, transforms with fan-in forwarders, connectors, remote-access supervisor, on_start tasks) into the AimDbRunner returned alongside the clone-able AimDb handle. No background work runs until runner.run().await is awaited.

Use this when you need programmatic access to the handle for manual subscriptions or production. For typical services, use .run().await which calls build() and runner.run() for you.

Connector Setup: Connectors are constructed during build() from the ConnectorBuilders previously registered via .with_connector(). Their driving futures are appended to the runner.

§Returns

DbResult<(AimDb, AimDbRunner)> — the handle (cloneable) and the non-Clone runner that owns the collected futures.

§Errors

build() is the single surface for configuration mistakes: everything recorded during configuration (conflicting .source()/.transform()/ .link_from(), missing serializers, unregistered schemes, …) plus the build-time checks here (record validation, linked records without a buffer, duplicate keys, dependency-graph cycles) is collected and returned as one DbError::InvalidConfiguration carrying all findings — one run surfaces every mistake.

Trait Implementations§

Source§

impl Default for AimDbBuilder

Source§

fn default() -> Self

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