maple_runtime/fabrics/
presence.rs1use crate::config::PresenceConfig as PresenceFabricConfig;
6use crate::types::*;
7use dashmap::DashMap;
8use std::time::{Duration, Instant};
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 fn initial_last_update(min_signal_interval_ms: u64) -> Instant {
32 Instant::now()
34 .checked_sub(Duration::from_millis(min_signal_interval_ms))
35 .unwrap_or_else(Instant::now)
36 }
37
38 pub fn new(config: &PresenceFabricConfig) -> Self {
39 Self {
40 states: DashMap::new(),
41 config: config.clone(),
42 }
43 }
44
45 pub async fn initialize_presence(
47 &self,
48 resonator: &ResonatorId,
49 config: &PresenceConfig,
50 ) -> Result<(), String> {
51 let mut state = PresenceState::new();
52 state.discoverability = config.initial_discoverability;
53 state.responsiveness = config.initial_responsiveness;
54 state.silent_mode = config.start_silent;
55
56 let metadata = PresenceStateWithMetadata {
57 state,
58 last_update: Self::initial_last_update(self.config.min_signal_interval_ms),
59 };
60
61 self.states.insert(*resonator, metadata);
62
63 tracing::debug!("Initialized presence for {}", resonator);
64 Ok(())
65 }
66
67 pub async fn signal_presence(
71 &self,
72 resonator: ResonatorId,
73 state: PresenceState,
74 ) -> Result<(), PresenceError> {
75 if let Some(existing) = self.states.get(&resonator) {
77 let elapsed = existing.last_update.elapsed();
78 let min_interval = std::time::Duration::from_millis(self.config.min_signal_interval_ms);
79
80 if elapsed < min_interval {
81 return Err(PresenceError::RateLimitExceeded);
82 }
83 }
84
85 let metadata = PresenceStateWithMetadata {
89 state,
90 last_update: Instant::now(),
91 };
92
93 self.states.insert(resonator, metadata);
94
95 Ok(())
96 }
97
98 pub async fn enable_silent_presence(&self, resonator: ResonatorId) {
103 if let Some(mut entry) = self.states.get_mut(&resonator) {
104 entry.state.silent_mode = true;
105 entry.state.discoverability = 0.1; }
107 }
108
109 pub async fn disable_silent_presence(&self, resonator: ResonatorId) {
111 if let Some(mut entry) = self.states.get_mut(&resonator) {
112 entry.state.silent_mode = false;
113 entry.state.discoverability = 0.5; }
115 }
116
117 pub fn get_presence(&self, resonator: &ResonatorId) -> Option<PresenceState> {
119 self.states.get(resonator).map(|r| r.state.clone())
120 }
121
122 pub fn is_present(&self, resonator: &ResonatorId) -> bool {
124 self.states.contains_key(resonator)
125 }
126
127 pub async fn update_presence_gradient(
129 &self,
130 resonator: &ResonatorId,
131 adjustment: PresenceAdjustment,
132 ) {
133 if let Some(mut entry) = self.states.get_mut(resonator) {
134 match adjustment {
135 PresenceAdjustment::IncreaseResponsiveness(delta) => {
136 entry.state.responsiveness = (entry.state.responsiveness + delta).min(1.0);
137 }
138 PresenceAdjustment::DecreaseResponsiveness(delta) => {
139 entry.state.responsiveness = (entry.state.responsiveness - delta).max(0.0);
140 }
141 PresenceAdjustment::IncreaseStability(delta) => {
142 entry.state.stability = (entry.state.stability + delta).min(1.0);
143 }
144 PresenceAdjustment::DecreaseStability(delta) => {
145 entry.state.stability = (entry.state.stability - delta).max(0.0);
146 }
147 PresenceAdjustment::SetCouplingReadiness(value) => {
148 entry.state.coupling_readiness = value.clamp(0.0, 1.0);
149 }
150 }
151 }
152 }
153
154 pub async fn restore_presence(
156 &self,
157 resonator: &ResonatorId,
158 state: &PresenceState,
159 ) -> Result<(), String> {
160 let metadata = PresenceStateWithMetadata {
161 state: state.clone(),
162 last_update: Self::initial_last_update(self.config.min_signal_interval_ms),
163 };
164
165 self.states.insert(*resonator, metadata);
166
167 tracing::debug!("Restored presence for {}", resonator);
168 Ok(())
169 }
170
171 pub fn remove_presence(&self, resonator: &ResonatorId) {
173 self.states.remove(resonator);
174 }
175
176 pub fn get_all_present(&self) -> Vec<ResonatorId> {
178 self.states.iter().map(|entry| *entry.key()).collect()
179 }
180
181 pub fn count(&self) -> usize {
183 self.states.len()
184 }
185}
186
187pub enum PresenceAdjustment {
189 IncreaseResponsiveness(f64),
190 DecreaseResponsiveness(f64),
191 IncreaseStability(f64),
192 DecreaseStability(f64),
193 SetCouplingReadiness(f64),
194}