diff --git a/src/service/client/mod.rs b/src/service/client/mod.rs index cc8d52d1..03b0a142 100644 --- a/src/service/client/mod.rs +++ b/src/service/client/mod.rs @@ -18,9 +18,7 @@ pub struct Service { impl crate::Service for Service { fn build(args: crate::Args<'_>) -> Result> { let config = &args.server.config; - let resolver = args - .get_service::("resolver") - .expect("resolver must be built prior to client"); + let resolver = args.require_service::("resolver"); Ok(Arc::new(Self { default: base(config) diff --git a/src/service/service.rs b/src/service/service.rs index 99b8723a..863b955b 100644 --- a/src/service/service.rs +++ b/src/service/service.rs @@ -1,7 +1,7 @@ use std::{any::Any, collections::BTreeMap, fmt::Write, sync::Arc}; use async_trait::async_trait; -use conduit::{utils::string::split_once_infallible, Result, Server}; +use conduit::{err, error::inspect_log, utils::string::split_once_infallible, Err, Result, Server}; use database::Database; #[async_trait] @@ -44,9 +44,26 @@ pub(crate) type Map = BTreeMap; pub(crate) type MapVal = (Arc, Arc); impl Args<'_> { - pub(crate) fn get_service(&self, name: &str) -> Option> { - get::(self.service, name) + pub(crate) fn require_service(&self, name: &str) -> Arc { + self.try_get_service::(name) + .inspect_err(inspect_log) + .expect("Failure to reference service required by another service.") } + + pub(crate) fn try_get_service(&self, name: &str) -> Result> { + try_get::(self.service, name) + } +} + +pub(crate) fn try_get(map: &Map, name: &str) -> Result> { + map.get(name).map_or_else( + || Err!("Service {name:?} does not exist or has not been built yet."), + |(_, s)| { + s.clone() + .downcast::() + .map_err(|_| err!("Service {name:?} must be correctly downcast.")) + }, + ) } pub(crate) fn get(map: &Map, name: &str) -> Option> { diff --git a/src/service/services.rs b/src/service/services.rs index d0f74e13..136059cd 100644 --- a/src/service/services.rs +++ b/src/service/services.rs @@ -173,5 +173,17 @@ impl Services { } } - pub fn get(&self, name: &str) -> Option> { service::get::(&self.service, name) } + pub fn try_get(&self, name: &str) -> Result> + where + T: Any + Send + Sync, + { + service::try_get::(&self.service, name) + } + + pub fn get(&self, name: &str) -> Option> + where + T: Any + Send + Sync, + { + service::get::(&self.service, name) + } }