use crate::types::TemporalConfig as TemporalCoordinatorConfig;
use crate::types::*;
use dashmap::DashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
pub struct TemporalCoordinator {
timelines: DashMap<ResonatorId, LocalTimeline>,
#[allow(dead_code)]
causality_graph: Arc<RwLock<CausalityGraph>>,
anchors: DashMap<AnchorId, TemporalAnchor>,
#[allow(dead_code)]
config: TemporalCoordinatorConfig,
}
impl TemporalCoordinator {
pub fn new(config: &TemporalCoordinatorConfig) -> Self {
Self {
timelines: DashMap::new(),
causality_graph: Arc::new(RwLock::new(CausalityGraph::new())),
anchors: DashMap::new(),
config: config.clone(),
}
}
pub fn anchor(&self, event: &ResonanceEvent, resonator: ResonatorId) -> TemporalAnchor {
let mut timeline = self
.timelines
.entry(resonator)
.or_insert_with(|| LocalTimeline::new());
let local_time = timeline.next_timestamp();
let causal_deps = self.compute_causal_dependencies(event);
let anchor = TemporalAnchor {
id: AnchorId::generate(),
local_time,
causal_deps: causal_deps.clone(),
commitment: event.commitment_id(),
};
self.anchors.insert(anchor.id, anchor.clone());
tracing::trace!("Created temporal anchor {} for {}", anchor.id, resonator);
anchor
}
fn compute_causal_dependencies(&self, event: &ResonanceEvent) -> Vec<AnchorId> {
event.causal_context().iter().copied().collect()
}
pub fn causal_order(
&self,
a: &TemporalAnchor,
b: &TemporalAnchor,
) -> Option<std::cmp::Ordering> {
if self.happened_before(a, b) {
return Some(std::cmp::Ordering::Less);
}
if self.happened_before(b, a) {
return Some(std::cmp::Ordering::Greater);
}
None
}
fn happened_before(&self, a: &TemporalAnchor, b: &TemporalAnchor) -> bool {
if b.causal_deps.contains(&a.id) {
return true;
}
for dep_id in &b.causal_deps {
if let Some(dep) = self.anchors.get(dep_id) {
if self.happened_before(a, &dep) {
return true;
}
}
}
false
}
pub fn get_anchor(&self, id: &AnchorId) -> Option<TemporalAnchor> {
self.anchors.get(id).map(|r| r.clone())
}
pub fn are_concurrent(&self, a: &TemporalAnchor, b: &TemporalAnchor) -> bool {
self.causal_order(a, b).is_none()
}
}
struct LocalTimeline {
current_sequence: u64,
}
impl LocalTimeline {
fn new() -> Self {
Self {
current_sequence: 0,
}
}
fn next_timestamp(&mut self) -> LocalTimestamp {
let seq = self.current_sequence;
self.current_sequence += 1;
LocalTimestamp::with_sequence(seq)
}
}
struct CausalityGraph {
}
impl CausalityGraph {
fn new() -> Self {
Self {}
}
}
#[derive(Debug, Clone)]
pub struct ResonanceEvent {
causal_context: Vec<AnchorId>,
commitment: Option<CommitmentId>,
}
impl ResonanceEvent {
pub fn new() -> Self {
Self {
causal_context: Vec::new(),
commitment: None,
}
}
pub fn with_causal_context(mut self, context: Vec<AnchorId>) -> Self {
self.causal_context = context;
self
}
pub fn with_commitment(mut self, commitment: CommitmentId) -> Self {
self.commitment = Some(commitment);
self
}
pub fn causal_context(&self) -> &[AnchorId] {
&self.causal_context
}
pub fn commitment_id(&self) -> Option<CommitmentId> {
self.commitment
}
}
impl Default for ResonanceEvent {
fn default() -> Self {
Self::new()
}
}