Watch
0
0
Fork
You've already forked hyperhive
0

swarm-controller: record the review classifier's runs and list them

Every run is recorded when it ends: a try-out when its reply settles it,
a requested review once its review is posted or the post fails, and a
request turned away by a full queue once its comment is posted. A
duplicate request that starts nothing is not recorded. The newest 100
are one JSON array under `recent` in a new controller-owned KV bucket,
`review-classifier-runs`, written with compare-and-set as
`schedule-definitions` is (five attempts). A failed write is logged; the
review is already posted by then.

Each recorded run is also one info event, "review classifier run
finished", with the record's fields as tracing fields. The controller
logs natively to the journal, so they reach VictoriaLogs as F_<NAME>.

GET /api/review-classifier/runs returns the list, newest first, gated
by the gateway like the try-out GET. post_classifier_review now returns
the posted review's html_url, which the record keeps as review_url.

Closes #5153, part of #5096.
This commit is contained in:
atlas 2026-10-12 19:23:28 +02:00
commit 2fc0166427
14 changed files with 1138 additions and 66 deletions

View file

@ -898,6 +898,8 @@ struct AppState {
try_outs: review_classifier::TryOuts,
/// The requested reviews running or waiting.
reviews: Arc<review_classifier::review::Reviews>,
/// The review classifier's finished runs.
runs: review_classifier::runs::Runs,
}
/// Env var the controller's NixOS module sets from
@ -3253,6 +3255,7 @@ async fn main() -> Result<()> {
// what `policy::render_agent` grants today reaches them only from here.
read_policy::ensure_agent_policies().await;
let runs = review_classifier::runs::Runs::Live(status.as_ref().map(|s| s.queue_client()));
let state = AppState {
hives: Arc::new(hives),
links: Arc::new(load_links()),
@ -3271,6 +3274,7 @@ async fn main() -> Result<()> {
accounts: linked_accounts::Accounts::Live,
try_outs: review_classifier::TryOuts::default(),
reviews: Arc::default(),
runs,
};
let app = build_app(state);
@ -3346,6 +3350,7 @@ fn build_app(state: AppState) -> axum::Router {
.routes(routes!(review_classifier::post_try_out))
.routes(routes!(review_classifier::get_try_out))
.routes(routes!(review_classifier::get_rules))
.routes(routes!(review_classifier::runs::get_runs))
.routes(routes!(webhook::post_webhook_forge))
.split_for_parts();
// Just the JSON, not the UI — Swagger UI itself is nginx-hosted from
@ -3467,6 +3472,7 @@ mod tests {
accounts: super::linked_accounts::Accounts::Fake(std::sync::Arc::default()),
try_outs: super::review_classifier::TryOuts::default(),
reviews: std::sync::Arc::default(),
runs: super::review_classifier::runs::Runs::Live(None),
};
(state, sched)
}