arqen 0.1.0

Backend infrastructure for agent-ready applications
Documentation
use async_trait::async_trait;
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThingdObject {
    pub id: String,
    pub collection: String,
    pub data: serde_json::Value,
    pub created_at: String,
    pub updated_at: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThingdEvent {
    pub id: String,
    pub stream: String,
    pub event_type: String,
    pub data: serde_json::Value,
    pub timestamp: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThingdJob {
    pub id: String,
    pub queue: String,
    pub payload: serde_json::Value,
    pub state: JobState,
    pub attempts: u32,
    pub max_retries: u32,
    pub lease_expires_at: Option<String>,
    pub created_at: String,
    pub updated_at: String,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum JobState {
    Queued,
    Leased,
    Completed,
    Retrying,
    Dead,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThingdLink {
    pub id: String,
    pub source_id: String,
    pub target_id: String,
    pub relation: String,
    pub created_at: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThingdFilter {
    pub field: String,
    pub operator: FilterOperator,
    pub value: serde_json::Value,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum FilterOperator {
    Eq,
    Ne,
    Gt,
    Lt,
    Gte,
    Lte,
    Contains,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchOptions {
    pub limit: usize,
    pub offset: usize,
    pub filters: Vec<ThingdFilter>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchResults {
    pub items: Vec<ThingdObject>,
    pub total: usize,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ThingdOperation {
    Put {
        collection: String,
        id: String,
        data: serde_json::Value,
    },
    Delete {
        collection: String,
        id: String,
    },
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThingdOperationResult {
    pub success: bool,
    pub error: Option<String>,
}

#[async_trait]
pub trait ThingdBackend: Send + Sync {
    async fn get_object(
        &self,
        collection: &str,
        id: &str,
    ) -> Result<Option<ThingdObject>, crate::core::AppError>;
    async fn put_object(
        &self,
        collection: &str,
        id: &str,
        data: serde_json::Value,
    ) -> Result<ThingdObject, crate::core::AppError>;
    async fn delete_object(&self, collection: &str, id: &str) -> Result<(), crate::core::AppError>;
    async fn query_objects(
        &self,
        collection: &str,
        filter: Option<ThingdFilter>,
    ) -> Result<Vec<ThingdObject>, crate::core::AppError>;
    async fn count_objects(&self, collection: &str) -> Result<usize, crate::core::AppError>;

    async fn batch_write(
        &self,
        operations: Vec<ThingdOperation>,
    ) -> Result<Vec<ThingdOperationResult>, crate::core::AppError>;

    async fn append_event(
        &self,
        stream: &str,
        event_type: &str,
        data: serde_json::Value,
    ) -> Result<ThingdEvent, crate::core::AppError>;
    async fn read_events(
        &self,
        stream: &str,
        from: Option<String>,
        limit: usize,
    ) -> Result<Vec<ThingdEvent>, crate::core::AppError>;

    async fn push_job(
        &self,
        queue: &str,
        payload: serde_json::Value,
        max_retries: u32,
    ) -> Result<ThingdJob, crate::core::AppError>;
    async fn claim_job(
        &self,
        queue: &str,
        worker_id: &str,
        lease_seconds: u32,
    ) -> Result<Option<ThingdJob>, crate::core::AppError>;
    async fn complete_job(&self, queue: &str, job_id: &str) -> Result<(), crate::core::AppError>;
    async fn nack_job(&self, queue: &str, job_id: &str) -> Result<(), crate::core::AppError>;
    async fn dead_letter_job(&self, queue: &str, job_id: &str) -> Result<(), crate::core::AppError>;

    async fn search(
        &self,
        query: &str,
        options: SearchOptions,
    ) -> Result<SearchResults, crate::core::AppError>;

    async fn create_link(
        &self,
        source_id: &str,
        target_id: &str,
        relation: &str,
    ) -> Result<ThingdLink, crate::core::AppError>;
    async fn get_links(
        &self,
        source_id: &str,
        relation: Option<&str>,
    ) -> Result<Vec<ThingdLink>, crate::core::AppError>;
    async fn delete_link(&self, link_id: &str) -> Result<(), crate::core::AppError>;

    // Fixture helpers
    async fn reset(&self) -> Result<(), crate::core::AppError>;
    async fn seed(&self) -> Result<(), crate::core::AppError>;
}