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