nym_task/
runtime_registry.rs1use thiserror::Error;
5
6use crate::ShutdownManager;
7use std::sync::RwLock;
8use std::sync::{Arc, LazyLock};
9
10pub(crate) struct RuntimeRegistry {
14 sdk_manager: RwLock<Option<Arc<ShutdownManager>>>,
16}
17
18#[derive(Debug, Error)]
19pub enum RegistryAccessError {
20 #[error("the runtime registry is poisoned")]
21 Poisoned,
22
23 #[error("The SDK ShutdownManager already exists")]
24 ExistingShutdownManager,
25
26 #[error("No existing SDK ShutdownManager")]
27 MissingShutdownManager,
28}
29
30impl RuntimeRegistry {
31 pub(crate) fn create_sdk() -> Result<Arc<ShutdownManager>, RegistryAccessError> {
35 let mut guard = REGISTRY
36 .sdk_manager
37 .write()
38 .map_err(|_| RegistryAccessError::Poisoned)?;
39
40 Ok(guard
41 .insert(Arc::new(
42 ShutdownManager::new_without_signals().with_cancel_on_panic(),
43 ))
44 .clone())
45 }
46
47 #[allow(dead_code)]
51 pub(crate) fn get_sdk() -> Result<Arc<ShutdownManager>, RegistryAccessError> {
52 let guard = REGISTRY
53 .sdk_manager
54 .read()
55 .map_err(|_| RegistryAccessError::Poisoned)?;
56 if let Some(manager) = guard.as_ref() {
57 Ok(manager.clone())
58 } else {
59 Err(RegistryAccessError::MissingShutdownManager)
60 }
61 }
62
63 #[allow(dead_code)]
66 pub(crate) fn has_sdk_manager() -> Result<bool, RegistryAccessError> {
67 Ok(REGISTRY
68 .sdk_manager
69 .read()
70 .map_err(|_| RegistryAccessError::Poisoned)?
71 .is_some())
72 }
73
74 #[cfg(test)]
77 pub(crate) async fn clear() -> Result<(), RegistryAccessError> {
78 *REGISTRY
79 .sdk_manager
80 .write()
81 .map_err(|_| RegistryAccessError::Poisoned)? = None;
82 Ok(())
83 }
84}
85
86static REGISTRY: LazyLock<RuntimeRegistry> = LazyLock::new(|| RuntimeRegistry {
89 sdk_manager: RwLock::new(None),
90});
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 #[tokio::test]
97 async fn test_get_or_create_sdk() {
98 let _ = RuntimeRegistry::clear().await;
100
101 assert!(!RuntimeRegistry::has_sdk_manager().unwrap());
102
103 assert!(RuntimeRegistry::get_sdk().is_err());
105
106 let manager1 = RuntimeRegistry::create_sdk().unwrap();
107 assert!(RuntimeRegistry::has_sdk_manager().unwrap());
108
109 let manager2 = RuntimeRegistry::get_sdk().unwrap();
110 assert!(Arc::ptr_eq(&manager1, &manager2));
112
113 let _ = RuntimeRegistry::clear().await;
114 assert!(!RuntimeRegistry::has_sdk_manager().unwrap());
115 }
116}