maple_runtime/temporal/
mod.rs1use crate::types::TemporalConfig as TemporalCoordinatorConfig;
7use crate::types::*;
8use dashmap::DashMap;
9use std::sync::Arc;
10use tokio::sync::RwLock;
11
12pub struct TemporalCoordinator {
14 timelines: DashMap<ResonatorId, LocalTimeline>,
16
17 #[allow(dead_code)]
19 causality_graph: Arc<RwLock<CausalityGraph>>,
20
21 anchors: DashMap<AnchorId, TemporalAnchor>,
23
24 #[allow(dead_code)]
26 config: TemporalCoordinatorConfig,
27}
28
29impl TemporalCoordinator {
30 pub fn new(config: &TemporalCoordinatorConfig) -> Self {
31 Self {
32 timelines: DashMap::new(),
33 causality_graph: Arc::new(RwLock::new(CausalityGraph::new())),
34 anchors: DashMap::new(),
35 config: config.clone(),
36 }
37 }
38
39 pub fn anchor(&self, event: &ResonanceEvent, resonator: ResonatorId) -> TemporalAnchor {
43 let mut timeline = self
45 .timelines
46 .entry(resonator)
47 .or_insert_with(|| LocalTimeline::new());
48
49 let local_time = timeline.next_timestamp();
50
51 let causal_deps = self.compute_causal_dependencies(event);
52
53 let anchor = TemporalAnchor {
54 id: AnchorId::generate(),
55 local_time,
56 causal_deps: causal_deps.clone(),
57 commitment: event.commitment_id(),
58 };
59
60 self.anchors.insert(anchor.id, anchor.clone());
62
63 tracing::trace!("Created temporal anchor {} for {}", anchor.id, resonator);
67
68 anchor
69 }
70
71 fn compute_causal_dependencies(&self, event: &ResonanceEvent) -> Vec<AnchorId> {
73 event.causal_context().iter().copied().collect()
76 }
77
78 pub fn causal_order(
82 &self,
83 a: &TemporalAnchor,
84 b: &TemporalAnchor,
85 ) -> Option<std::cmp::Ordering> {
86 if self.happened_before(a, b) {
88 return Some(std::cmp::Ordering::Less);
89 }
90
91 if self.happened_before(b, a) {
93 return Some(std::cmp::Ordering::Greater);
94 }
95
96 None
98 }
99
100 fn happened_before(&self, a: &TemporalAnchor, b: &TemporalAnchor) -> bool {
102 if b.causal_deps.contains(&a.id) {
107 return true;
108 }
109
110 for dep_id in &b.causal_deps {
113 if let Some(dep) = self.anchors.get(dep_id) {
114 if self.happened_before(a, &dep) {
115 return true;
116 }
117 }
118 }
119
120 false
121 }
122
123 pub fn get_anchor(&self, id: &AnchorId) -> Option<TemporalAnchor> {
125 self.anchors.get(id).map(|r| r.clone())
126 }
127
128 pub fn are_concurrent(&self, a: &TemporalAnchor, b: &TemporalAnchor) -> bool {
130 self.causal_order(a, b).is_none()
131 }
132}
133
134struct LocalTimeline {
136 current_sequence: u64,
137}
138
139impl LocalTimeline {
140 fn new() -> Self {
141 Self {
142 current_sequence: 0,
143 }
144 }
145
146 fn next_timestamp(&mut self) -> LocalTimestamp {
147 let seq = self.current_sequence;
148 self.current_sequence += 1;
149 LocalTimestamp::with_sequence(seq)
150 }
151}
152
153struct CausalityGraph {
155 }
157
158impl CausalityGraph {
159 fn new() -> Self {
160 Self {}
161 }
162}
163
164#[derive(Debug, Clone)]
166pub struct ResonanceEvent {
167 causal_context: Vec<AnchorId>,
168 commitment: Option<CommitmentId>,
169}
170
171impl ResonanceEvent {
172 pub fn new() -> Self {
173 Self {
174 causal_context: Vec::new(),
175 commitment: None,
176 }
177 }
178
179 pub fn with_causal_context(mut self, context: Vec<AnchorId>) -> Self {
180 self.causal_context = context;
181 self
182 }
183
184 pub fn with_commitment(mut self, commitment: CommitmentId) -> Self {
185 self.commitment = Some(commitment);
186 self
187 }
188
189 pub fn causal_context(&self) -> &[AnchorId] {
190 &self.causal_context
191 }
192
193 pub fn commitment_id(&self) -> Option<CommitmentId> {
194 self.commitment
195 }
196}
197
198impl Default for ResonanceEvent {
199 fn default() -> Self {
200 Self::new()
201 }
202}