webterm_agent/models/
activity_registry.rs

1use crate::models::activity::Activity;
2use crate::models::agent_error::AgentError;
3use std::collections::HashMap;
4use std::sync::atomic::{AtomicU64, Ordering};
5use std::sync::{Arc, OnceLock};
6use tokio::sync::RwLock;
7use tracing::debug;
8use webterm_core::types::ActivityId;
9
10static NEXT_ACTIVITY_ID: AtomicU64 = AtomicU64::new(1);
11
12pub struct ActivityRegistry {
13    map: RwLock<HashMap<ActivityId, Arc<Activity>>>,
14}
15
16impl ActivityRegistry {
17    pub(crate) async fn singleton() -> &'static Self {
18        static INSTANCE: OnceLock<ActivityRegistry> = OnceLock::new();
19        INSTANCE.get_or_init(|| Self {
20            map: RwLock::new(HashMap::new()),
21        })
22    }
23
24    pub fn next_activity_id() -> ActivityId {
25        ActivityId(NEXT_ACTIVITY_ID.fetch_add(1, Ordering::SeqCst))
26    }
27
28    pub async fn find(activity_id: ActivityId) -> Result<Arc<Activity>, AgentError> {
29        let registry = Self::singleton().await;
30        registry
31            .map
32            .read()
33            .await
34            .get(&activity_id)
35            .ok_or(AgentError::ActivityNotFound(Some(activity_id)))
36            .cloned()
37    }
38
39    pub async fn register(activity: Arc<Activity>) -> Result<(), AgentError> {
40        let registry = Self::singleton().await;
41        debug!("Registering activity {:?}", activity.activity_id());
42        registry
43            .map
44            .write()
45            .await
46            .insert(activity.activity_id(), activity);
47
48        Ok(())
49    }
50}