graphwalker_restful/
rest.rs1use std::sync::mpsc;
2
3use axum::extract::{Path, State};
4use axum::http::StatusCode;
5use axum::response::Json;
6use serde_json::{json, Value};
7use tokio::sync::oneshot;
8
9use crate::actor::Command;
10
11#[derive(Clone)]
12pub struct RestState {
13 pub machine_tx: mpsc::Sender<Command>,
14 pub default_seed: Option<u64>,
15}
16
17async fn send_command(
18 tx: &mpsc::Sender<Command>,
19 build: impl FnOnce(oneshot::Sender<Result<Value, String>>) -> Command,
20) -> (StatusCode, Json<Value>) {
21 let (reply_tx, reply_rx) = oneshot::channel();
22 if tx.send(build(reply_tx)).is_err() {
23 return (
24 StatusCode::INTERNAL_SERVER_ERROR,
25 Json(json!({"result": "nok", "error": "Machine thread unavailable"})),
26 );
27 }
28 match reply_rx.await {
29 Ok(Ok(val)) => (StatusCode::OK, Json(val)),
30 Ok(Err(msg)) => (StatusCode::OK, Json(json!({"result": "nok", "error": msg}))),
31 Err(_) => (
32 StatusCode::INTERNAL_SERVER_ERROR,
33 Json(json!({"result": "nok", "error": "Machine thread dropped"})),
34 ),
35 }
36}
37
38pub async fn load(State(state): State<RestState>, body: String) -> (StatusCode, Json<Value>) {
39 tracing::debug!(body_length = body.len(), "REST load request");
40 send_command(&state.machine_tx, |reply| Command::Load {
41 json_body: body,
42 seed: state.default_seed,
43 global_data: None,
44 reply,
45 })
46 .await
47}
48
49pub async fn has_next(State(state): State<RestState>) -> (StatusCode, Json<Value>) {
50 send_command(&state.machine_tx, |reply| Command::HasNext { reply }).await
51}
52
53pub async fn get_next(State(state): State<RestState>) -> (StatusCode, Json<Value>) {
54 tracing::trace!("REST next-step request");
55 send_command(&state.machine_tx, |reply| Command::GetNext {
56 verbose: false,
57 reply,
58 })
59 .await
60}
61
62pub async fn get_data(State(state): State<RestState>) -> (StatusCode, Json<Value>) {
63 send_command(&state.machine_tx, |reply| Command::GetData { reply }).await
64}
65
66pub async fn set_data(
67 State(state): State<RestState>,
68 Path(script): Path<String>,
69) -> (StatusCode, Json<Value>) {
70 tracing::debug!(script_length = script.len(), "REST set-data request");
71 send_command(&state.machine_tx, |reply| Command::SetData {
72 script,
73 reply,
74 })
75 .await
76}
77
78pub async fn restart(State(state): State<RestState>) -> (StatusCode, Json<Value>) {
79 tracing::debug!("REST restart request");
80 send_command(&state.machine_tx, |reply| Command::Restart { reply }).await
81}
82
83pub async fn get_statistics(State(state): State<RestState>) -> (StatusCode, Json<Value>) {
84 send_command(&state.machine_tx, |reply| Command::GetStatistics { reply }).await
85}