use std::future::Future;
use std::time::Duration;
use serde_json::Value;
use time::OffsetDateTime;
use uuid::Uuid;
use crate::workflow::{WorkflowId, WorkflowRef};
#[derive(Debug, Clone)]
pub struct OutboxEffect {
pub id: Uuid,
pub workflow: WorkflowRef,
pub payload: Value,
pub attempts: u32,
pub created_at: OffsetDateTime,
}
#[derive(Debug, Clone)]
pub struct DeadLetter {
pub id: Uuid,
pub workflow: WorkflowRef,
pub payload: Value,
pub attempts: u32,
pub last_error: Option<String>,
pub created_at: OffsetDateTime,
}
#[derive(Debug, Clone, Default)]
pub struct DeadLetterQuery {
pub workflow_type: Option<String>,
pub workflow_id: Option<WorkflowId>,
pub limit: Option<u32>,
}
impl DeadLetterQuery {
pub fn new() -> Self {
Self::default()
}
pub fn workflow_type(mut self, workflow_type: impl Into<String>) -> Self {
self.workflow_type = Some(workflow_type.into());
self
}
pub fn workflow_id(mut self, workflow_id: impl Into<WorkflowId>) -> Self {
self.workflow_id = Some(workflow_id.into());
self
}
pub fn limit(mut self, limit: u32) -> Self {
self.limit = Some(limit);
self
}
}
pub trait OutboxStore: Send + Sync + Clone + 'static {
fn claim_effect(
&self,
worker_id: &str,
registered_types: &[String],
lock_duration: Duration,
max_attempts: u32,
) -> impl Future<Output = crate::Result<Option<OutboxEffect>>> + Send;
fn mark_processed(
&self,
effect_id: Uuid,
worker_id: &str,
) -> impl Future<Output = crate::Result<()>> + Send;
fn record_failure(
&self,
effect_id: Uuid,
worker_id: &str,
error: &str,
backoff_duration: Duration,
) -> impl Future<Output = crate::Result<()>> + Send;
fn record_permanent_failure(
&self,
effect_id: Uuid,
worker_id: &str,
error: &str,
max_attempts: u32,
) -> impl Future<Output = crate::Result<()>> + Send;
fn claim_timer(
&self,
worker_id: &str,
registered_types: &[String],
lock_duration: Duration,
max_attempts: u32,
) -> impl Future<Output = crate::Result<Option<OutboxEffect>>> + Send;
fn fetch_dead_letters(
&self,
query: &DeadLetterQuery,
max_attempts: u32,
) -> impl Future<Output = crate::Result<Vec<DeadLetter>>> + Send;
fn retry_dead_letter(
&self,
effect_id: Uuid,
) -> impl Future<Output = crate::Result<bool>> + Send;
fn count_dead_letters(
&self,
query: &DeadLetterQuery,
max_attempts: u32,
) -> impl Future<Output = crate::Result<u64>> + Send;
fn mark_timer_processed(
&self,
timer_id: Uuid,
worker_id: &str,
) -> impl Future<Output = crate::Result<()>> + Send;
fn record_timer_failure(
&self,
timer_id: Uuid,
worker_id: &str,
error: &str,
backoff_duration: Duration,
) -> impl Future<Output = crate::Result<()>> + Send;
fn fetch_timer_dead_letters(
&self,
query: &DeadLetterQuery,
max_attempts: u32,
) -> impl Future<Output = crate::Result<Vec<DeadLetter>>> + Send;
fn retry_timer_dead_letter(
&self,
timer_id: Uuid,
) -> impl Future<Output = crate::Result<bool>> + Send;
fn count_timer_dead_letters(
&self,
query: &DeadLetterQuery,
max_attempts: u32,
) -> impl Future<Output = crate::Result<u64>> + Send;
}