Skip to main content

StateStore

Trait StateStore 

Source
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>, Error>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             'life1: 'async_trait,
             Self: 'async_trait;
    fn save<'life0, 'life1, 'async_trait>(
        &'life0 self,
        key: &'life1 str,
        value: Value,
    ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             'life1: 'async_trait,
             Self: 'async_trait;

    // Provided method
    fn flush<'life0, 'async_trait>(
        &'life0 self,
    ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             Self: '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§

Source

fn load<'life0, 'life1, 'async_trait>( &'life0 self, key: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<Option<Value>, Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: '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).

Source

fn save<'life0, 'life1, 'async_trait>( &'life0 self, key: &'life1 str, value: Value, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Persist value under key, overwriting any previous snapshot.

Provided Methods§

Source

fn flush<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, Self: '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".

Implementors§