hive-c0re: annotate remaining dashboard routes with utoipa
This commit is contained in:
parent
8ebefeb0d5
commit
582ebe5eee
21 changed files with 738 additions and 45 deletions
|
|
@ -14,12 +14,25 @@ use axum::{
|
|||
use problem_details::ProblemDetails;
|
||||
|
||||
use crate::scheduled_prompts::ScheduleNotFoundOrCancelled;
|
||||
use crate::scheduled_prompts_worker::FireNowReport;
|
||||
|
||||
use super::{AppState, error_problem, error_response};
|
||||
|
||||
/// `GET /api/schedules` — snapshot of every schedule for the
|
||||
/// scheduled-prompts tab. Returns the wire shape directly
|
||||
/// so the frontend can render without an extra translation layer.
|
||||
// `hive_sh4re::WireSchedule` (the actual body) has no `ToSchema` — adding
|
||||
// one would pull `utoipa` into the wire-types crate for a single dashboard
|
||||
// endpoint. `serde_json::Value` placeholder; see the batch report.
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/api/schedules",
|
||||
responses(
|
||||
(status = 200, description = "every schedule, wire shape", body = Vec<serde_json::Value>),
|
||||
(status = 500, description = "sqlite read failed"),
|
||||
),
|
||||
tag = "schedules"
|
||||
)]
|
||||
pub(super) async fn api_schedules(State(state): State<AppState>) -> Response {
|
||||
match state.coord.scheduled_prompts.list() {
|
||||
Ok(rows) => {
|
||||
|
|
@ -50,6 +63,20 @@ pub(super) async fn api_schedules(State(state): State<AppState>) -> Response {
|
|||
/// skips the approval gate — the operator click *is* the
|
||||
/// approval. The schedule lands directly with
|
||||
/// `source = Operator` and the worker picks it up at fire time.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/schedules",
|
||||
// `hive_sh4re::SchedulePromptPayload` (the actual body) has no `ToSchema` —
|
||||
// same reasoning as the `Vec<serde_json::Value>` placeholder on
|
||||
// `api_schedules` above.
|
||||
request_body(content = serde_json::Value, description = "SchedulePromptPayload wire shape"),
|
||||
responses(
|
||||
(status = 200, description = "created; body carries the new row id", body = serde_json::Value),
|
||||
(status = 400, description = "no targets, empty body, or interval_seconds == 0"),
|
||||
(status = 500, description = "submit failed"),
|
||||
),
|
||||
tag = "schedules"
|
||||
)]
|
||||
pub(super) async fn post_schedule_new(
|
||||
State(state): State<AppState>,
|
||||
axum::Json(payload): axum::Json<hive_sh4re::SchedulePromptPayload>,
|
||||
|
|
@ -86,7 +113,7 @@ pub(super) async fn post_schedule_new(
|
|||
|
||||
/// Optional JSON body for `fire-now`. Absent / empty body ⇒
|
||||
/// `reset_timer = false` (back-compat: cadence stays intact).
|
||||
#[derive(serde::Deserialize, Default)]
|
||||
#[derive(serde::Deserialize, Default, utoipa::ToSchema)]
|
||||
pub(super) struct FireNowBody {
|
||||
#[serde(default)]
|
||||
reset_timer: bool,
|
||||
|
|
@ -100,6 +127,17 @@ pub(super) struct FireNowBody {
|
|||
/// wrong." For recurring schedules the cadence stays intact unless
|
||||
/// the body carries `{"reset_timer": true}`, in which case the
|
||||
/// countdown is re-armed from now (`next_fire_at = now + interval`).
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/schedules/{id}/fire-now",
|
||||
params(("id" = i64, Path, description = "schedule row id")),
|
||||
request_body(content = FireNowBody, description = "optional; absent body means reset_timer = false"),
|
||||
responses(
|
||||
(status = 200, description = "fired; per-target outcome counts", body = FireNowReport),
|
||||
(status = 500, description = "schedule missing, cancelled, or fully drained"),
|
||||
),
|
||||
tag = "schedules"
|
||||
)]
|
||||
pub(super) async fn post_schedule_fire_now(
|
||||
State(state): State<AppState>,
|
||||
AxumPath(id): AxumPath<i64>,
|
||||
|
|
@ -123,6 +161,13 @@ pub(super) async fn post_schedule_fire_now(
|
|||
/// flip to Cancelled, `{"cancelled": false}` when the DAG was
|
||||
/// Running / terminal / gone. On success a fresh `RebuildQueueChanged`
|
||||
/// snapshot fires so the state flip surfaces live.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/rebuild-queue/{id}/cancel",
|
||||
params(("id" = u64, Path, description = "job-queue DAG id")),
|
||||
responses((status = 200, description = "whether the DAG was cancelled", body = serde_json::Value)),
|
||||
tag = "schedules"
|
||||
)]
|
||||
pub(super) async fn post_rebuild_queue_cancel(
|
||||
State(state): State<AppState>,
|
||||
AxumPath(id): AxumPath<u64>,
|
||||
|
|
@ -137,14 +182,14 @@ pub(super) async fn post_rebuild_queue_cancel(
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, Default)]
|
||||
#[derive(serde::Deserialize, Default, utoipa::ToSchema)]
|
||||
pub(super) struct CancelScheduleForm {
|
||||
/// `None` / absent / empty array → cancel whole schedule.
|
||||
#[serde(default)]
|
||||
targets: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, Default)]
|
||||
#[derive(serde::Deserialize, Default, utoipa::ToSchema)]
|
||||
#[allow(
|
||||
clippy::option_option,
|
||||
reason = "double-Option carries three-state PATCH semantics on the wire \
|
||||
|
|
@ -203,6 +248,16 @@ where
|
|||
/// `interval_seconds`. Cancelled schedules are refused — submit
|
||||
/// a new one instead. Returns the updated `WireSchedule` so the
|
||||
/// caller's post-edit refresh has the new state inline.
|
||||
#[utoipa::path(
|
||||
patch,
|
||||
path = "/api/schedules/{id}",
|
||||
params(("id" = i64, Path, description = "schedule row id")),
|
||||
responses(
|
||||
(status = 200, description = "updated, wire shape", body = serde_json::Value),
|
||||
(status = 500, description = "update failed (cancelled, not found, ...)"),
|
||||
),
|
||||
tag = "schedules"
|
||||
)]
|
||||
pub(super) async fn patch_schedule(
|
||||
State(state): State<AppState>,
|
||||
AxumPath(id): AxumPath<i64>,
|
||||
|
|
@ -233,6 +288,17 @@ pub(super) async fn patch_schedule(
|
|||
/// `POST /api/schedules/{id}/pause` — pause a schedule so the worker
|
||||
/// skips it until explicitly resumed. Idempotent; no-op on an already-
|
||||
/// paused row. Returns 404 when the schedule is cancelled or not found.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/schedules/{id}/pause",
|
||||
params(("id" = i64, Path, description = "schedule row id")),
|
||||
responses(
|
||||
(status = 200, description = "paused", body = String),
|
||||
(status = 404, description = "schedule cancelled or not found"),
|
||||
(status = 500, description = "pause failed"),
|
||||
),
|
||||
tag = "schedules"
|
||||
)]
|
||||
pub(super) async fn post_schedule_pause(
|
||||
State(state): State<AppState>,
|
||||
AxumPath(id): AxumPath<i64>,
|
||||
|
|
@ -255,6 +321,17 @@ pub(super) async fn post_schedule_pause(
|
|||
/// `POST /api/schedules/{id}/resume` — resume a paused schedule.
|
||||
/// Idempotent; no-op on an already-active row. Returns 404 when the
|
||||
/// schedule is cancelled or not found.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/schedules/{id}/resume",
|
||||
params(("id" = i64, Path, description = "schedule row id")),
|
||||
responses(
|
||||
(status = 200, description = "resumed", body = String),
|
||||
(status = 404, description = "schedule cancelled or not found"),
|
||||
(status = 500, description = "resume failed"),
|
||||
),
|
||||
tag = "schedules"
|
||||
)]
|
||||
pub(super) async fn post_schedule_resume(
|
||||
State(state): State<AppState>,
|
||||
AxumPath(id): AxumPath<i64>,
|
||||
|
|
@ -278,6 +355,16 @@ pub(super) async fn post_schedule_resume(
|
|||
/// (whole schedule when no `targets` field, partial when one is
|
||||
/// provided). Operator bypasses the topology check; the manager
|
||||
/// surface enforces it for agent callers.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/schedules/{id}/cancel",
|
||||
params(("id" = i64, Path, description = "schedule row id")),
|
||||
responses(
|
||||
(status = 200, description = "cancelled (whole or partial)", body = String),
|
||||
(status = 500, description = "cancel failed"),
|
||||
),
|
||||
tag = "schedules"
|
||||
)]
|
||||
pub(super) async fn post_schedule_cancel(
|
||||
State(state): State<AppState>,
|
||||
AxumPath(id): AxumPath<i64>,
|
||||
|
|
|
|||
Loading…
Reference in a new issue