pub mod cancellation;
use actionqueue_core::budget::BudgetConsumption;
use actionqueue_core::ids::{AttemptId, RunId};
use actionqueue_core::task::safety::SafetyLevel;
pub use cancellation::{CancellationContext, CancellationToken};
use crate::children::ChildrenSnapshot;
#[derive(Debug, Clone)]
pub struct HandlerInput {
pub run_id: RunId,
pub attempt_id: AttemptId,
pub payload: Vec<u8>,
pub metadata: AttemptMetadata,
pub cancellation_context: CancellationContext,
}
#[derive(Debug, Clone)]
pub struct AttemptMetadata {
pub max_attempts: u32,
pub attempt_number: u32,
pub timeout_secs: Option<u64>,
pub safety_level: SafetyLevel,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum HandlerOutput {
Success {
output: Option<Vec<u8>>,
consumption: Vec<BudgetConsumption>,
},
RetryableFailure {
error: String,
consumption: Vec<BudgetConsumption>,
},
TerminalFailure {
error: String,
consumption: Vec<BudgetConsumption>,
},
Suspended {
output: Option<Vec<u8>>,
consumption: Vec<BudgetConsumption>,
},
}
impl HandlerOutput {
pub fn success() -> Self {
Self::Success { output: None, consumption: vec![] }
}
pub fn success_with_output(output: Vec<u8>) -> Self {
Self::Success { output: Some(output), consumption: vec![] }
}
pub fn success_with_consumption(
output: Option<Vec<u8>>,
consumption: Vec<BudgetConsumption>,
) -> Self {
Self::Success { output, consumption }
}
pub fn retryable_failure(error: impl Into<String>) -> Self {
Self::RetryableFailure { error: error.into(), consumption: vec![] }
}
pub fn terminal_failure(error: impl Into<String>) -> Self {
Self::TerminalFailure { error: error.into(), consumption: vec![] }
}
pub fn suspended() -> Self {
Self::Suspended { output: None, consumption: vec![] }
}
pub fn suspended_with_output(output: Vec<u8>, consumption: Vec<BudgetConsumption>) -> Self {
Self::Suspended { output: Some(output), consumption }
}
pub fn consumption(&self) -> &[BudgetConsumption] {
match self {
Self::Success { consumption, .. }
| Self::RetryableFailure { consumption, .. }
| Self::TerminalFailure { consumption, .. }
| Self::Suspended { consumption, .. } => consumption,
}
}
}
pub trait TaskSubmissionPort: Send + Sync {
fn submit(
&self,
task_spec: actionqueue_core::task::task_spec::TaskSpec,
dependencies: Vec<actionqueue_core::ids::TaskId>,
);
}
pub struct ExecutorContext {
pub input: HandlerInput,
pub submission: Option<std::sync::Arc<dyn TaskSubmissionPort>>,
pub children: Option<ChildrenSnapshot>,
}
impl std::fmt::Debug for ExecutorContext {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ExecutorContext")
.field("input", &self.input)
.field("submission", &self.submission.as_ref().map(|_| "<TaskSubmissionPort>"))
.field("children", &self.children)
.finish()
}
}
pub trait ExecutorHandler: Send + Sync {
fn execute(&self, ctx: ExecutorContext) -> HandlerOutput;
}