Compare commits
2 changed files with 0 additions and 64 deletions
|
|
@ -93,17 +93,6 @@ impl ConfigPrCache {
|
||||||
.cloned()
|
.cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Every agent with an open PR, per the last successful scan (plus any
|
|
||||||
/// webhook upserts since). The bulk counterpart to [`Self::get`] — for
|
|
||||||
/// `GET /api/config-prs` (swarm-ui's config-PR table), which needs every
|
|
||||||
/// agent's status in one round trip rather than one request per agent.
|
|
||||||
pub fn snapshot(&self) -> HashMap<String, ConfigPrStatus> {
|
|
||||||
self.0
|
|
||||||
.lock()
|
|
||||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
|
||||||
.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ⚠️ Can race [`Self::apply_webhook_delivery`]: a scan started before a
|
/// ⚠️ Can race [`Self::apply_webhook_delivery`]: a scan started before a
|
||||||
/// PR opened may finish *after* the webhook already upserted it, and
|
/// PR opened may finish *after* the webhook already upserted it, and
|
||||||
/// this snapshot — taken before that PR existed — will overwrite the
|
/// this snapshot — taken before that PR existed — will overwrite the
|
||||||
|
|
@ -232,21 +221,6 @@ mod tests {
|
||||||
assert_eq!(status.pr_number, 6);
|
assert_eq!(status.pr_number, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn snapshot_returns_every_agent_with_an_open_pr() {
|
|
||||||
let cache = ConfigPrCache::new();
|
|
||||||
assert!(
|
|
||||||
cache.snapshot().is_empty(),
|
|
||||||
"an unpopulated cache snapshots empty, not missing"
|
|
||||||
);
|
|
||||||
cache.apply_webhook_delivery(&payload("damocles", 5, "open"));
|
|
||||||
cache.apply_webhook_delivery(&payload("iris", 9, "open"));
|
|
||||||
let snapshot = cache.snapshot();
|
|
||||||
assert_eq!(snapshot.len(), 2);
|
|
||||||
assert_eq!(snapshot["damocles"].pr_number, 5);
|
|
||||||
assert_eq!(snapshot["iris"].pr_number, 9);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn a_malformed_payload_leaves_the_cache_unchanged() {
|
fn a_malformed_payload_leaves_the_cache_unchanged() {
|
||||||
let cache = ConfigPrCache::new();
|
let cache = ConfigPrCache::new();
|
||||||
|
|
|
||||||
|
|
@ -804,43 +804,6 @@ async fn get_agent_config_pr(
|
||||||
Ok(Json(cache.get(&name)))
|
Ok(Json(cache.get(&name)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Every agent with an open config PR, in one response — the bulk
|
|
||||||
/// counterpart to [`get_agent_config_pr`]. swarm-ui's config-PR table needs
|
|
||||||
/// every agent's status to render, and fetching them one at a time doesn't
|
|
||||||
/// scale and isn't how the rest of swarm-ui's single-fetch pages (jobq,
|
|
||||||
/// hives status) work.
|
|
||||||
///
|
|
||||||
/// Deliberately **not** `/api/agents/config-prs`: agent names are
|
|
||||||
/// user-specified (any string `hive_types::Ident` accepts), so a literal
|
|
||||||
/// path segment sitting where a `{name}` capture could plausibly also want
|
|
||||||
/// to live is a real, not theoretical, clash risk the moment someone names
|
|
||||||
/// an agent `config-prs` — per mara's review call, closed off by
|
|
||||||
/// construction rather than relying on axum's static-route-priority
|
|
||||||
/// tiebreak to paper over it.
|
|
||||||
///
|
|
||||||
/// Only agents with a currently-open PR are present — same "absence is the
|
|
||||||
/// answer" shape [`get_agent_config_pr`]'s `null` uses, just at map-entry
|
|
||||||
/// granularity instead of per-request.
|
|
||||||
#[utoipa::path(
|
|
||||||
get,
|
|
||||||
path = "/api/config-prs",
|
|
||||||
responses(
|
|
||||||
(status = 200, description = "agent name -> open config PR, only agents with one present", body = std::collections::HashMap<String, forge::ConfigPrStatus>),
|
|
||||||
(status = 503, description = "no forge is configured on this host", body = String),
|
|
||||||
),
|
|
||||||
tag = "agents"
|
|
||||||
)]
|
|
||||||
async fn get_config_prs(
|
|
||||||
State(state): State<AppState>,
|
|
||||||
) -> Result<Json<std::collections::HashMap<String, forge::ConfigPrStatus>>, StatusUnavailable> {
|
|
||||||
let Some(cache) = state.config_prs.as_ref() else {
|
|
||||||
return Err(StatusUnavailable(
|
|
||||||
"no forge is configured on this host".to_owned(),
|
|
||||||
));
|
|
||||||
};
|
|
||||||
Ok(Json(cache.snapshot()))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The swarm's own public base URL, as the forge must address it.
|
/// The swarm's own public base URL, as the forge must address it.
|
||||||
///
|
///
|
||||||
/// Set by `swarm-controller.nix` **only when this host actually serves the
|
/// Set by `swarm-controller.nix` **only when this host actually serves the
|
||||||
|
|
@ -1042,7 +1005,6 @@ async fn main() -> Result<()> {
|
||||||
.routes(routes!(get_jobq_graph))
|
.routes(routes!(get_jobq_graph))
|
||||||
.routes(routes!(get_jobq_rollup))
|
.routes(routes!(get_jobq_rollup))
|
||||||
.routes(routes!(get_agent_config_pr))
|
.routes(routes!(get_agent_config_pr))
|
||||||
.routes(routes!(get_config_prs))
|
|
||||||
.routes(routes!(create_agent))
|
.routes(routes!(create_agent))
|
||||||
.routes(routes!(webhook::post_webhook_forge))
|
.routes(routes!(webhook::post_webhook_forge))
|
||||||
.split_for_parts();
|
.split_for_parts();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue