glass/browser/session/workflow/
checkpoint.rs1use super::*;
2#[derive(Debug, Clone, Serialize, Deserialize)]
5#[serde(rename_all = "camelCase")]
6pub struct WorkflowCheckpoint {
7 pub schema_version: u8,
8 #[serde(default)]
9 pub run_id: String,
10 pub workflow_name: String,
11 pub workflow_version: String,
12 pub definition_hash: String,
13 pub status: WorkflowRunStatus,
14 pub next_step_index: usize,
15 pub steps: Vec<WorkflowCheckpointStep>,
16 pub page: WorkflowCheckpointPage,
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
21#[serde(rename_all = "camelCase")]
22pub struct WorkflowCheckpointStep {
23 pub id: String,
24 pub state: WorkflowStepState,
25 pub attempts: u32,
26 #[serde(default, skip_serializing_if = "Vec::is_empty")]
27 pub history: Vec<WorkflowStepState>,
28 #[serde(default, skip_serializing_if = "Vec::is_empty")]
29 pub execution_ids: Vec<String>,
30 #[serde(default)]
31 pub dispatch_acknowledged: bool,
32 #[serde(default)]
33 pub effect_observed: bool,
34 #[serde(default)]
35 pub postcondition_verified: bool,
36 #[serde(default)]
37 pub retry_safe: bool,
38 #[serde(default, skip_serializing_if = "Option::is_none")]
39 pub previous_revision: Option<u64>,
40 #[serde(default, skip_serializing_if = "Option::is_none")]
41 pub current_revision: Option<u64>,
42 #[serde(default, skip_serializing_if = "Option::is_none")]
43 pub branch_decision: Option<WorkflowBranchDecision>,
44 #[serde(default, skip_serializing_if = "Option::is_none")]
45 pub intent_evidence: Option<WorkflowIntentEvidence>,
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize)]
50#[serde(rename_all = "camelCase")]
51pub struct WorkflowCheckpointPage {
52 pub target_id: String,
53 pub frame_id: String,
54 pub url: String,
55 pub title: String,
56 pub revision: u64,
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize)]
61#[serde(rename_all = "camelCase")]
62pub struct WorkflowResumePlan {
63 pub workflow_name: String,
64 pub workflow_version: String,
65 pub next_step_index: usize,
66 pub current_revision: u64,
67 pub reconciled: bool,
68}
69
70#[derive(Debug, Clone, Serialize)]
72#[serde(tag = "kind", rename_all = "snake_case")]
73pub enum WorkflowResumeError {
74 SchemaVersionMismatch {
75 expected: u8,
76 found: u8,
77 },
78 DefinitionMismatch,
79 RouteChanged,
80 InvalidState {
81 step_id: String,
82 state: WorkflowStepState,
83 },
84 CheckpointTooLarge,
85 CheckpointShape(String),
86}
87
88impl fmt::Display for WorkflowResumeError {
89 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
90 match self {
91 Self::SchemaVersionMismatch { expected, found } => {
92 write!(
93 formatter,
94 "workflow checkpoint schema mismatch: expected {expected}, found {found}"
95 )
96 }
97 Self::DefinitionMismatch => {
98 formatter.write_str("workflow definition does not match checkpoint")
99 }
100 Self::RouteChanged => {
101 formatter.write_str("workflow checkpoint route or target changed")
102 }
103 Self::InvalidState { step_id, state } => {
104 write!(
105 formatter,
106 "workflow step {step_id:?} cannot be resumed from {state:?}"
107 )
108 }
109 Self::CheckpointTooLarge => {
110 formatter.write_str("workflow checkpoint exceeds the 8 KiB limit")
111 }
112 Self::CheckpointShape(message) => {
113 write!(formatter, "invalid workflow checkpoint: {message}")
114 }
115 }
116 }
117}
118
119impl std::error::Error for WorkflowResumeError {}