assay_workflow/api/
mod.rs1pub mod activities;
2pub mod api_keys;
3pub mod auth;
4pub mod dashboard;
5pub mod events;
6pub mod meta;
7pub mod namespaces;
8pub mod openapi;
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 {
42 let needs_auth = state.auth_mode.is_enabled();
43
44 let api = Router::new()
45 .nest("/api/v1", api_v1_router())
46 .nest("/api/v1", events::router());
47
48 let api = if needs_auth {
49 api.layer(middleware::from_fn_with_state(
50 Arc::clone(&state),
51 auth::auth_middleware,
52 ))
53 } else {
54 api
55 };
56
57 let app = api
59 .merge(dashboard::router())
60 .merge(openapi::router());
61
62 app.with_state(state)
63}
64
65fn api_v1_router<S: WorkflowStore + 'static>() -> Router<Arc<AppState<S>>> {
66 Router::new()
67 .merge(workflows::router())
68 .merge(activities::router())
69 .merge(workflow_tasks::router())
70 .merge(tasks::router())
71 .merge(schedules::router())
72 .merge(workers::router())
73 .merge(namespaces::router())
74 .merge(queues::router())
75 .merge(api_keys::router())
76 .merge(meta::router())
77}
78
79pub async fn serve<S: WorkflowStore + 'static>(
81 engine: Engine<S>,
82 port: u16,
83 auth_mode: AuthMode,
84) -> anyhow::Result<()> {
85 serve_with_version(engine, port, auth_mode, None).await
86}
87
88pub async fn serve_with_version<S: WorkflowStore + 'static>(
94 engine: Engine<S>,
95 port: u16,
96 auth_mode: AuthMode,
97 binary_version: Option<&'static str>,
98) -> anyhow::Result<()> {
99 let (event_tx, _) = broadcast::channel(1024);
100
101 let mode_desc = auth_mode.describe();
102
103 let state = Arc::new(AppState {
104 engine: Arc::new(engine),
105 event_tx,
106 auth_mode,
107 binary_version,
108 });
109
110 let app = router(state);
111 let listener = tokio::net::TcpListener::bind(format!("0.0.0.0:{port}")).await?;
112 info!("Workflow API listening on 0.0.0.0:{port} (auth: {mode_desc})");
113
114 axum::serve(listener, app).await?;
115 Ok(())
116}