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