Archived
rename crates/ to engrams/, bindings/ to receptors/
- crates/ → engrams/ (Rust engrams live here) - bindings/ → receptors/ (cross-language access points into the graph) - Cargo.toml workspace paths updated
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
/// In-memory registry of named projection schemas.
|
||||
///
|
||||
/// The registry is the store of all registered projections. In a running server,
|
||||
/// one registry instance is shared (behind a Mutex or RwLock). Projections are
|
||||
/// looked up by name to execute queries.
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::error::{ProjectionError, ProjectionResult};
|
||||
use crate::schema::ProjectionSchema;
|
||||
|
||||
/// Holds all registered `ProjectionSchema`s, keyed by name.
|
||||
#[derive(Default)]
|
||||
pub struct ProjectionRegistry {
|
||||
schemas: HashMap<String, ProjectionSchema>,
|
||||
}
|
||||
|
||||
impl ProjectionRegistry {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
schemas: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Register a new schema. Fails if one with the same name already exists.
|
||||
pub fn register(&mut self, schema: ProjectionSchema) -> ProjectionResult<()> {
|
||||
if self.schemas.contains_key(&schema.name) {
|
||||
return Err(ProjectionError::AlreadyExists(schema.name.clone()));
|
||||
}
|
||||
if schema.name.is_empty() {
|
||||
return Err(ProjectionError::InvalidSchema("name must not be empty".into()));
|
||||
}
|
||||
self.schemas.insert(schema.name.clone(), schema);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Replace an existing schema (upsert). Creates if not present.
|
||||
pub fn upsert(&mut self, schema: ProjectionSchema) -> ProjectionResult<()> {
|
||||
if schema.name.is_empty() {
|
||||
return Err(ProjectionError::InvalidSchema("name must not be empty".into()));
|
||||
}
|
||||
self.schemas.insert(schema.name.clone(), schema);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Retrieve a schema by name.
|
||||
pub fn get(&self, name: &str) -> ProjectionResult<&ProjectionSchema> {
|
||||
self.schemas
|
||||
.get(name)
|
||||
.ok_or_else(|| ProjectionError::NotFound(name.to_string()))
|
||||
}
|
||||
|
||||
/// List all schema names.
|
||||
pub fn list(&self) -> Vec<&ProjectionSchema> {
|
||||
let mut schemas: Vec<&ProjectionSchema> = self.schemas.values().collect();
|
||||
schemas.sort_by(|a, b| a.name.cmp(&b.name));
|
||||
schemas
|
||||
}
|
||||
|
||||
/// Remove a schema by name. Returns true if it existed.
|
||||
pub fn remove(&mut self, name: &str) -> bool {
|
||||
self.schemas.remove(name).is_some()
|
||||
}
|
||||
|
||||
/// Number of registered schemas.
|
||||
pub fn len(&self) -> usize {
|
||||
self.schemas.len()
|
||||
}
|
||||
|
||||
/// True if no schemas are registered.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.schemas.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::schema::{NodeFilter, ProjectionType};
|
||||
|
||||
fn make_schema(name: &str) -> ProjectionSchema {
|
||||
ProjectionSchema {
|
||||
name: name.to_string(),
|
||||
description: None,
|
||||
projection_type: ProjectionType::Relational,
|
||||
node_filter: NodeFilter::All,
|
||||
field_mappings: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_register_and_get() {
|
||||
let mut reg = ProjectionRegistry::new();
|
||||
reg.register(make_schema("users")).unwrap();
|
||||
let s = reg.get("users").unwrap();
|
||||
assert_eq!(s.name, "users");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_register_duplicate_fails() {
|
||||
let mut reg = ProjectionRegistry::new();
|
||||
reg.register(make_schema("events")).unwrap();
|
||||
assert!(reg.register(make_schema("events")).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_upsert_replaces() {
|
||||
let mut reg = ProjectionRegistry::new();
|
||||
reg.register(make_schema("s1")).unwrap();
|
||||
let mut updated = make_schema("s1");
|
||||
updated.description = Some("updated".into());
|
||||
reg.upsert(updated).unwrap();
|
||||
assert_eq!(reg.get("s1").unwrap().description.as_deref(), Some("updated"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_list_sorted() {
|
||||
let mut reg = ProjectionRegistry::new();
|
||||
reg.register(make_schema("zoo")).unwrap();
|
||||
reg.register(make_schema("alpha")).unwrap();
|
||||
reg.register(make_schema("mango")).unwrap();
|
||||
let names: Vec<&str> = reg.list().iter().map(|s| s.name.as_str()).collect();
|
||||
assert_eq!(names, vec!["alpha", "mango", "zoo"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_remove() {
|
||||
let mut reg = ProjectionRegistry::new();
|
||||
reg.register(make_schema("temp")).unwrap();
|
||||
assert!(reg.remove("temp"));
|
||||
assert!(!reg.remove("temp"));
|
||||
assert!(reg.get("temp").is_err());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user