pub trait StateStore:
Send
+ Sync
+ 'static {
// Required methods
fn load<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Option<Value>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn save<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 str,
value: Value,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
// Provided method
fn flush<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait { ... }
}Expand description
A durable key/value store for framework state snapshots.
Implementors persist opaque serde_json::Value payloads keyed by a
string. The framework calls save after every
realised trade and on graceful shutdown, and load
once per symbol at startup. Keys are stable for the lifetime of a
(bot, symbol) pair.
§Object-safe + async
async_trait is used so Arc<dyn StateStore> works — the facade holds
the store behind a trait object and never names the concrete backend.
§Example
A trivial echo store backed by a Mutex<HashMap> — this is exactly
what InMemoryStore does. Real backends write to disk or a database.
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use async_trait::async_trait;
use rustrade_core::{Result, StateStore};
#[derive(Default)]
struct MapStore(Arc<Mutex<HashMap<String, serde_json::Value>>>);
#[async_trait]
impl StateStore for MapStore {
async fn load(&self, key: &str) -> Result<Option<serde_json::Value>> {
Ok(self.0.lock().unwrap().get(key).cloned())
}
async fn save(&self, key: &str, value: serde_json::Value) -> Result<()> {
self.0.lock().unwrap().insert(key.to_string(), value);
Ok(())
}
}Required Methods§
Sourcefn load<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Option<Value>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn load<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Option<Value>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Load the snapshot stored under key, or None if there is none.
A missing key is not an error — first-ever boots return None.
Reserve Error::Storage for genuine backend failures (I/O,
deserialization of a corrupt blob).
Provided Methods§
Sourcefn flush<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn flush<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Flush any buffered writes to durable storage.
The default is a no-op for stores that write through on every
save. Buffered backends override it; the
framework calls it once on graceful shutdown.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".