rustev_runtime/
progress.rs1use rustev_contract::{
3 evidence::StepStatus,
4 judgment::{Derivation, Unresolved},
5};
6use std::{
7 panic::{AssertUnwindSafe, catch_unwind},
8 sync::atomic::{AtomicU64, Ordering},
9};
10
11#[derive(Debug, Clone, PartialEq)]
13pub struct StepProgress {
14 pub step_id: String,
15 pub instance_ids: Vec<String>,
16 pub outcome: Result<(), Unresolved>,
17 pub derivation: Derivation,
18}
19
20#[derive(Debug, Clone, PartialEq)]
23pub struct SkippedStep {
24 pub step_id: String,
25 pub instance_ids: Vec<String>,
26 pub derivation: Derivation,
27}
28
29pub trait ProgressObserver: Send + Sync {
33 fn admitted(&self) {}
35 fn step(&self, progress: StepProgress);
36 fn skipped(&self, _step: SkippedStep) {}
39}
40
41pub(crate) struct Observing<'a> {
42 pub observer: &'a dyn ProgressObserver,
43 pub panics: &'a AtomicU64,
44}
45impl Observing<'_> {
46 pub fn call(&self, f: impl FnOnce(&dyn ProgressObserver)) {
47 if catch_unwind(AssertUnwindSafe(|| f(self.observer))).is_err() {
48 self.panics.fetch_add(1, Ordering::Relaxed);
49 }
50 }
51 pub fn remaining(
52 &self,
53 evidence: &rustev_contract::evidence::EvidenceRecord,
54 requests: &[rustev_contract::run::RequestRecord],
55 plan: &rustev_contract::plan::Plan,
56 ) {
57 for step in &evidence.steps {
58 if requests
60 .iter()
61 .any(|r| r.step == step.step && r.instance == step.instance)
62 {
63 continue;
64 }
65 let compiled = || {
68 plan.steps
69 .iter()
70 .find(|s| s.id == step.step)
71 .expect("recorded step belongs to plan")
72 .derivation
73 };
74 let (outcome, derivation) = match &step.status {
75 StepStatus::Skipped { .. } => {
76 let derivation = compiled();
77 self.call(|o| {
78 o.skipped(SkippedStep {
79 step_id: step.step.clone(),
80 instance_ids: step.instance.clone(),
81 derivation,
82 })
83 });
84 continue;
85 }
86 StepStatus::Resolved { derivation, .. } => (Ok(()), *derivation),
87 StepStatus::Unresolved(reason) => (Err(reason.clone()), compiled()),
88 };
89 self.call(|o| {
90 o.step(StepProgress {
91 step_id: step.step.clone(),
92 instance_ids: step.instance.clone(),
93 outcome,
94 derivation,
95 })
96 });
97 }
98 }
99}