stasis-rs 0.1.0

Durable AI orchestration framework with runtime jobs, lineage, and memory integration
Documentation
use std::collections::HashMap;
use std::sync::{Arc, RwLock};

use async_trait::async_trait;
use chrono::Utc;

use crate::domain::errors::{Result, StasisError};
use crate::domain::runtime::delivery_endpoint::{DeliveryEndpoint, NewDeliveryEndpoint};
use crate::ports::outbound::runtime::delivery_endpoint_store::DeliveryEndpointStore;

#[derive(Clone, Default)]
pub struct InMemoryDeliveryEndpointStore {
    endpoints: Arc<RwLock<HashMap<String, DeliveryEndpoint>>>,
}

#[async_trait]
impl DeliveryEndpointStore for InMemoryDeliveryEndpointStore {
    async fn insert(&self, endpoint: NewDeliveryEndpoint) -> Result<DeliveryEndpoint> {
        let mut endpoints = self.endpoints.write().map_err(|_| {
            StasisError::PortFailure("delivery endpoint store lock poisoned".to_string())
        })?;

        if endpoints.contains_key(&endpoint.endpoint_id) {
            return Err(StasisError::PortFailure(format!(
                "delivery endpoint already exists: {}",
                endpoint.endpoint_id
            )));
        }

        let record = endpoint.into_record();
        endpoints.insert(record.endpoint_id.clone(), record.clone());
        Ok(record)
    }

    async fn get(&self, endpoint_id: &str) -> Result<Option<DeliveryEndpoint>> {
        let endpoints = self.endpoints.read().map_err(|_| {
            StasisError::PortFailure("delivery endpoint store lock poisoned".to_string())
        })?;

        Ok(endpoints.get(endpoint_id).cloned())
    }

    async fn list(&self) -> Result<Vec<DeliveryEndpoint>> {
        let endpoints = self.endpoints.read().map_err(|_| {
            StasisError::PortFailure("delivery endpoint store lock poisoned".to_string())
        })?;

        let mut out = endpoints.values().cloned().collect::<Vec<_>>();
        out.sort_by(|left, right| left.endpoint_id.cmp(&right.endpoint_id));
        Ok(out)
    }

    async fn set_enabled(&self, endpoint_id: &str, enabled: bool) -> Result<bool> {
        let mut endpoints = self.endpoints.write().map_err(|_| {
            StasisError::PortFailure("delivery endpoint store lock poisoned".to_string())
        })?;

        let Some(endpoint) = endpoints.get_mut(endpoint_id) else {
            return Ok(false);
        };

        endpoint.enabled = enabled;
        endpoint.updated_at = Utc::now();
        Ok(true)
    }
}