assay_workflow/api/
workflow_tasks.rs1use std::sync::Arc;
21
22use axum::extract::{Path, State};
23use axum::routing::post;
24use axum::{Json, Router};
25use serde::Deserialize;
26use utoipa::ToSchema;
27
28use crate::api::workflows::AppError;
29use crate::ctx::WorkflowCtx;
30use crate::store::WorkflowStore;
31
32pub fn router<S: WorkflowStore + 'static>() -> Router<Arc<WorkflowCtx<S>>> {
33 Router::new()
34 .route("/workflow-tasks/poll", post(poll_workflow_task))
35 .route("/workflow-tasks/{id}/commands", post(submit_commands))
36}
37
38#[derive(Deserialize, ToSchema)]
39pub struct PollWorkflowTaskRequest {
40 pub queue: String,
41 pub worker_id: String,
42}
43
44#[utoipa::path(
47 post, path = "/api/v1/workflow-tasks/poll",
48 tag = "workflow-tasks",
49 request_body = PollWorkflowTaskRequest,
50 responses(
51 (status = 200, description = "Workflow task or null"),
52 ),
53)]
54pub async fn poll_workflow_task<S: WorkflowStore>(
55 State(state): State<Arc<WorkflowCtx<S>>>,
56 Json(req): Json<PollWorkflowTaskRequest>,
57) -> Result<Json<serde_json::Value>, AppError> {
58 match state
59 .claim_workflow_task(&req.queue, &req.worker_id)
60 .await?
61 {
62 Some((wf, history)) => Ok(Json(serde_json::json!({
63 "workflow_id": wf.id,
64 "namespace": wf.namespace,
65 "workflow_type": wf.workflow_type,
66 "task_queue": wf.task_queue,
67 "input": wf.input.as_deref().and_then(|s| serde_json::from_str::<serde_json::Value>(s).ok()),
68 "history": history.iter().map(|e| serde_json::json!({
69 "seq": e.seq,
70 "event_type": e.event_type,
71 "payload": e.payload.as_deref().and_then(|s| serde_json::from_str::<serde_json::Value>(s).ok()),
72 "timestamp": e.timestamp,
73 })).collect::<Vec<_>>(),
74 }))),
75 None => Ok(Json(serde_json::Value::Null)),
76 }
77}
78
79#[derive(Deserialize, ToSchema)]
80pub struct SubmitCommandsRequest {
81 pub worker_id: String,
82 pub commands: Vec<serde_json::Value>,
83}
84
85#[utoipa::path(
91 post, path = "/api/v1/workflow-tasks/{id}/commands",
92 tag = "workflow-tasks",
93 params(("id" = String, Path, description = "Workflow ID")),
94 request_body = SubmitCommandsRequest,
95 responses((status = 200, description = "Commands processed; lease released")),
96)]
97pub async fn submit_commands<S: WorkflowStore>(
98 State(state): State<Arc<WorkflowCtx<S>>>,
99 Path(workflow_id): Path<String>,
100 Json(req): Json<SubmitCommandsRequest>,
101) -> Result<axum::http::StatusCode, AppError> {
102 state
103 .submit_workflow_commands(&workflow_id, &req.worker_id, &req.commands)
104 .await?;
105 Ok(axum::http::StatusCode::OK)
106}