agent_effects_store/
contract.rs1use std::time::Duration;
4
5use serde::{Deserialize, Serialize};
6
7use crate::EffectKind;
8
9#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
11#[serde(rename_all = "snake_case", tag = "mode")]
12pub enum VerificationContract {
13 None,
15 Authoritative,
17 EventuallyConsistent {
19 settle: Duration,
21 },
22}
23
24#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
32#[serde(deny_unknown_fields)]
33pub struct ExecutionContract {
34 pub format_version: u32,
36 pub kind: EffectKind,
38 pub remote_idempotency: bool,
40 pub verification: VerificationContract,
42 pub handler_version: String,
44 pub adapter: Option<String>,
46 pub require_approval: bool,
48 pub automatic_retry: bool,
50 pub max_attempts: u32,
52}
53
54impl ExecutionContract {
55 pub fn new(kind: EffectKind, max_attempts: u32) -> Self {
58 Self {
59 format_version: 1,
60 kind,
61 remote_idempotency: false,
62 verification: VerificationContract::None,
63 handler_version: "1".into(),
64 adapter: None,
65 require_approval: false,
66 automatic_retry: true,
67 max_attempts,
68 }
69 }
70
71 pub fn permits(&self, requested: &Self) -> bool {
74 if self.format_version != 1 || requested.format_version != 1 {
75 return false;
76 }
77 self == requested
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84 use proptest::prelude::*;
85
86 proptest! {
87 #[test]
88 fn compatibility_never_grants_changed_execution_assumptions(
89 remote in any::<bool>(), approval in any::<bool>(),
90 automatic in any::<bool>(), attempts in any::<u32>(),
91 format in 2_u32..u32::MAX,
92 ) {
93 let mut stored = ExecutionContract::new(EffectKind::IrreversibleWrite, attempts);
94 stored.remote_idempotency = remote;
95 stored.require_approval = approval;
96 stored.automatic_retry = automatic;
97 prop_assert!(stored.permits(&stored));
98 let mut changed = stored.clone();
99 changed.remote_idempotency = !remote;
100 prop_assert!(!stored.permits(&changed));
101 changed = stored.clone();
102 changed.require_approval = !approval;
103 prop_assert!(!stored.permits(&changed));
104 changed = stored.clone();
105 changed.automatic_retry = !automatic;
106 prop_assert!(!stored.permits(&changed));
107 changed = stored.clone();
108 changed.format_version = format;
109 prop_assert!(!stored.permits(&changed));
110 prop_assert!(!changed.permits(&changed));
111 }
112 }
113}