Some checks failed
Build - Verify Code & Build Binaries / Check Code Format (push) Has been cancelled
Build - Verify Code & Build Binaries / Lint with Clippy (push) Has been cancelled
Build - Verify Code & Build Binaries / Test Suite (push) Has been cancelled
Build - Verify Code & Build Binaries / Cargo Check (push) Has been cancelled
Build - Verify Code & Build Binaries / Security Audit (push) Has been cancelled
Build - Verify Code & Build Binaries / Build (Debug) - macos-latest (push) Has been cancelled
Build - Verify Code & Build Binaries / Build (Debug) - ubuntu-latest (push) Has been cancelled
Build - Verify Code & Build Binaries / Build (Debug) - windows-latest (push) Has been cancelled
Build - Verify Code & Build Binaries / Build (Release) - macos-latest (push) Has been cancelled
Build - Verify Code & Build Binaries / Build (Release) - ubuntu-latest (push) Has been cancelled
Build - Verify Code & Build Binaries / Build (Release) - windows-latest (push) Has been cancelled
CI/CD with Staging Preset / Validate Installation with Staging Preset (macos-latest) (push) Has been cancelled
CI/CD with Staging Preset / Validate Installation with Staging Preset (ubuntu-latest) (push) Has been cancelled
CI/CD with Staging Preset / Validate Documentation (push) Has been cancelled
Build - Verify Code & Build Binaries / All Checks Passed (push) Has been cancelled
CI/CD with Staging Preset / Build and Test with Staging Preset (push) Has been cancelled
CI/CD with Staging Preset / Integration Test with Docker Compose (push) Has been cancelled
CI/CD with Staging Preset / Test Summary (push) Has been cancelled
platform - Add orchestration.rs and kogral_bridge.rs to syntaxis-vapora - Replace async-nats with platform-nats (NKey auth support) - Wire stratum-orchestrator, stratum-graph, stratum-state deps - Upgrade surrealdb 2.3 → 3 with kv-surrealkv and rustls features - Consolidate core/Cargo.toml into root workspace (remove virtual manifest) - Add shared/rust/nickel.rs for Nickel config integration - Rename CLI binary from syntaxis-cli to syntaxis
217 lines
5.8 KiB
Rust
217 lines
5.8 KiB
Rust
//! Registry for managing ecosystem integrations
|
|
|
|
use crate::ecosystem::{EcosystemIntegration, EcosystemIntegrationError, IntegrationMetadata};
|
|
use std::collections::HashMap;
|
|
use std::sync::Arc;
|
|
use tracing::{debug, info};
|
|
|
|
/// Registry for ecosystem integrations
|
|
pub struct IntegrationRegistry {
|
|
integrations: HashMap<String, Arc<dyn EcosystemIntegration>>,
|
|
}
|
|
|
|
impl IntegrationRegistry {
|
|
/// Create a new empty registry
|
|
pub fn new() -> Self {
|
|
Self {
|
|
integrations: HashMap::new(),
|
|
}
|
|
}
|
|
|
|
/// Register an integration
|
|
pub fn register(
|
|
&mut self,
|
|
integration: Arc<dyn EcosystemIntegration>,
|
|
) -> Result<(), EcosystemIntegrationError> {
|
|
let name = integration.name().to_string();
|
|
|
|
if self.integrations.contains_key(&name) {
|
|
return Err(EcosystemIntegrationError::IntegrationError(format!(
|
|
"Integration '{}' already registered",
|
|
name
|
|
)));
|
|
}
|
|
|
|
info!("Registering ecosystem integration: {}", name);
|
|
self.integrations.insert(name, integration);
|
|
Ok(())
|
|
}
|
|
|
|
/// Get an integration by name
|
|
pub fn get(
|
|
&self,
|
|
name: &str,
|
|
) -> Result<Arc<dyn EcosystemIntegration>, EcosystemIntegrationError> {
|
|
self.integrations.get(name).map(Arc::clone).ok_or(
|
|
EcosystemIntegrationError::NotFound {
|
|
name: name.to_string(),
|
|
},
|
|
)
|
|
}
|
|
|
|
/// Get all registered integrations
|
|
pub fn all(&self) -> Vec<Arc<dyn EcosystemIntegration>> {
|
|
self.integrations.values().cloned().collect()
|
|
}
|
|
|
|
/// Get all available integrations (those that are configured and available)
|
|
pub fn available(&self) -> Vec<Arc<dyn EcosystemIntegration>> {
|
|
self.integrations
|
|
.values()
|
|
.filter(|i| i.is_available())
|
|
.cloned()
|
|
.collect()
|
|
}
|
|
|
|
/// Get metadata for all integrations
|
|
pub fn metadata(&self) -> Vec<IntegrationMetadata> {
|
|
self.integrations.values().map(|i| i.metadata()).collect()
|
|
}
|
|
|
|
/// Check if integration is registered
|
|
pub fn has(&self, name: &str) -> bool {
|
|
self.integrations.contains_key(name)
|
|
}
|
|
|
|
/// Get number of registered integrations
|
|
pub fn count(&self) -> usize {
|
|
self.integrations.len()
|
|
}
|
|
|
|
/// Get number of available integrations
|
|
pub fn available_count(&self) -> usize {
|
|
self.integrations
|
|
.values()
|
|
.filter(|i| i.is_available())
|
|
.count()
|
|
}
|
|
|
|
/// Unregister an integration
|
|
pub fn unregister(&mut self, name: &str) -> Result<(), EcosystemIntegrationError> {
|
|
if self.integrations.remove(name).is_some() {
|
|
info!("Unregistered ecosystem integration: {}", name);
|
|
Ok(())
|
|
} else {
|
|
Err(EcosystemIntegrationError::NotFound {
|
|
name: name.to_string(),
|
|
})
|
|
}
|
|
}
|
|
|
|
/// Clear all registrations
|
|
pub fn clear(&mut self) {
|
|
debug!("Clearing all ecosystem integrations");
|
|
self.integrations.clear();
|
|
}
|
|
}
|
|
|
|
impl Default for IntegrationRegistry {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use async_trait::async_trait;
|
|
|
|
struct TestIntegration {
|
|
name: String,
|
|
}
|
|
|
|
#[async_trait]
|
|
impl EcosystemIntegration for TestIntegration {
|
|
fn name(&self) -> &str {
|
|
&self.name
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_registry_register() {
|
|
let mut registry = IntegrationRegistry::new();
|
|
let integration = Arc::new(TestIntegration {
|
|
name: "test".to_string(),
|
|
});
|
|
|
|
assert!(registry.register(integration).is_ok());
|
|
assert!(registry.has("test"));
|
|
assert_eq!(registry.count(), 1);
|
|
}
|
|
|
|
#[test]
|
|
fn test_registry_duplicate_registration() {
|
|
let mut registry = IntegrationRegistry::new();
|
|
let integration = Arc::new(TestIntegration {
|
|
name: "test".to_string(),
|
|
});
|
|
|
|
assert!(registry.register(integration.clone()).is_ok());
|
|
assert!(registry.register(integration).is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn test_registry_get() {
|
|
let mut registry = IntegrationRegistry::new();
|
|
let integration = Arc::new(TestIntegration {
|
|
name: "test".to_string(),
|
|
});
|
|
|
|
registry.register(integration).unwrap();
|
|
|
|
let retrieved = registry.get("test").unwrap();
|
|
assert_eq!(retrieved.name(), "test");
|
|
}
|
|
|
|
#[test]
|
|
fn test_registry_get_not_found() {
|
|
let registry = IntegrationRegistry::new();
|
|
assert!(registry.get("nonexistent").is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn test_registry_unregister() {
|
|
let mut registry = IntegrationRegistry::new();
|
|
let integration = Arc::new(TestIntegration {
|
|
name: "test".to_string(),
|
|
});
|
|
|
|
registry.register(integration).unwrap();
|
|
assert_eq!(registry.count(), 1);
|
|
|
|
assert!(registry.unregister("test").is_ok());
|
|
assert_eq!(registry.count(), 0);
|
|
assert!(!registry.has("test"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_registry_clear() {
|
|
let mut registry = IntegrationRegistry::new();
|
|
|
|
for i in 0..3 {
|
|
let integration = Arc::new(TestIntegration {
|
|
name: format!("test{}", i),
|
|
});
|
|
registry.register(integration).unwrap();
|
|
}
|
|
|
|
assert_eq!(registry.count(), 3);
|
|
registry.clear();
|
|
assert_eq!(registry.count(), 0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_registry_metadata() {
|
|
let mut registry = IntegrationRegistry::new();
|
|
let integration = Arc::new(TestIntegration {
|
|
name: "test".to_string(),
|
|
});
|
|
|
|
registry.register(integration).unwrap();
|
|
|
|
let metadata = registry.metadata();
|
|
assert_eq!(metadata.len(), 1);
|
|
assert_eq!(metadata[0].name, "test");
|
|
}
|
|
}
|