1use thiserror::Error;
2
3#[derive(Debug, Error)]
5#[non_exhaustive]
6pub enum Error {
7 #[error("step job is missing header `{0}`")]
10 MissingHeader(&'static str),
11
12 #[error("step job has invalid `{header}` header `{value}`")]
15 InvalidStepHeader {
16 header: &'static str,
18 value: String,
20 },
21
22 #[error("submission header `{0}` uses the reserved `workflow.*` prefix")]
26 ReservedHeaderInSubmit(String),
27
28 #[error("run `{0}` is active with a different input; pick a fresh run_id")]
33 InputMismatch(String),
34
35 #[error(transparent)]
37 Queue(#[from] taquba::Error),
38}
39
40impl Error {
41 pub fn is_permanent(&self) -> bool {
47 match self {
48 Self::MissingHeader(_)
49 | Self::InvalidStepHeader { .. }
50 | Self::ReservedHeaderInSubmit(_)
51 | Self::InputMismatch(_) => true,
52 Self::Queue(e) => e.is_permanent(),
53 }
54 }
55}
56
57pub type Result<T> = std::result::Result<T, Error>;
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 #[test]
65 fn workflow_variants_are_permanent() {
66 assert!(Error::MissingHeader("workflow.run_id").is_permanent());
67 assert!(
68 Error::InvalidStepHeader {
69 header: "workflow.step",
70 value: "not-a-u32".into(),
71 }
72 .is_permanent()
73 );
74 assert!(Error::ReservedHeaderInSubmit("workflow.foo".into()).is_permanent());
75 assert!(Error::InputMismatch("run-1".into()).is_permanent());
76 }
77
78 #[test]
79 fn queue_classifies_per_inner_variant() {
80 assert!(Error::Queue(taquba::Error::JobNotFound("job-1".into())).is_permanent());
81 assert!(Error::Queue(taquba::Error::InvalidState).is_permanent());
82 assert!(Error::Queue(taquba::Error::KvValueTooLarge { size: 10, max: 5 }).is_permanent());
83 }
84}