use crate::{AimDb, DbError, DbResult, RuntimeAdapter, RuntimeContext};
use aimdb_executor::Spawn;
use core::fmt::Debug;
#[cfg(not(feature = "std"))]
extern crate alloc;
#[cfg(not(feature = "std"))]
use alloc::boxed::Box;
#[cfg(feature = "std")]
use std::boxed::Box;
pub struct Database<A: RuntimeAdapter + aimdb_executor::Spawn + 'static> {
adapter: A,
aimdb: AimDb<A>,
}
impl<A: RuntimeAdapter + aimdb_executor::Spawn + 'static> Database<A> {
#[doc(hidden)]
pub fn inner_aimdb(&self) -> &AimDb<A> {
&self.aimdb
}
pub fn new(adapter: A, aimdb: AimDb<A>) -> DbResult<Self> {
#[cfg(feature = "tracing")]
tracing::info!("Initializing unified database with typed records");
Ok(Self { adapter, aimdb })
}
pub fn adapter(&self) -> &A {
&self.adapter
}
pub async fn produce<T>(&self, key: impl AsRef<str>, data: T) -> DbResult<()>
where
T: Send + 'static + Clone + core::fmt::Debug,
{
self.aimdb.produce(key, data).await
}
pub fn subscribe<T>(
&self,
key: impl AsRef<str>,
) -> DbResult<Box<dyn crate::buffer::BufferReader<T> + Send>>
where
T: Send + Sync + 'static + Debug + Clone,
{
self.aimdb.subscribe(key)
}
pub fn context(&self) -> RuntimeContext<A>
where
A: aimdb_executor::Runtime + Clone,
{
#[cfg(feature = "std")]
{
RuntimeContext::from_arc(std::sync::Arc::new(self.adapter.clone()))
}
#[cfg(not(feature = "std"))]
{
panic!("context() not supported in no_std without a static reference. To use context(), store your adapter in a static cell (e.g., StaticCell from portable-atomic or embassy-sync), or use adapter() directly.")
}
}
}
impl<A> Database<A>
where
A: RuntimeAdapter + Spawn,
{
pub fn spawn<F>(&self, future: F) -> DbResult<()>
where
F: core::future::Future<Output = ()> + Send + 'static,
{
#[cfg(feature = "tracing")]
tracing::debug!("Spawning service on database runtime");
self.adapter.spawn(future).map_err(DbError::from)?;
Ok(())
}
}