maple_runtime/fabrics/
presence.rs1use dashmap::DashMap;
6use std::time::Instant;
7use crate::types::*;
8use crate::config::PresenceConfig as PresenceFabricConfig;
9
10pub struct PresenceFabric {
18 states: DashMap<ResonatorId, PresenceStateWithMetadata>,
20
21 config: PresenceFabricConfig,
23}
24
25struct PresenceStateWithMetadata {
26 state: PresenceState,
27 last_update: Instant,
28}
29
30impl PresenceFabric {
31 pub fn new(config: &PresenceFabricConfig) -> Self {
32 Self {
33 states: DashMap::new(),
34 config: config.clone(),
35 }
36 }
37
38 pub async fn initialize_presence(
40 &self,
41 resonator: &ResonatorId,
42 config: &PresenceConfig,
43 ) -> Result<(), String> {
44 let mut state = PresenceState::new();
45 state.discoverability = config.initial_discoverability;
46 state.responsiveness = config.initial_responsiveness;
47 state.silent_mode = config.start_silent;
48
49 let metadata = PresenceStateWithMetadata {
50 state,
51 last_update: Instant::now(),
52 };
53
54 self.states.insert(*resonator, metadata);
55
56 tracing::debug!("Initialized presence for {}", resonator);
57 Ok(())
58 }
59
60 pub async fn signal_presence(
64 &self,
65 resonator: ResonatorId,
66 state: PresenceState,
67 ) -> Result<(), PresenceError> {
68 if let Some(existing) = self.states.get(&resonator) {
70 let elapsed = existing.last_update.elapsed();
71 let min_interval =
72 std::time::Duration::from_millis(self.config.min_signal_interval_ms);
73
74 if elapsed < min_interval {
75 return Err(PresenceError::RateLimitExceeded);
76 }
77 }
78
79 let metadata = PresenceStateWithMetadata {
83 state,
84 last_update: Instant::now(),
85 };
86
87 self.states.insert(resonator, metadata);
88
89 Ok(())
90 }
91
92 pub async fn enable_silent_presence(&self, resonator: ResonatorId) {
97 if let Some(mut entry) = self.states.get_mut(&resonator) {
98 entry.state.silent_mode = true;
99 entry.state.discoverability = 0.1; }
101 }
102
103 pub async fn disable_silent_presence(&self, resonator: ResonatorId) {
105 if let Some(mut entry) = self.states.get_mut(&resonator) {
106 entry.state.silent_mode = false;
107 entry.state.discoverability = 0.5; }
109 }
110
111 pub fn get_presence(&self, resonator: &ResonatorId) -> Option<PresenceState> {
113 self.states.get(resonator).map(|r| r.state.clone())
114 }
115
116 pub fn is_present(&self, resonator: &ResonatorId) -> bool {
118 self.states.contains_key(resonator)
119 }
120
121 pub async fn update_presence_gradient(
123 &self,
124 resonator: &ResonatorId,
125 adjustment: PresenceAdjustment,
126 ) {
127 if let Some(mut entry) = self.states.get_mut(resonator) {
128 match adjustment {
129 PresenceAdjustment::IncreaseResponsiveness(delta) => {
130 entry.state.responsiveness = (entry.state.responsiveness + delta).min(1.0);
131 }
132 PresenceAdjustment::DecreaseResponsiveness(delta) => {
133 entry.state.responsiveness = (entry.state.responsiveness - delta).max(0.0);
134 }
135 PresenceAdjustment::IncreaseStability(delta) => {
136 entry.state.stability = (entry.state.stability + delta).min(1.0);
137 }
138 PresenceAdjustment::DecreaseStability(delta) => {
139 entry.state.stability = (entry.state.stability - delta).max(0.0);
140 }
141 PresenceAdjustment::SetCouplingReadiness(value) => {
142 entry.state.coupling_readiness = value.clamp(0.0, 1.0);
143 }
144 }
145 }
146 }
147
148 pub async fn restore_presence(
150 &self,
151 resonator: &ResonatorId,
152 state: &PresenceState,
153 ) -> Result<(), String> {
154 let metadata = PresenceStateWithMetadata {
155 state: state.clone(),
156 last_update: Instant::now(),
157 };
158
159 self.states.insert(*resonator, metadata);
160
161 tracing::debug!("Restored presence for {}", resonator);
162 Ok(())
163 }
164
165 pub fn remove_presence(&self, resonator: &ResonatorId) {
167 self.states.remove(resonator);
168 }
169
170 pub fn get_all_present(&self) -> Vec<ResonatorId> {
172 self.states.iter().map(|entry| *entry.key()).collect()
173 }
174
175 pub fn count(&self) -> usize {
177 self.states.len()
178 }
179}
180
181pub enum PresenceAdjustment {
183 IncreaseResponsiveness(f64),
184 DecreaseResponsiveness(f64),
185 IncreaseStability(f64),
186 DecreaseStability(f64),
187 SetCouplingReadiness(f64),
188}