54 lines
2.0 KiB
Rust
54 lines
2.0 KiB
Rust
impl App {
|
|
/// Rebuild only the effective routing snapshot from the latest Docker observations.
|
|
/// Desired configuration and its SQLite revision remain unchanged.
|
|
pub async fn reconcile_docker(self: &Arc<Self>) -> Result<(), ApiError> {
|
|
let _lock = self.update_lock.lock().await;
|
|
let previous = self.config.load_full();
|
|
let desired = previous.envelope.config.clone();
|
|
let desired_vhost_count = desired.vhosts.len();
|
|
let observed = self.docker.snapshot().await;
|
|
let policy = self.policy.clone();
|
|
let defaults = self.startup_listeners;
|
|
let active_listeners = self.active_listeners.clone();
|
|
let revision = previous.envelope.revision;
|
|
let prepared = tokio::task::spawn_blocking(move || {
|
|
let effective = crate::docker::effective_config(desired, &observed)?;
|
|
let mut prepared = config::compile_with_active(
|
|
effective,
|
|
revision,
|
|
&policy,
|
|
defaults,
|
|
Some(&previous),
|
|
&active_listeners,
|
|
)?;
|
|
prepared
|
|
.envelope
|
|
.config
|
|
.vhosts
|
|
.truncate(desired_vhost_count);
|
|
Ok::<_, anyhow::Error>(prepared)
|
|
})
|
|
.await
|
|
.map_err(|_| {
|
|
ApiError(
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
"Docker reconcile task failed".into(),
|
|
)
|
|
})?
|
|
.map_err(|error| ApiError(StatusCode::UNPROCESSABLE_ENTITY, format!("{error:#}")))?;
|
|
self.config.store(Arc::new(prepared));
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn refresh_docker(
|
|
self: &Arc<Self>,
|
|
) -> Result<Vec<crate::docker::Observation>, ApiError> {
|
|
let settings = self.config.load().envelope.config.docker_agents.clone();
|
|
let (observations, changed) = self.docker.refresh(&settings, true).await;
|
|
if changed {
|
|
self.reconcile_docker().await?;
|
|
}
|
|
Ok(observations)
|
|
}
|
|
}
|