use thiserror::Error;
use crate::ShutdownManager;
use std::sync::RwLock;
use std::sync::{Arc, LazyLock};
pub(crate) struct RuntimeRegistry {
sdk_manager: RwLock<Option<Arc<ShutdownManager>>>,
}
#[derive(Debug, Error)]
pub enum RegistryAccessError {
#[error("the runtime registry is poisoned")]
Poisoned,
#[error("The SDK ShutdownManager already exists")]
ExistingShutdownManager,
#[error("No existing SDK ShutdownManager")]
MissingShutdownManager,
}
impl RuntimeRegistry {
pub(crate) fn create_sdk() -> Result<Arc<ShutdownManager>, RegistryAccessError> {
let mut guard = REGISTRY
.sdk_manager
.write()
.map_err(|_| RegistryAccessError::Poisoned)?;
Ok(guard
.insert(Arc::new(
ShutdownManager::new_without_signals().with_cancel_on_panic(),
))
.clone())
}
#[allow(dead_code)]
pub(crate) fn get_sdk() -> Result<Arc<ShutdownManager>, RegistryAccessError> {
let guard = REGISTRY
.sdk_manager
.read()
.map_err(|_| RegistryAccessError::Poisoned)?;
if let Some(manager) = guard.as_ref() {
Ok(manager.clone())
} else {
Err(RegistryAccessError::MissingShutdownManager)
}
}
#[allow(dead_code)]
pub(crate) fn has_sdk_manager() -> Result<bool, RegistryAccessError> {
Ok(REGISTRY
.sdk_manager
.read()
.map_err(|_| RegistryAccessError::Poisoned)?
.is_some())
}
#[cfg(test)]
pub(crate) async fn clear() -> Result<(), RegistryAccessError> {
*REGISTRY
.sdk_manager
.write()
.map_err(|_| RegistryAccessError::Poisoned)? = None;
Ok(())
}
}
static REGISTRY: LazyLock<RuntimeRegistry> = LazyLock::new(|| RuntimeRegistry {
sdk_manager: RwLock::new(None),
});
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_get_or_create_sdk() {
let _ = RuntimeRegistry::clear().await;
assert!(!RuntimeRegistry::has_sdk_manager().unwrap());
assert!(RuntimeRegistry::get_sdk().is_err());
let manager1 = RuntimeRegistry::create_sdk().unwrap();
assert!(RuntimeRegistry::has_sdk_manager().unwrap());
let manager2 = RuntimeRegistry::get_sdk().unwrap();
assert!(Arc::ptr_eq(&manager1, &manager2));
let _ = RuntimeRegistry::clear().await;
assert!(!RuntimeRegistry::has_sdk_manager().unwrap());
}
}