Interactive timer
This commit is contained in:
@ -1,12 +1,17 @@
|
|||||||
//! Executes KCL programs.
|
//! Executes KCL programs.
|
||||||
//! The server reuses the same engine session for each KCL program it receives.
|
//! The server reuses the same engine session for each KCL program it receives.
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use hyper::header::CONTENT_TYPE;
|
use hyper::header::CONTENT_TYPE;
|
||||||
use hyper::service::{make_service_fn, service_fn};
|
use hyper::service::{make_service_fn, service_fn};
|
||||||
use hyper::{Body, Error, Response, Server};
|
use hyper::{Body, Error, Response, Server};
|
||||||
use kcl_lib::executor::ExecutorContext;
|
use kcl_lib::executor::ExecutorContext;
|
||||||
use kcl_lib::settings::types::UnitLength;
|
use kcl_lib::settings::types::UnitLength;
|
||||||
|
use kcl_lib::test_server::RequestBody;
|
||||||
|
use tokio::sync::oneshot;
|
||||||
|
use tokio::task::JoinHandle;
|
||||||
|
use tokio::time::sleep;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> anyhow::Result<()> {
|
async fn main() -> anyhow::Result<()> {
|
||||||
@ -20,13 +25,6 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
start(listen_on).await
|
start(listen_on).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
|
||||||
pub struct RequestBody {
|
|
||||||
kcl_program: String,
|
|
||||||
#[serde(default)]
|
|
||||||
test_name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn start(listen_on: SocketAddr) -> anyhow::Result<()> {
|
pub async fn start(listen_on: SocketAddr) -> anyhow::Result<()> {
|
||||||
let state = ExecutorContext::new_for_unit_test(UnitLength::Mm).await?;
|
let state = ExecutorContext::new_for_unit_test(UnitLength::Mm).await?;
|
||||||
// In hyper, a `MakeService` is basically your server.
|
// In hyper, a `MakeService` is basically your server.
|
||||||
@ -66,13 +64,12 @@ pub async fn start(listen_on: SocketAddr) -> anyhow::Result<()> {
|
|||||||
/// KCL errors (from engine or the executor) respond with HTTP Bad Gateway.
|
/// KCL errors (from engine or the executor) respond with HTTP Bad Gateway.
|
||||||
/// Malformed requests are HTTP Bad Request.
|
/// Malformed requests are HTTP Bad Request.
|
||||||
/// Successful requests contain a PNG as the body.
|
/// Successful requests contain a PNG as the body.
|
||||||
async fn snapshot_endpoint(body: Vec<u8>, state3: ExecutorContext) -> Response<Body> {
|
async fn snapshot_endpoint(body: Vec<u8>, state: ExecutorContext) -> Response<Body> {
|
||||||
let body = match serde_json::from_slice::<RequestBody>(&body) {
|
let body = match serde_json::from_slice::<RequestBody>(&body) {
|
||||||
Ok(bd) => bd,
|
Ok(bd) => bd,
|
||||||
Err(e) => return bad_request(format!("Invalid request JSON: {e}")),
|
Err(e) => return bad_request(format!("Invalid request JSON: {e}")),
|
||||||
};
|
};
|
||||||
let RequestBody { kcl_program, test_name } = body;
|
let RequestBody { kcl_program, test_name } = body;
|
||||||
eprintln!("Executing {test_name}");
|
|
||||||
let parser = match kcl_lib::token::lexer(&kcl_program) {
|
let parser = match kcl_lib::token::lexer(&kcl_program) {
|
||||||
Ok(ts) => kcl_lib::parser::Parser::new(ts),
|
Ok(ts) => kcl_lib::parser::Parser::new(ts),
|
||||||
Err(e) => return bad_request(format!("tokenization error: {e}")),
|
Err(e) => return bad_request(format!("tokenization error: {e}")),
|
||||||
@ -81,13 +78,19 @@ async fn snapshot_endpoint(body: Vec<u8>, state3: ExecutorContext) -> Response<B
|
|||||||
Ok(pr) => pr,
|
Ok(pr) => pr,
|
||||||
Err(e) => return bad_request(format!("Parse error: {e}")),
|
Err(e) => return bad_request(format!("Parse error: {e}")),
|
||||||
};
|
};
|
||||||
if let Err(e) = state3.reset_scene().await {
|
eprintln!("Executing {test_name}");
|
||||||
|
if let Err(e) = state.reset_scene().await {
|
||||||
return kcl_err(e);
|
return kcl_err(e);
|
||||||
}
|
}
|
||||||
let snapshot = match state3.execute_and_prepare_snapshot(program).await {
|
// Let users know if the test is taking a long time.
|
||||||
|
let (done_tx, done_rx) = oneshot::channel::<()>();
|
||||||
|
let timer = time_until(done_rx);
|
||||||
|
let snapshot = match state.execute_and_prepare_snapshot(program).await {
|
||||||
Ok(sn) => sn,
|
Ok(sn) => sn,
|
||||||
Err(e) => return kcl_err(e),
|
Err(e) => return kcl_err(e),
|
||||||
};
|
};
|
||||||
|
let _ = done_tx.send(());
|
||||||
|
timer.abort();
|
||||||
eprintln!("\tServing response");
|
eprintln!("\tServing response");
|
||||||
let png_bytes = snapshot.contents.0;
|
let png_bytes = snapshot.contents.0;
|
||||||
let mut resp = Response::new(Body::from(png_bytes));
|
let mut resp = Response::new(Body::from(png_bytes));
|
||||||
@ -113,3 +116,20 @@ fn kcl_err(err: anyhow::Error) -> Response<Body> {
|
|||||||
eprintln!("\tBad KCL");
|
eprintln!("\tBad KCL");
|
||||||
bad_gateway(format!("{err}"))
|
bad_gateway(format!("{err}"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn time_until(done: oneshot::Receiver<()>) -> JoinHandle<()> {
|
||||||
|
tokio::task::spawn(async move {
|
||||||
|
let period = 10;
|
||||||
|
tokio::pin!(done);
|
||||||
|
for i in 1..=3 {
|
||||||
|
tokio::select! {
|
||||||
|
biased;
|
||||||
|
// If the test is done, no need for this timer anymore.
|
||||||
|
_ = &mut done => return,
|
||||||
|
_ = sleep(Duration::from_secs(period)) => {
|
||||||
|
eprintln!("\tTest has taken {}s", period * i);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@ -16,6 +16,7 @@ pub mod lsp;
|
|||||||
pub mod parser;
|
pub mod parser;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
pub mod std;
|
pub mod std;
|
||||||
|
pub mod test_server;
|
||||||
pub mod thread;
|
pub mod thread;
|
||||||
pub mod token;
|
pub mod token;
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
|||||||
8
src/wasm-lib/kcl/src/test_server.rs
Normal file
8
src/wasm-lib/kcl/src/test_server.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
//! Types used to send data to the test server.
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize, serde::Serialize)]
|
||||||
|
pub struct RequestBody {
|
||||||
|
pub kcl_program: String,
|
||||||
|
#[serde(default)]
|
||||||
|
pub test_name: String,
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user