Skip to main content

runx_runtime/effects/
types.rs

1use std::any::Any;
2use std::collections::BTreeMap;
3use std::fmt;
4use std::path::Path;
5use std::sync::Arc;
6
7use runx_contracts::{AuthorityVerb, JsonObject, Receipt, Reference};
8use runx_core::state_machine::AuthorityAdmissionWitness;
9use runx_parser::GraphStep;
10
11use crate::adapter::SkillOutput;
12
13use super::RuntimeEffectError;
14
15pub trait RuntimeEffect: Send + Sync {
16    fn family(&self) -> &'static str;
17
18    fn can_run_parallel(&self, step: &GraphStep) -> bool {
19        let _ = step;
20        true
21    }
22
23    fn find_replay(
24        &self,
25        request: EffectStepRequest<'_>,
26    ) -> Result<Option<EffectReplay>, RuntimeEffectError> {
27        let _ = request;
28        Ok(None)
29    }
30
31    fn recover_pending(&self, request: EffectStepRequest<'_>) -> Result<(), RuntimeEffectError> {
32        let _ = request;
33        Ok(())
34    }
35
36    fn admit(
37        &self,
38        request: EffectStepRequest<'_>,
39    ) -> Result<Option<EffectAdmission>, RuntimeEffectError> {
40        let _ = request;
41        Ok(None)
42    }
43
44    fn prepare_output(&self, request: EffectOutputRequest<'_>) -> Result<(), RuntimeEffectError> {
45        let _ = request;
46        Ok(())
47    }
48
49    fn finalize_output(&self, request: EffectReceiptRequest<'_>) -> Result<(), RuntimeEffectError> {
50        let _ = request;
51        Ok(())
52    }
53
54    fn persist(&self, request: EffectReceiptRequest<'_>) -> Result<(), RuntimeEffectError> {
55        let _ = request;
56        Ok(())
57    }
58
59    fn prepare_replay_output(
60        &self,
61        request: EffectReplayOutputRequest<'_>,
62    ) -> Result<(), RuntimeEffectError> {
63        let _ = request;
64        Ok(())
65    }
66
67    fn validate_replay(
68        &self,
69        request: EffectReplayReceiptRequest<'_>,
70    ) -> Result<(), RuntimeEffectError> {
71        let _ = request;
72        Ok(())
73    }
74
75    fn refresh_output_metadata(
76        &self,
77        request: EffectMetadataRefreshRequest<'_>,
78    ) -> Result<(), RuntimeEffectError> {
79        let _ = request;
80        Ok(())
81    }
82
83    fn authority_grant_refs(
84        &self,
85        admission: &EffectAdmission,
86    ) -> Result<Vec<Reference>, RuntimeEffectError> {
87        let _ = admission;
88        Ok(Vec::new())
89    }
90
91    fn replay_authority_grant_refs(
92        &self,
93        replay: &EffectReplay,
94    ) -> Result<Vec<Reference>, RuntimeEffectError> {
95        let _ = replay;
96        Ok(Vec::new())
97    }
98}
99
100#[derive(Clone, Copy, Debug)]
101pub struct EffectStepRequest<'a> {
102    pub step: &'a GraphStep,
103    pub inputs: &'a JsonObject,
104    pub env: &'a BTreeMap<String, String>,
105    pub graph_dir: &'a Path,
106}
107
108pub struct EffectOutputRequest<'a> {
109    pub step: &'a GraphStep,
110    pub admission: &'a EffectAdmission,
111    pub claim: &'a JsonObject,
112    pub output: &'a mut SkillOutput,
113}
114
115pub struct EffectReceiptRequest<'a> {
116    pub step: &'a GraphStep,
117    pub graph_dir: &'a Path,
118    pub admission: &'a EffectAdmission,
119    pub claim: &'a JsonObject,
120    pub output: &'a mut SkillOutput,
121    pub receipt: &'a Receipt,
122    pub env: &'a BTreeMap<String, String>,
123}
124
125pub struct EffectReplayOutputRequest<'a> {
126    pub step: &'a GraphStep,
127    pub replay: &'a EffectReplay,
128    pub output: &'a mut SkillOutput,
129}
130
131pub struct EffectReplayReceiptRequest<'a> {
132    pub step: &'a GraphStep,
133    pub replay: &'a EffectReplay,
134    pub receipt: &'a Receipt,
135    pub output: &'a SkillOutput,
136    pub claim: &'a JsonObject,
137}
138
139pub struct EffectMetadataRefreshRequest<'a> {
140    pub output: &'a mut SkillOutput,
141    pub receipt: &'a Receipt,
142}
143
144#[derive(Clone)]
145pub struct EffectAdmission {
146    family: &'static str,
147    verb: AuthorityVerb,
148    witness: AuthorityAdmissionWitness,
149    context: Arc<dyn Any + Send + Sync>,
150}
151
152impl EffectAdmission {
153    #[must_use]
154    pub fn new<T>(
155        family: &'static str,
156        verb: AuthorityVerb,
157        witness: AuthorityAdmissionWitness,
158        context: T,
159    ) -> Self
160    where
161        T: Any + Send + Sync + 'static,
162    {
163        Self {
164            family,
165            verb,
166            witness,
167            context: Arc::new(context),
168        }
169    }
170
171    #[must_use]
172    pub fn family(&self) -> &'static str {
173        self.family
174    }
175
176    #[must_use]
177    pub fn verb(&self) -> AuthorityVerb {
178        self.verb.clone()
179    }
180
181    #[must_use]
182    pub fn witness(&self) -> &AuthorityAdmissionWitness {
183        &self.witness
184    }
185
186    #[must_use]
187    pub fn context<T: Any>(&self) -> Option<&T> {
188        self.context.as_ref().downcast_ref::<T>()
189    }
190}
191
192impl fmt::Debug for EffectAdmission {
193    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
194        formatter
195            .debug_struct("EffectAdmission")
196            .field("family", &self.family)
197            .field("verb", &self.verb)
198            .field("witness", &self.witness)
199            .finish_non_exhaustive()
200    }
201}
202
203#[derive(Clone)]
204pub struct EffectReplay {
205    family: &'static str,
206    receipt_ref: String,
207    receipt_created_at: String,
208    receipt_digest: String,
209    outputs: JsonObject,
210    context: Arc<dyn Any + Send + Sync>,
211}
212
213impl EffectReplay {
214    #[must_use]
215    pub fn new<T>(
216        family: &'static str,
217        receipt_ref: impl Into<String>,
218        receipt_created_at: impl Into<String>,
219        receipt_digest: impl Into<String>,
220        outputs: JsonObject,
221        context: T,
222    ) -> Self
223    where
224        T: Any + Send + Sync + 'static,
225    {
226        Self {
227            family,
228            receipt_ref: receipt_ref.into(),
229            receipt_created_at: receipt_created_at.into(),
230            receipt_digest: receipt_digest.into(),
231            outputs,
232            context: Arc::new(context),
233        }
234    }
235
236    #[must_use]
237    pub fn family(&self) -> &'static str {
238        self.family
239    }
240
241    #[must_use]
242    pub fn receipt_ref(&self) -> &str {
243        &self.receipt_ref
244    }
245
246    #[must_use]
247    pub fn receipt_created_at(&self) -> &str {
248        &self.receipt_created_at
249    }
250
251    #[must_use]
252    pub fn receipt_digest(&self) -> &str {
253        &self.receipt_digest
254    }
255
256    #[must_use]
257    pub fn outputs(&self) -> &JsonObject {
258        &self.outputs
259    }
260
261    #[must_use]
262    pub fn context<T: Any>(&self) -> Option<&T> {
263        self.context.as_ref().downcast_ref::<T>()
264    }
265}
266
267impl fmt::Debug for EffectReplay {
268    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
269        formatter
270            .debug_struct("EffectReplay")
271            .field("family", &self.family)
272            .field("receipt_ref", &self.receipt_ref)
273            .field("receipt_created_at", &self.receipt_created_at)
274            .field("receipt_digest", &self.receipt_digest)
275            .finish_non_exhaustive()
276    }
277}