aimdb_persistence/backend.rs
1//! Persistence backend trait for AimDB.
2//!
3//! Defines the [`PersistenceBackend`] trait that concrete implementations
4//! (SQLite, Postgres, …) must fulfill.
5
6use core::future::Future;
7use core::pin::Pin;
8
9use serde_json::Value;
10
11use crate::error::PersistenceError;
12
13/// Type alias matching the pattern used throughout aimdb-core (no async_trait).
14pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
15
16/// A stored value returned by [`PersistenceBackend::query`].
17#[derive(Debug, Clone)]
18pub struct StoredValue {
19 /// The record name this value belongs to (e.g. `"accuracy::vienna"`).
20 pub record_name: String,
21 /// The JSON-serialized value.
22 pub value: Value,
23 /// Unix timestamp in milliseconds when the value was persisted.
24 pub stored_at: u64,
25}
26
27/// Parameters for [`PersistenceBackend::query`].
28#[derive(Debug, Clone, Default)]
29pub struct QueryParams {
30 /// For pattern queries: maximum number of results **per matching record**.
31 pub limit_per_record: Option<usize>,
32 /// Only return values stored at or after this timestamp (Unix ms).
33 pub start_time: Option<u64>,
34 /// Only return values stored at or before this timestamp (Unix ms).
35 pub end_time: Option<u64>,
36}
37
38/// Pluggable persistence backend.
39///
40/// Implementations run on a concrete async runtime (e.g. Tokio). The trait
41/// uses manual `BoxFuture` instead of `async_trait` for consistency with the
42/// rest of the AimDB codebase.
43pub trait PersistenceBackend: Send + Sync {
44 /// Store a JSON value for a record.
45 fn store<'a>(
46 &'a self,
47 record_name: &'a str,
48 value: &'a Value,
49 timestamp: u64,
50 ) -> BoxFuture<'a, Result<(), PersistenceError>>;
51
52 /// Query stored values, with optional pattern and time-range support.
53 ///
54 /// `record_pattern` supports `*` as a glob wildcard. For example,
55 /// `"accuracy::*"` matches all records whose name starts with `"accuracy::"`.
56 fn query<'a>(
57 &'a self,
58 record_pattern: &'a str,
59 params: QueryParams,
60 ) -> BoxFuture<'a, Result<Vec<StoredValue>, PersistenceError>>;
61
62 /// Initialize storage (create tables, indexes, …).
63 ///
64 /// Default: no-op. Backends that perform setup eagerly in `::new()`
65 /// (like `SqliteBackend`) do not need to override this.
66 fn initialize(&self) -> BoxFuture<'_, Result<(), PersistenceError>> {
67 Box::pin(async { Ok(()) })
68 }
69
70 /// Delete all rows older than `older_than` (Unix ms).
71 ///
72 /// Called automatically by the retention cleanup task registered during
73 /// `with_persistence()`. Can also be called explicitly.
74 fn cleanup(&self, older_than: u64) -> BoxFuture<'_, Result<u64, PersistenceError>>;
75}