use axum::{ Json, extract::{Path, State}, }; use crate::{dto::ScheduledTaskResponse, error::ApiError, state::AppState}; #[utoipa::path( get, path = "/api/v1/scheduled-tasks", tag = "scheduled_tasks", responses( (status = 200, description = "List of scheduled tasks", body = Vec), (status = 401, description = "Unauthorized"), (status = 403, description = "Forbidden"), ), security(("bearer_auth" = [])) )] pub async fn list_scheduled_tasks( State(state): State, ) -> Result>, ApiError> { let tasks = state.scheduler.list_tasks().await; let responses: Vec = tasks .into_iter() .map(|t| { ScheduledTaskResponse { id: t.id, name: t.name, schedule: t.schedule.display_string(), enabled: t.enabled, last_run: t.last_run.map(|dt| dt.to_rfc3339()), next_run: t.next_run.map(|dt| dt.to_rfc3339()), last_status: t.last_status, } }) .collect(); Ok(Json(responses)) } #[utoipa::path( post, path = "/api/v1/scheduled-tasks/{id}/toggle", tag = "scheduled_tasks", params(("id" = String, Path, description = "Task ID")), responses( (status = 200, description = "Task toggled"), (status = 401, description = "Unauthorized"), (status = 403, description = "Forbidden"), (status = 404, description = "Not found"), ), security(("bearer_auth" = [])) )] pub async fn toggle_scheduled_task( State(state): State, Path(id): Path, ) -> Result, ApiError> { match state.scheduler.toggle_task(&id).await { Some(enabled) => { Ok(Json(serde_json::json!({ "id": id, "enabled": enabled, }))) }, None => { Err(ApiError(pinakes_core::error::PinakesError::NotFound( format!("scheduled task not found: {id}"), ))) }, } } #[utoipa::path( post, path = "/api/v1/scheduled-tasks/{id}/run", tag = "scheduled_tasks", params(("id" = String, Path, description = "Task ID")), responses( (status = 200, description = "Task triggered"), (status = 401, description = "Unauthorized"), (status = 403, description = "Forbidden"), (status = 404, description = "Not found"), ), security(("bearer_auth" = [])) )] pub async fn run_scheduled_task_now( State(state): State, Path(id): Path, ) -> Result, ApiError> { match state.scheduler.run_now(&id).await { Some(job_id) => { Ok(Json(serde_json::json!({ "id": id, "job_id": job_id, }))) }, None => { Err(ApiError(pinakes_core::error::PinakesError::NotFound( format!("scheduled task not found: {id}"), ))) }, } }