liminal_server/config/validation/
profiles.rs1use crate::ServerError;
2use crate::config::types::{SelfStreamsConfig, ServerConfig, ServiceProfile};
3
4impl SelfStreamsConfig {
10 pub fn validate(&self) -> Result<(), ServerError> {
15 let mut errors = Vec::new();
16 collect_self_stream_bound_errors(self, &mut errors);
17 if errors.is_empty() {
18 Ok(())
19 } else {
20 Err(ServerError::ConfigValidation {
21 message: errors.join("; "),
22 })
23 }
24 }
25}
26
27fn collect_self_stream_bound_errors(config: &SelfStreamsConfig, errors: &mut Vec<String>) {
28 errors.extend(
29 [
30 ("cost_rows", config.cost_rows),
31 ("events_rows", config.events_rows),
32 ]
33 .into_iter()
34 .filter(|(_, rows)| *rows == 0)
35 .map(|(name, _)| format!("services.self_streams.{name}: must be non-zero")),
36 );
37}
38
39pub(super) fn validate_services(config: &ServerConfig, errors: &mut Vec<String>) {
40 collect_self_stream_bound_errors(&config.services.self_streams, errors);
41 let profile = match config.services.profile() {
42 Ok(profile) => profile,
43 Err(error) => {
44 match error {
48 crate::ServerError::ConfigValidation { message } => errors.push(message),
49 other => errors.push(other.to_string()),
50 }
51 return;
52 }
53 };
54
55 if profile == ServiceProfile::WorkerFrontDoor {
56 errors.extend(worker_front_door_field_errors(config));
57 }
58}
59
60pub fn worker_front_door_field_errors(config: &ServerConfig) -> Vec<String> {
73 let mut errors = Vec::new();
74 if !config.channels.is_empty() {
75 errors.push(
76 "services.profile: \"worker-front-door\" builds no channels; remove the \
77 [[channels]] entries or use profile = \"full\""
78 .to_owned(),
79 );
80 }
81 if !config.routing_rules.is_empty() {
82 errors.push(
83 "services.profile: \"worker-front-door\" builds no channels to route between; \
84 remove the [[routing_rules]] entries or use profile = \"full\""
85 .to_owned(),
86 );
87 }
88 if config.persistence_path.is_some() {
89 errors.push(
90 "services.profile: \"worker-front-door\" builds no durable store; remove \
91 persistence_path or use profile = \"full\""
92 .to_owned(),
93 );
94 }
95 if config.cluster.is_some() {
96 errors.push(
97 "services.profile: \"worker-front-door\" builds no channel cluster; remove the \
98 [cluster] section or use profile = \"full\""
99 .to_owned(),
100 );
101 }
102 if config.participant.is_some() {
103 errors.push(
104 "services.profile: \"worker-front-door\" installs no participant service; remove \
105 the [participant] section or use profile = \"full\""
106 .to_owned(),
107 );
108 }
109 errors
110}