systemprompt_provider_contracts/config_plane/
set.rs1use std::collections::{BTreeMap, HashSet};
21use std::fmt;
22use std::path::{Path, PathBuf};
23use std::sync::Arc;
24
25use serde::{Deserialize, Serialize};
26
27use super::{ConfigPlane, ConfigPlaneError, ConfigPlaneResult};
28
29#[derive(
32 Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize, schemars::JsonSchema,
33)]
34#[serde(rename_all = "lowercase")]
35pub enum PlaneAuthority {
36 #[default]
37 File,
38 Db,
39}
40
41impl PlaneAuthority {
42 #[must_use]
43 pub const fn as_str(self) -> &'static str {
44 match self {
45 Self::File => "file",
46 Self::Db => "db",
47 }
48 }
49}
50
51#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
54#[serde(rename_all = "snake_case")]
55pub enum EffectiveAuthority {
56 File,
57 Db,
58 Undeclared,
59}
60
61impl EffectiveAuthority {
62 #[must_use]
63 pub const fn as_str(self) -> &'static str {
64 match self {
65 Self::File => "file",
66 Self::Db => "db",
67 Self::Undeclared => "undeclared",
68 }
69 }
70
71 #[must_use]
72 pub const fn is_file_managed(self) -> bool {
73 matches!(self, Self::File)
74 }
75}
76
77pub struct PlaneWriter<'a> {
83 plane: &'a dyn ConfigPlane,
84 authority: EffectiveAuthority,
85}
86
87impl<'a> PlaneWriter<'a> {
88 #[must_use]
89 pub fn plane(&self) -> &'a dyn ConfigPlane {
90 self.plane
91 }
92
93 #[must_use]
94 pub fn name(&self) -> &'static str {
95 self.plane.name()
96 }
97
98 #[must_use]
99 pub const fn authority(&self) -> EffectiveAuthority {
100 self.authority
101 }
102}
103
104impl fmt::Debug for PlaneWriter<'_> {
105 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106 f.debug_struct("PlaneWriter")
107 .field("plane", &self.plane.name())
108 .field("authority", &self.authority)
109 .finish()
110 }
111}
112
113#[derive(Clone)]
114pub struct ConfigPlaneSet {
115 planes: Vec<Arc<dyn ConfigPlane>>,
116 authority: BTreeMap<String, PlaneAuthority>,
117 services_root: PathBuf,
118}
119
120impl fmt::Debug for ConfigPlaneSet {
121 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122 f.debug_struct("ConfigPlaneSet")
123 .field("planes", &self.names())
124 .field("authority", &self.authority)
125 .field("services_root", &self.services_root)
126 .finish()
127 }
128}
129
130impl ConfigPlaneSet {
131 pub fn new(
132 planes: Vec<Arc<dyn ConfigPlane>>,
133 authority: BTreeMap<String, PlaneAuthority>,
134 services_root: PathBuf,
135 ) -> ConfigPlaneResult<Self> {
136 Ok(Self {
137 planes: dependency_order(planes)?,
138 authority,
139 services_root,
140 })
141 }
142
143 #[must_use]
144 pub fn planes(&self) -> &[Arc<dyn ConfigPlane>] {
145 &self.planes
146 }
147
148 #[must_use]
149 pub fn names(&self) -> Vec<&'static str> {
150 self.planes.iter().map(|p| p.name()).collect()
151 }
152
153 #[must_use]
154 pub fn services_root(&self) -> &Path {
155 &self.services_root
156 }
157
158 pub fn find(&self, name: &str) -> ConfigPlaneResult<&Arc<dyn ConfigPlane>> {
159 self.planes
160 .iter()
161 .find(|p| p.name() == name)
162 .ok_or_else(|| ConfigPlaneError::UnknownPlane(name.to_owned()))
163 }
164
165 #[must_use]
166 pub fn declared_exists(&self, plane: &dyn ConfigPlane) -> bool {
167 self.services_root.join(plane.declared_path()).exists()
168 }
169
170 #[must_use]
171 pub fn authority_of(&self, plane: &dyn ConfigPlane) -> EffectiveAuthority {
172 match self
173 .authority
174 .get(plane.name())
175 .copied()
176 .unwrap_or_default()
177 {
178 PlaneAuthority::Db => EffectiveAuthority::Db,
179 PlaneAuthority::File if self.declared_exists(plane) => EffectiveAuthority::File,
180 PlaneAuthority::File => EffectiveAuthority::Undeclared,
181 }
182 }
183
184 pub fn authority(&self, name: &str) -> ConfigPlaneResult<EffectiveAuthority> {
185 Ok(self.authority_of(self.find(name)?.as_ref()))
186 }
187
188 pub fn writer(&self, name: &str) -> ConfigPlaneResult<PlaneWriter<'_>> {
189 let plane = self.find(name)?;
190 let authority = self.authority_of(plane.as_ref());
191 if authority.is_file_managed() {
192 return Err(ConfigPlaneError::FileManaged {
193 plane: name.to_owned(),
194 path: plane.declared_path().to_owned(),
195 });
196 }
197 Ok(PlaneWriter {
198 plane: plane.as_ref(),
199 authority,
200 })
201 }
202
203 #[must_use]
204 pub fn unregistered_authority_keys(&self) -> Vec<&str> {
205 self.authority
206 .keys()
207 .map(String::as_str)
208 .filter(|key| !self.planes.iter().any(|p| p.name() == *key))
209 .collect()
210 }
211}
212
213fn dependency_order(
214 planes: Vec<Arc<dyn ConfigPlane>>,
215) -> ConfigPlaneResult<Vec<Arc<dyn ConfigPlane>>> {
216 let mut seen = HashSet::new();
217 for plane in &planes {
218 if !seen.insert(plane.name()) {
219 return Err(ConfigPlaneError::DuplicatePlane(plane.name().to_owned()));
220 }
221 }
222 for plane in &planes {
223 if let Some(missing) = plane.depends_on().iter().find(|dep| !seen.contains(*dep)) {
224 return Err(ConfigPlaneError::UnknownDependency {
225 plane: plane.name().to_owned(),
226 dependency: (*missing).to_owned(),
227 });
228 }
229 }
230 let mut pending: Vec<Option<Arc<dyn ConfigPlane>>> = planes.into_iter().map(Some).collect();
231 let mut placed: HashSet<&'static str> = HashSet::new();
232 let mut ordered = Vec::with_capacity(pending.len());
233 while ordered.len() < pending.len() {
234 let ready = pending.iter().position(|slot| {
235 slot.as_ref()
236 .is_some_and(|p| p.depends_on().iter().all(|dep| placed.contains(dep)))
237 });
238 let Some(index) = ready else {
239 let stuck = pending.iter().flatten().next().map_or("", |p| p.name());
240 return Err(ConfigPlaneError::DependencyCycle(stuck.to_owned()));
241 };
242 if let Some(plane) = pending.get_mut(index).and_then(Option::take) {
243 placed.insert(plane.name());
244 ordered.push(plane);
245 }
246 }
247 Ok(ordered)
248}