use async_trait::async_trait;
use chrono::{DateTime, Utc};
use thiserror::Error;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TaskId(pub i64);
#[derive(Debug, Clone)]
pub struct StoredTask {
pub id: TaskId,
pub pipeline: String,
pub input: serde_json::Value,
pub created_at: DateTime<Utc>,
}
#[derive(Error, Debug)]
pub enum TaskError {
#[error("storage error: {0}")]
StorageError(String),
#[error("serialization error: {0}")]
SerializationError(String),
#[error("unknown pipeline: {0}")]
UnknownPipeline(String),
#[error("deserialization error: {0}")]
DeserializationError(String),
#[error("pipeline error: {0}")]
PipelineError(String),
}
#[async_trait]
pub trait TaskStore: Send + Sync {
async fn enqueue(&self, pipeline: &str, input: serde_json::Value) -> Result<TaskId, TaskError>;
async fn claim(&self, limit: usize) -> Result<Vec<StoredTask>, TaskError>;
async fn claim_for_pipeline(
&self,
pipeline: &str,
limit: usize,
) -> Result<Vec<StoredTask>, TaskError> {
let tasks = self.claim(limit).await?;
Ok(tasks
.into_iter()
.filter(|t| t.pipeline == pipeline)
.collect())
}
async fn recover_orphans(&self) -> Result<usize, TaskError> {
Ok(0) }
async fn claim_excluding(
&self,
limit: usize,
exclude_pipelines: &[&str],
) -> Result<Vec<StoredTask>, TaskError> {
let tasks = self.claim(limit).await?;
Ok(tasks
.into_iter()
.filter(|t| !exclude_pipelines.contains(&t.pipeline.as_str()))
.collect())
}
async fn complete(&self, id: TaskId) -> Result<(), TaskError>;
async fn fail(&self, id: TaskId, error: &str) -> Result<(), TaskError>;
}