assay_workflow/api/
activities.rs1use std::sync::Arc;
4
5use axum::extract::{Path, State};
6use axum::routing::{get, post};
7use axum::{Json, Router};
8use serde::Deserialize;
9use utoipa::ToSchema;
10
11use crate::api::workflows::AppError;
12use crate::ctx::WorkflowCtx;
13use crate::store::WorkflowStore;
14use crate::types::{ScheduleActivityOpts, WorkflowActivity};
15
16pub fn router<S: WorkflowStore + 'static>() -> Router<Arc<WorkflowCtx<S>>> {
17 Router::new()
18 .route("/workflows/{id}/activities", post(schedule_activity))
19 .route("/activities/{id}", get(get_activity))
20}
21
22#[derive(Deserialize, ToSchema)]
23pub struct ScheduleActivityRequest {
24 pub name: String,
26 pub seq: i32,
30 pub task_queue: String,
32 pub input: Option<serde_json::Value>,
34 pub max_attempts: Option<i32>,
36 pub initial_interval_secs: Option<f64>,
38 pub backoff_coefficient: Option<f64>,
40 pub start_to_close_secs: Option<f64>,
42 pub heartbeat_timeout_secs: Option<f64>,
44}
45
46#[utoipa::path(
47 post, path = "/api/v1/workflows/{id}/activities",
48 tag = "activities",
49 params(("id" = String, Path, description = "Workflow ID")),
50 request_body = ScheduleActivityRequest,
51 responses(
52 (status = 201, description = "Activity scheduled", body = WorkflowActivity),
53 ),
54)]
55pub async fn schedule_activity<S: WorkflowStore>(
56 State(state): State<Arc<WorkflowCtx<S>>>,
57 Path(workflow_id): Path<String>,
58 Json(req): Json<ScheduleActivityRequest>,
59) -> Result<(axum::http::StatusCode, Json<WorkflowActivity>), AppError> {
60 let input = req.input.map(|v| v.to_string());
61 let opts = ScheduleActivityOpts {
62 max_attempts: req.max_attempts,
63 initial_interval_secs: req.initial_interval_secs,
64 backoff_coefficient: req.backoff_coefficient,
65 start_to_close_secs: req.start_to_close_secs,
66 heartbeat_timeout_secs: req.heartbeat_timeout_secs,
67 };
68 let act = state
69 .schedule_activity(
70 &workflow_id,
71 req.seq,
72 &req.name,
73 input.as_deref(),
74 &req.task_queue,
75 opts,
76 )
77 .await?;
78 Ok((axum::http::StatusCode::CREATED, Json(act)))
79}
80
81#[utoipa::path(
82 get, path = "/api/v1/activities/{id}",
83 tag = "activities",
84 params(("id" = i64, Path, description = "Activity ID")),
85 responses(
86 (status = 200, description = "Activity record", body = WorkflowActivity),
87 (status = 404, description = "Not found"),
88 ),
89)]
90pub async fn get_activity<S: WorkflowStore>(
91 State(state): State<Arc<WorkflowCtx<S>>>,
92 Path(id): Path<i64>,
93) -> Result<Json<WorkflowActivity>, AppError> {
94 match state.get_activity(id).await? {
95 Some(a) => Ok(Json(a)),
96 None => Err(AppError::NotFound(format!("activity {id} not found"))),
97 }
98}