Skip to main content

graphwalker_restful/
rest.rs

1use 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    send_command(&state.machine_tx, |reply| Command::Load {
40        json_body: body,
41        seed: state.default_seed,
42        global_data: None,
43        reply,
44    })
45    .await
46}
47
48pub async fn has_next(State(state): State<RestState>) -> (StatusCode, Json<Value>) {
49    send_command(&state.machine_tx, |reply| Command::HasNext { reply }).await
50}
51
52pub async fn get_next(State(state): State<RestState>) -> (StatusCode, Json<Value>) {
53    send_command(&state.machine_tx, |reply| Command::GetNext {
54        verbose: false,
55        reply,
56    })
57    .await
58}
59
60pub async fn get_data(State(state): State<RestState>) -> (StatusCode, Json<Value>) {
61    send_command(&state.machine_tx, |reply| Command::GetData { reply }).await
62}
63
64pub async fn set_data(
65    State(state): State<RestState>,
66    Path(script): Path<String>,
67) -> (StatusCode, Json<Value>) {
68    send_command(&state.machine_tx, |reply| Command::SetData { script, reply }).await
69}
70
71pub async fn restart(State(state): State<RestState>) -> (StatusCode, Json<Value>) {
72    send_command(&state.machine_tx, |reply| Command::Restart { reply }).await
73}
74
75pub async fn get_statistics(State(state): State<RestState>) -> (StatusCode, Json<Value>) {
76    send_command(&state.machine_tx, |reply| Command::GetStatistics { reply }).await
77}