use crate::connection::ConnectionRegistry;
use saya_types::{ProfileIdentity, SchemaTree};
use std::collections::HashMap;
pub(crate) struct ProfileFacts {
pub identity: ProfileIdentity,
pub schema: SchemaTree,
}
#[derive(Debug, Clone)]
pub(crate) enum ProfileLookupError {
Connection(String),
MissingIdentity,
InvalidIdentity(String),
}
#[derive(Default)]
pub(crate) struct ProfileCatalog {
seen: HashMap<String, Result<ProfileFacts, ProfileLookupError>>,
}
impl ProfileCatalog {
pub(crate) fn new() -> Self {
Self::default()
}
pub(crate) async fn facts(
&mut self,
profile: &str,
registry: &ConnectionRegistry,
) -> Result<&ProfileFacts, ProfileLookupError> {
if !self.seen.contains_key(profile) {
let looked_up = Self::look_up(profile, registry).await;
self.seen.insert(profile.to_string(), looked_up);
}
match self.seen.get(profile) {
Some(Ok(facts)) => Ok(facts),
Some(Err(error)) => Err(error.clone()),
None => Err(ProfileLookupError::MissingIdentity),
}
}
async fn look_up(
profile: &str,
registry: &ConnectionRegistry,
) -> Result<ProfileFacts, ProfileLookupError> {
let entry = registry
.resolve(Some(profile))
.map_err(|e| ProfileLookupError::Connection(e.to_string()))?;
let identity = entry
.profile_id
.as_deref()
.ok_or(ProfileLookupError::MissingIdentity)
.and_then(|raw| {
ProfileIdentity::parse(raw)
.map_err(|e| ProfileLookupError::InvalidIdentity(e.to_string()))
})?;
let schema = entry
.connector
.schema()
.await
.map_err(|e| ProfileLookupError::Connection(e.to_string()))?;
Ok(ProfileFacts { identity, schema })
}
}