1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
7#[serde(rename_all = "snake_case")]
8pub enum FailureClass {
9 BaselineTimeout,
11 PatchedCrash,
13 DuplicateCeaReplay,
15 DbBusy,
17 PostReceiptCrash,
19 MemoryIngestUnavailable,
21 PartialVerification,
23 MigrationInterrupted,
25 WorkspaceSizeExceeded,
27 Other,
29}
30
31#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct FailureRecord {
34 pub failure_id: String,
35 pub run_id: String,
36 pub class: FailureClass,
37 pub message: String,
38 pub phase: String,
40 pub retriable: bool,
42 pub retry_count: u32,
44 pub occurred_at: String,
45}
46
47impl FailureClass {
48 pub fn is_retriable(&self) -> bool {
50 matches!(
51 self,
52 Self::DbBusy
53 | Self::MemoryIngestUnavailable
54 | Self::PostReceiptCrash
55 | Self::BaselineTimeout
56 )
57 }
58
59 pub fn from_error(error: &crate::error::ForgeError) -> Self {
61 match error {
62 crate::error::ForgeError::CommandTimeout { .. } => Self::BaselineTimeout,
63 crate::error::ForgeError::Database(e) => {
64 if e.to_string().contains("database is locked") {
65 Self::DbBusy
66 } else {
67 Self::Other
68 }
69 }
70 _ => Self::Other,
71 }
72 }
73}