use std::collections::HashMap;
use std::future::Future;
use std::time::Duration;
use tokio_util::sync::CancellationToken;
use crate::memo::Memo;
#[derive(Debug, Clone)]
pub struct Step {
pub run_id: String,
pub step_number: u32,
pub payload: Vec<u8>,
pub headers: HashMap<String, String>,
pub job_id: String,
pub attempts: u32,
pub cancel_token: CancellationToken,
pub memo: Memo,
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub enum StepOutcome {
Continue {
payload: Vec<u8>,
},
ContinueAfter {
payload: Vec<u8>,
delay: Duration,
},
Succeed {
result: Vec<u8>,
},
Fail {
reason: String,
},
Cancel {
reason: String,
},
}
#[derive(Debug)]
pub struct StepError {
pub message: String,
pub kind: StepErrorKind,
}
impl StepError {
pub fn transient(message: impl Into<String>) -> Self {
Self {
message: message.into(),
kind: StepErrorKind::Transient,
}
}
pub fn permanent(message: impl Into<String>) -> Self {
Self {
message: message.into(),
kind: StepErrorKind::Permanent,
}
}
}
impl std::fmt::Display for StepError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.message)
}
}
impl std::error::Error for StepError {}
impl From<crate::Error> for StepError {
fn from(err: crate::Error) -> Self {
let permanent = err.is_permanent();
let message = err.to_string();
if permanent {
Self::permanent(message)
} else {
Self::transient(message)
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum StepErrorKind {
Transient,
Permanent,
}
pub trait StepRunner: Send + Sync {
fn run_step(
&self,
step: &Step,
) -> impl Future<Output = std::result::Result<StepOutcome, StepError>> + Send;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn from_workflow_error_maps_via_is_permanent() {
let permanent: StepError = crate::Error::InputMismatch("run-1".into()).into();
assert_eq!(permanent.kind, StepErrorKind::Permanent);
let store_err = taquba::object_store::Error::NotFound {
path: "x".into(),
source: "missing".into(),
};
let transient: StepError = crate::Error::Store(store_err).into();
assert_eq!(transient.kind, StepErrorKind::Transient);
}
}