rs_zero/core/
dependency_config.rs1use std::collections::BTreeMap;
2
3use crate::core::ConfigFeatureWarning;
4#[cfg(any(feature = "rpc", feature = "discovery-etcd"))]
5use crate::core::CoreError;
6
7mod database;
8mod etcd;
9mod rpc;
10
11pub use database::{DatabaseKindSection, DatabaseSection};
12pub use etcd::{EtcdAuthSection, EtcdBackoffSection, EtcdDiscoverySection};
13pub use rpc::{
14 RpcClientProvider, RpcClientSection, RpcDeadlineSection, RpcLoadBalancePolicySection,
15 RpcLoadBalanceSection, RpcRetrySection, RpcStreamingSection,
16};
17
18pub type RpcClientsConfig = BTreeMap<String, RpcClientSection>;
20
21pub fn dependency_feature_warnings(
23 rpc_clients: &RpcClientsConfig,
24 database: Option<&DatabaseSection>,
25) -> Vec<ConfigFeatureWarning> {
26 let mut warnings = Vec::new();
27 if !rpc_clients.is_empty() && !cfg!(feature = "rpc") {
28 warnings.push(ConfigFeatureWarning::ignored("rpc_clients", "rpc"));
29 }
30 if rpc_clients
31 .values()
32 .any(|client| client.provider == RpcClientProvider::Etcd)
33 && !cfg!(feature = "discovery-etcd")
34 {
35 warnings.push(ConfigFeatureWarning::ignored(
36 "rpc_clients.*.etcd",
37 "discovery-etcd",
38 ));
39 }
40 if let Some(database) = database {
41 let required_feature = match database.kind {
42 DatabaseKindSection::Sqlite if !cfg!(feature = "db-sqlite") => Some("db-sqlite"),
43 DatabaseKindSection::Postgres if !cfg!(feature = "db-postgres") => Some("db-postgres"),
44 DatabaseKindSection::Mysql if !cfg!(feature = "db-mysql") => Some("db-mysql"),
45 _ => None,
46 };
47 if let Some(required_feature) = required_feature {
48 warnings.push(ConfigFeatureWarning::ignored(
49 "database.kind",
50 required_feature,
51 ));
52 }
53 }
54 warnings
55}
56
57#[cfg(any(feature = "rpc", feature = "discovery-etcd"))]
58fn config_error(message: impl Into<String>) -> CoreError {
59 config::ConfigError::Message(message.into()).into()
60}
61
62#[cfg(test)]
63mod tests {
64 use super::{DatabaseKindSection, DatabaseSection, RpcClientProvider, RpcClientSection};
65
66 #[test]
67 fn default_rpc_client_is_static_without_endpoint() {
68 let client = RpcClientSection::default();
69 assert_eq!(client.provider, RpcClientProvider::Static);
70 assert!(client.endpoint.is_empty());
71 assert!(client.retry.enabled);
72 }
73
74 #[test]
75 fn database_defaults_to_sqlite_memory() {
76 let database = DatabaseSection::default();
77 assert_eq!(database.kind, DatabaseKindSection::Sqlite);
78 assert_eq!(database.url, "sqlite::memory:");
79 }
80
81 #[cfg(feature = "rpc")]
82 #[test]
83 fn maps_rpc_client_runtime_config() {
84 let client = RpcClientSection {
85 endpoint: "http://127.0.0.1:50051".to_string(),
86 service: "hello-rpc".to_string(),
87 ..RpcClientSection::default()
88 };
89 let config = client.to_rpc_client_config().expect("rpc client config");
90 assert_eq!(config.endpoint, "http://127.0.0.1:50051");
91 assert_eq!(config.discovery.service.as_deref(), Some("hello-rpc"));
92 assert!(config.retry.enabled);
93 }
94}