assay_workflow/api/
mod.rs1pub mod activities;
2pub mod api_keys;
3pub mod auth;
4pub mod dashboard;
5pub mod events;
6pub mod namespaces;
7pub mod openapi;
8pub mod public;
9pub mod queues;
10pub mod schedules;
11pub mod tasks;
12pub mod workers;
13pub mod workflow_tasks;
14pub mod workflows;
15
16use std::sync::Arc;
17
18use axum::middleware;
19use axum::Router;
20use tokio::sync::broadcast;
21use tracing::info;
22
23use crate::api::auth::AuthMode;
24use crate::engine::Engine;
25use crate::store::WorkflowStore;
26
27pub struct AppState<S: WorkflowStore> {
29 pub engine: Arc<Engine<S>>,
30 pub event_tx: broadcast::Sender<events::BroadcastEvent>,
31 pub auth_mode: AuthMode,
32 pub binary_version: Option<&'static str>,
38}
39
40pub fn router<S: WorkflowStore + 'static>(state: Arc<AppState<S>>) -> Router {
51 let needs_auth = state.auth_mode.is_enabled();
52
53 let authed_api = Router::new()
54 .nest("/api/v1", api_v1_router())
55 .nest("/api/v1", events::router());
56
57 let authed_api = if needs_auth {
58 authed_api.layer(middleware::from_fn_with_state(
59 Arc::clone(&state),
60 auth::auth_middleware,
61 ))
62 } else {
63 authed_api
64 };
65
66 let public_api = Router::new().nest("/api/v1", public::router());
68
69 let app = authed_api
70 .merge(public_api)
71 .merge(dashboard::router())
72 .merge(openapi::router());
73
74 app.with_state(state)
75}
76
77fn api_v1_router<S: WorkflowStore + 'static>() -> Router<Arc<AppState<S>>> {
78 Router::new()
79 .merge(workflows::router())
80 .merge(activities::router())
81 .merge(workflow_tasks::router())
82 .merge(tasks::router())
83 .merge(schedules::router())
84 .merge(workers::router())
85 .merge(namespaces::router())
86 .merge(queues::router())
87 .merge(api_keys::router())
88}
89
90pub async fn serve<S: WorkflowStore + 'static>(
92 engine: Engine<S>,
93 port: u16,
94 auth_mode: AuthMode,
95) -> anyhow::Result<()> {
96 serve_with_version(engine, port, auth_mode, None).await
97}
98
99pub async fn serve_with_version<S: WorkflowStore + 'static>(
105 engine: Engine<S>,
106 port: u16,
107 auth_mode: AuthMode,
108 binary_version: Option<&'static str>,
109) -> anyhow::Result<()> {
110 let (event_tx, _) = broadcast::channel(1024);
111
112 let mode_desc = auth_mode.describe();
113
114 let state = Arc::new(AppState {
115 engine: Arc::new(engine),
116 event_tx,
117 auth_mode,
118 binary_version,
119 });
120
121 let app = router(state);
122 let listener = tokio::net::TcpListener::bind(format!("0.0.0.0:{port}")).await?;
123 info!("Workflow API listening on 0.0.0.0:{port} (auth: {mode_desc})");
124
125 axum::serve(listener, app).await?;
126 Ok(())
127}