Skip to content

Commit 3e275df

Browse files
committed
wip: graph topology
1 parent ff29e86 commit 3e275df

File tree

3 files changed

+40
-15
lines changed

3 files changed

+40
-15
lines changed
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
11
// Test file to verify serializable ProcessingGraph functionality
2-
use rust_photoacoustic::processing::{ProcessingGraph, SerializableProcessingGraph};
32
use rust_photoacoustic::processing::nodes::{InputNode, ProcessingNode};
3+
use rust_photoacoustic::processing::{ProcessingGraph, SerializableProcessingGraph};
44

55
fn main() -> anyhow::Result<()> {
66
// Create a simple processing graph
77
let mut graph = ProcessingGraph::new();
8-
8+
99
// Add an input node
1010
let input_node = Box::new(InputNode::new("main_input".to_string()));
1111
graph.add_node(input_node)?;
12-
12+
1313
// Convert to serializable format
1414
let serializable_graph: SerializableProcessingGraph = graph.into();
15-
15+
1616
// Verify the conversion
1717
println!("Serializable Graph Created Successfully!");
1818
println!("Number of nodes: {}", serializable_graph.nodes.len());
1919
println!("Input node: {:?}", serializable_graph.input_node);
2020
println!("Graph is valid: {}", serializable_graph.is_valid);
21-
21+
2222
if let Some(node) = serializable_graph.nodes.first() {
2323
println!("First node: {} (type: {})", node.id, node.node_type);
2424
println!("Accepts input types: {:?}", node.accepts_input_types);
2525
}
26-
26+
2727
// Try serializing to JSON
2828
match serde_json::to_string_pretty(&serializable_graph) {
2929
Ok(json) => {
@@ -34,8 +34,8 @@ fn main() -> anyhow::Result<()> {
3434
println!("JSON serialization failed: {}", e);
3535
}
3636
}
37-
37+
3838
println!("\n✅ All serializable ProcessingGraph functionality working correctly!");
39-
39+
4040
Ok(())
4141
}

rust/src/visualization/api/get/graph_statistics.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@
1010
1111
use rocket::serde::json::Json;
1212
use rocket::{get, response::status, State};
13+
use rocket_okapi::okapi::openapi3::OpenApi;
14+
use rocket_okapi::openapi_get_routes_spec;
1315

1416
use crate::processing::graph::ProcessingGraphStatistics;
17+
use crate::processing::SerializableProcessingGraph;
1518
use crate::visualization::shared_state::SharedVisualizationState;
1619
use auth_macros::openapi_protect_get;
1720

@@ -73,7 +76,7 @@ use auth_macros::openapi_protect_get;
7376
/// - `403 Forbidden`: Token lacks required scope
7477
/// - `404 Not Found`: No processing is currently active
7578
/// - `500 Internal Server Error`: Server error accessing statistics
76-
#[openapi_protect_get("/api/graph-statistics", "read:api")]
79+
#[openapi_protect_get("/api/graph-statistics", "read:api", tag = "Processing")]
7780
pub async fn get_graph_statistics(
7881
state: &State<SharedVisualizationState>,
7982
) -> Result<Json<ProcessingGraphStatistics>, status::NotFound<String>> {
@@ -85,3 +88,21 @@ pub async fn get_graph_statistics(
8588
)),
8689
}
8790
}
91+
92+
/// Get processing graph information
93+
///
94+
/// Returns a JSON object representing SerializableProcessingGraph
95+
#[openapi_protect_get("/api/graph", "read:api", tag = "Processing")]
96+
pub async fn get_graph(
97+
state: &State<SharedVisualizationState>,
98+
) -> Result<Json<SerializableProcessingGraph>, status::NotFound<String>> {
99+
// Get the current processing graph from shared state
100+
Err(status::NotFound(
101+
"No processing graph is currently available".to_string(),
102+
))
103+
}
104+
105+
/// Centralized function to get all graph routes with OpenAPI documentation
106+
pub fn get_graph_routes() -> (Vec<rocket::Route>, OpenApi) {
107+
openapi_get_routes_spec![get_graph_statistics, get_graph]
108+
}

rust/src/visualization/server/builder.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -170,16 +170,20 @@ pub async fn build_rocket(
170170
let rocket_builder = rocket::custom(figment).attach(CORS);
171171

172172
// Add visualization state if available (before mounting routes that need it)
173-
let rocket_builder = if let Some(vis_state) = visualization_state {
173+
let (rocket_builder, openapi_spec_graph) = if let Some(vis_state) = visualization_state {
174174
debug!("Adding SharedVisualizationState to Rocket state management");
175175
// Extract the value from Arc to match the expected type for State<SharedVisualizationState>
176176
let shared_state = (*vis_state).clone();
177-
rocket_builder
178-
.manage(shared_state)
179-
.mount("/", routes![get_graph_statistics,])
177+
let (openapi_routes_graph, openapi_spec_graph) = get_graph_routes(); // Get graph routes and OpenAPI spec
178+
(
179+
rocket_builder
180+
.manage(shared_state)
181+
.mount("/", openapi_routes_graph),
182+
openapi_spec_graph,
183+
)
180184
} else {
181185
debug!("No visualization state provided, API will return 404 for statistics");
182-
rocket_builder
186+
(rocket_builder, OpenApi::default())
183187
};
184188

185189
let openapi_spec_audio: OpenApi;
@@ -245,7 +249,7 @@ pub async fn build_rocket(
245249
(openapi_routes_audio, openapi_spec_audio) = get_audio_streaming_routes();
246250

247251
// Merge the audio OpenAPI spec with the base spec
248-
let merged_spec = marge_spec_list(&[("/".to_string(), openapi_spec_base), ("/".to_string(),openapi_spec_audio)]).unwrap();
252+
let merged_spec = marge_spec_list(&[("/".to_string(), openapi_spec_base), ("/".to_string(),openapi_spec_audio), ("/".to_string(),openapi_spec_graph)]).unwrap();
249253
let openapi_settings = OpenApiSettings::default();
250254
rocket_builder
251255
.mount(

0 commit comments

Comments
 (0)