Compare commits
3 Commits
nrc-refact
...
batch-take
Author | SHA1 | Date | |
---|---|---|---|
426de2d78d | |||
3011c0d2f8 | |||
5b75452f9e |
1159
src/wasm-lib/Cargo.lock
generated
1159
src/wasm-lib/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -59,7 +59,7 @@ members = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
kittycad = { version = "0.2.60", default-features = false, features = ["js", "requests"] }
|
kittycad = { path = "../../../kittycad.rs/kittycad", default-features = false, features = ["js", "requests"] }
|
||||||
kittycad-execution-plan = { git = "https://github.com/KittyCAD/modeling-api", branch = "main" }
|
kittycad-execution-plan = { git = "https://github.com/KittyCAD/modeling-api", branch = "main" }
|
||||||
kittycad-execution-plan-macros = { git = "https://github.com/KittyCAD/modeling-api", branch = "main" }
|
kittycad-execution-plan-macros = { git = "https://github.com/KittyCAD/modeling-api", branch = "main" }
|
||||||
kittycad-execution-plan-traits = { git = "https://github.com/KittyCAD/modeling-api", branch = "main" }
|
kittycad-execution-plan-traits = { git = "https://github.com/KittyCAD/modeling-api", branch = "main" }
|
||||||
|
@ -14,6 +14,7 @@ keywords = ["kcl", "KittyCAD", "CAD"]
|
|||||||
anyhow = { version = "1.0.81", features = ["backtrace"] }
|
anyhow = { version = "1.0.81", features = ["backtrace"] }
|
||||||
async-recursion = "1.0.5"
|
async-recursion = "1.0.5"
|
||||||
async-trait = "0.1.77"
|
async-trait = "0.1.77"
|
||||||
|
boxcar = "0.2.4"
|
||||||
chrono = "0.4.35"
|
chrono = "0.4.35"
|
||||||
clap = { version = "4.5.2", features = ["cargo", "derive", "env", "unicode"], optional = true }
|
clap = { version = "4.5.2", features = ["cargo", "derive", "env", "unicode"], optional = true }
|
||||||
dashmap = "5.5.3"
|
dashmap = "5.5.3"
|
||||||
|
@ -75,6 +75,7 @@ pub async fn modify_ast_for_sketch(
|
|||||||
// Let's get the path info.
|
// Let's get the path info.
|
||||||
let resp = engine
|
let resp = engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
|
false,
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
SourceRange::default(),
|
SourceRange::default(),
|
||||||
ModelingCmd::PathGetInfo { path_id: sketch_id },
|
ModelingCmd::PathGetInfo { path_id: sketch_id },
|
||||||
@ -99,6 +100,7 @@ pub async fn modify_ast_for_sketch(
|
|||||||
for segment in &path_info.segments {
|
for segment in &path_info.segments {
|
||||||
if let Some(command_id) = &segment.command_id {
|
if let Some(command_id) = &segment.command_id {
|
||||||
let h = engine.send_modeling_cmd(
|
let h = engine.send_modeling_cmd(
|
||||||
|
false,
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
SourceRange::default(),
|
SourceRange::default(),
|
||||||
ModelingCmd::CurveGetControlPoints { curve_id: *command_id },
|
ModelingCmd::CurveGetControlPoints { curve_id: *command_id },
|
||||||
|
@ -29,6 +29,7 @@ pub struct EngineConnection {
|
|||||||
responses: Arc<DashMap<uuid::Uuid, WebSocketResponse>>,
|
responses: Arc<DashMap<uuid::Uuid, WebSocketResponse>>,
|
||||||
tcp_read_handle: Arc<TcpReadHandle>,
|
tcp_read_handle: Arc<TcpReadHandle>,
|
||||||
socket_health: Arc<Mutex<SocketHealth>>,
|
socket_health: Arc<Mutex<SocketHealth>>,
|
||||||
|
batch: Arc<Mutex<Vec<WebSocketRequest>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TcpRead {
|
pub struct TcpRead {
|
||||||
@ -154,27 +155,136 @@ impl EngineConnection {
|
|||||||
}),
|
}),
|
||||||
responses,
|
responses,
|
||||||
socket_health,
|
socket_health,
|
||||||
|
batch: Arc::new(Mutex::new(Vec::new())),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn is_cmd_with_return_values(cmd: &kittycad::types::ModelingCmd) -> bool {
|
||||||
|
let (kittycad::types::ModelingCmd::Export { .. }
|
||||||
|
| kittycad::types::ModelingCmd::Extrude { .. }
|
||||||
|
| kittycad::types::ModelingCmd::SketchModeDisable { .. }
|
||||||
|
| kittycad::types::ModelingCmd::ObjectBringToFront { .. }
|
||||||
|
| kittycad::types::ModelingCmd::SelectWithPoint { .. }
|
||||||
|
| kittycad::types::ModelingCmd::HighlightSetEntity { .. }
|
||||||
|
| kittycad::types::ModelingCmd::EntityGetChildUuid { .. }
|
||||||
|
| kittycad::types::ModelingCmd::EntityGetNumChildren { .. }
|
||||||
|
| kittycad::types::ModelingCmd::EntityGetParentId { .. }
|
||||||
|
| kittycad::types::ModelingCmd::EntityGetAllChildUuids { .. }
|
||||||
|
| kittycad::types::ModelingCmd::CameraDragMove { .. }
|
||||||
|
| kittycad::types::ModelingCmd::CameraDragEnd { .. }
|
||||||
|
| kittycad::types::ModelingCmd::DefaultCameraGetSettings { .. }
|
||||||
|
| kittycad::types::ModelingCmd::DefaultCameraZoom { .. }
|
||||||
|
| kittycad::types::ModelingCmd::SelectGet { .. }
|
||||||
|
| kittycad::types::ModelingCmd::Solid3DGetAllEdgeFaces { .. }
|
||||||
|
| kittycad::types::ModelingCmd::Solid3DGetAllOppositeEdges { .. }
|
||||||
|
| kittycad::types::ModelingCmd::Solid3DGetOppositeEdge { .. }
|
||||||
|
| kittycad::types::ModelingCmd::Solid3DGetNextAdjacentEdge { .. }
|
||||||
|
| kittycad::types::ModelingCmd::Solid3DGetPrevAdjacentEdge { .. }
|
||||||
|
| kittycad::types::ModelingCmd::GetEntityType { .. }
|
||||||
|
| kittycad::types::ModelingCmd::CurveGetControlPoints { .. }
|
||||||
|
| kittycad::types::ModelingCmd::CurveGetType { .. }
|
||||||
|
| kittycad::types::ModelingCmd::MouseClick { .. }
|
||||||
|
| kittycad::types::ModelingCmd::TakeSnapshot { .. }
|
||||||
|
| kittycad::types::ModelingCmd::PathGetInfo { .. }
|
||||||
|
| kittycad::types::ModelingCmd::PathGetCurveUuidsForVertices { .. }
|
||||||
|
| kittycad::types::ModelingCmd::PathGetVertexUuids { .. }
|
||||||
|
| kittycad::types::ModelingCmd::CurveGetEndPoints { .. }
|
||||||
|
| kittycad::types::ModelingCmd::FaceIsPlanar { .. }
|
||||||
|
| kittycad::types::ModelingCmd::FaceGetPosition { .. }
|
||||||
|
| kittycad::types::ModelingCmd::FaceGetGradient { .. }
|
||||||
|
| kittycad::types::ModelingCmd::PlaneIntersectAndProject { .. }
|
||||||
|
| kittycad::types::ModelingCmd::ImportFiles { .. }
|
||||||
|
| kittycad::types::ModelingCmd::Mass { .. }
|
||||||
|
| kittycad::types::ModelingCmd::Volume { .. }
|
||||||
|
| kittycad::types::ModelingCmd::Density { .. }
|
||||||
|
| kittycad::types::ModelingCmd::SurfaceArea { .. }
|
||||||
|
| kittycad::types::ModelingCmd::CenterOfMass { .. }
|
||||||
|
| kittycad::types::ModelingCmd::GetSketchModePlane { .. }
|
||||||
|
| kittycad::types::ModelingCmd::EntityGetDistance { .. }
|
||||||
|
| kittycad::types::ModelingCmd::EntityLinearPattern { .. }
|
||||||
|
| kittycad::types::ModelingCmd::EntityCircularPattern { .. }
|
||||||
|
| kittycad::types::ModelingCmd::Solid3DGetExtrusionFaceInfo { .. }) = cmd
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl EngineManager for EngineConnection {
|
impl EngineManager for EngineConnection {
|
||||||
async fn send_modeling_cmd(
|
async fn send_modeling_cmd(
|
||||||
&self,
|
&self,
|
||||||
|
flush_batch: bool,
|
||||||
id: uuid::Uuid,
|
id: uuid::Uuid,
|
||||||
source_range: crate::executor::SourceRange,
|
source_range: crate::executor::SourceRange,
|
||||||
cmd: kittycad::types::ModelingCmd,
|
cmd: kittycad::types::ModelingCmd,
|
||||||
) -> Result<OkWebSocketResponseData, KclError> {
|
) -> Result<OkWebSocketResponseData, KclError> {
|
||||||
|
let req = WebSocketRequest::ModelingCmdReq {
|
||||||
|
cmd: cmd.clone(),
|
||||||
|
cmd_id: id,
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("req {:?}", req);
|
||||||
|
|
||||||
|
if !flush_batch {
|
||||||
|
self.batch.lock().unwrap().push(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the batch only has this one command that expects a return value,
|
||||||
|
// fire it right away, or if we want to flush batch queue.
|
||||||
|
let is_sending = (is_cmd_with_return_values(&cmd) && self.batch.lock().unwrap().len() == 1)
|
||||||
|
|| flush_batch
|
||||||
|
|| is_cmd_with_return_values(&cmd);
|
||||||
|
|
||||||
|
// Return a fake modeling_request empty response.
|
||||||
|
if !is_sending {
|
||||||
|
println!("fake {:?}", cmd);
|
||||||
|
return Ok(OkWebSocketResponseData::Modeling {
|
||||||
|
modeling_response: kittycad::types::OkModelingCmdResponse::Empty {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let batched_requests =
|
||||||
|
WebSocketRequest::ModelingCmdBatchReq {
|
||||||
|
requests: self.batch.lock().unwrap().iter().fold(vec![], |mut acc, val| {
|
||||||
|
let WebSocketRequest::ModelingCmdReq { cmd, cmd_id } = val else { return acc; };
|
||||||
|
acc.push(kittycad::types::ModelingCmdReq {
|
||||||
|
cmd: cmd.clone(),
|
||||||
|
cmd_id: *cmd_id,
|
||||||
|
});
|
||||||
|
acc
|
||||||
|
}),
|
||||||
|
batch_id: uuid::Uuid::new_v4()
|
||||||
|
};
|
||||||
|
|
||||||
|
let final_req = if self.batch.lock().unwrap().len() == 1 {
|
||||||
|
self.batch.lock().unwrap().get(0).unwrap().clone()
|
||||||
|
} else {
|
||||||
|
batched_requests
|
||||||
|
};
|
||||||
|
|
||||||
|
// Throw away the old batch queue.
|
||||||
|
self.batch.lock().unwrap().clear();
|
||||||
|
|
||||||
|
println!("final req {:?}", final_req);
|
||||||
|
|
||||||
|
// We pop off the responses to cleanup our mappings.
|
||||||
|
let id_final = match final_req {
|
||||||
|
WebSocketRequest::ModelingCmdBatchReq { requests: _, batch_id } => batch_id,
|
||||||
|
WebSocketRequest::ModelingCmdReq { cmd: _, cmd_id } => cmd_id,
|
||||||
|
_ => panic!("should not be possible"),
|
||||||
|
};
|
||||||
|
|
||||||
let (tx, rx) = oneshot::channel();
|
let (tx, rx) = oneshot::channel();
|
||||||
|
|
||||||
// Send the request to the engine, via the actor.
|
// Send the request to the engine, via the actor.
|
||||||
self.engine_req_tx
|
self.engine_req_tx
|
||||||
.send(ToEngineReq {
|
.send(ToEngineReq {
|
||||||
req: WebSocketRequest::ModelingCmdReq {
|
req: final_req.clone(),
|
||||||
cmd: cmd.clone(),
|
|
||||||
cmd_id: id,
|
|
||||||
},
|
|
||||||
request_sent: tx,
|
request_sent: tx,
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
@ -200,6 +310,7 @@ impl EngineManager for EngineConnection {
|
|||||||
})
|
})
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
|
||||||
// Wait for the response.
|
// Wait for the response.
|
||||||
let current_time = std::time::Instant::now();
|
let current_time = std::time::Instant::now();
|
||||||
while current_time.elapsed().as_secs() < 60 {
|
while current_time.elapsed().as_secs() < 60 {
|
||||||
@ -211,8 +322,9 @@ impl EngineManager for EngineConnection {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// We pop off the responses to cleanup our mappings.
|
|
||||||
if let Some((_, resp)) = self.responses.remove(&id) {
|
if let Some((_, resp)) = self.responses.remove(&id_final) {
|
||||||
|
println!("RESP {:?}", resp);
|
||||||
return if let Some(data) = &resp.resp {
|
return if let Some(data) = &resp.resp {
|
||||||
Ok(data.clone())
|
Ok(data.clone())
|
||||||
} else {
|
} else {
|
||||||
@ -225,7 +337,7 @@ impl EngineManager for EngineConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Err(KclError::Engine(KclErrorDetails {
|
Err(KclError::Engine(KclErrorDetails {
|
||||||
message: format!("Modeling command timed out `{}`", id),
|
message: format!("Modeling command timed out `{}`", id_final),
|
||||||
source_ranges: vec![source_range],
|
source_ranges: vec![source_range],
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ impl EngineConnection {
|
|||||||
impl crate::engine::EngineManager for EngineConnection {
|
impl crate::engine::EngineManager for EngineConnection {
|
||||||
async fn send_modeling_cmd(
|
async fn send_modeling_cmd(
|
||||||
&self,
|
&self,
|
||||||
|
_flush_batch: bool,
|
||||||
_id: uuid::Uuid,
|
_id: uuid::Uuid,
|
||||||
_source_range: crate::executor::SourceRange,
|
_source_range: crate::executor::SourceRange,
|
||||||
_cmd: kittycad::types::ModelingCmd,
|
_cmd: kittycad::types::ModelingCmd,
|
||||||
|
@ -13,6 +13,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
|||||||
/// Send a modeling command and wait for the response message.
|
/// Send a modeling command and wait for the response message.
|
||||||
async fn send_modeling_cmd(
|
async fn send_modeling_cmd(
|
||||||
&self,
|
&self,
|
||||||
|
flush_batch: bool,
|
||||||
id: uuid::Uuid,
|
id: uuid::Uuid,
|
||||||
source_range: crate::executor::SourceRange,
|
source_range: crate::executor::SourceRange,
|
||||||
cmd: kittycad::types::ModelingCmd,
|
cmd: kittycad::types::ModelingCmd,
|
||||||
|
@ -1008,6 +1008,7 @@ pub async fn execute(
|
|||||||
// Before we even start executing the program, set the units.
|
// Before we even start executing the program, set the units.
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
|
false,
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
SourceRange::default(),
|
SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::SetSceneUnits {
|
kittycad::types::ModelingCmd::SetSceneUnits {
|
||||||
@ -1219,6 +1220,17 @@ pub async fn execute(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fire the batch since we've reached the end.
|
||||||
|
// ctx.engine
|
||||||
|
// .send_modeling_cmd(
|
||||||
|
// true,
|
||||||
|
// uuid::Uuid::new_v4(),
|
||||||
|
// SourceRange::default(),
|
||||||
|
// // This is ignored when flush_batch is true.
|
||||||
|
// kittycad::types::ModelingCmd::EditModeExit {},
|
||||||
|
// )
|
||||||
|
// .await?;
|
||||||
|
|
||||||
Ok(memory.clone())
|
Ok(memory.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,7 +206,7 @@ impl Args {
|
|||||||
id: uuid::Uuid,
|
id: uuid::Uuid,
|
||||||
cmd: kittycad::types::ModelingCmd,
|
cmd: kittycad::types::ModelingCmd,
|
||||||
) -> Result<OkWebSocketResponseData, KclError> {
|
) -> Result<OkWebSocketResponseData, KclError> {
|
||||||
self.ctx.engine.send_modeling_cmd(id, self.source_range, cmd).await
|
self.ctx.engine.send_modeling_cmd(false, id, self.source_range, cmd).await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_user_val_from_json(&self, j: serde_json::Value) -> Result<MemoryItem, KclError> {
|
fn make_user_val_from_json(&self, j: serde_json::Value) -> Result<MemoryItem, KclError> {
|
||||||
|
@ -21,9 +21,9 @@ async fn execute_and_snapshot(code: &str, units: kittycad::types::UnitLength) ->
|
|||||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||||
|
|
||||||
// Create the client.
|
// Create the client.
|
||||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
let mut client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||||
// uncomment to use a local server
|
// uncomment to use a local server
|
||||||
//client.set_base_url("http://system76-pc:8080/");
|
client.set_base_url("http://localhost:8080/");
|
||||||
|
|
||||||
let ws = client
|
let ws = client
|
||||||
.modeling()
|
.modeling()
|
||||||
@ -45,6 +45,7 @@ async fn execute_and_snapshot(code: &str, units: kittycad::types::UnitLength) ->
|
|||||||
|
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
|
false,
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
kcl_lib::executor::SourceRange::default(),
|
kcl_lib::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
kittycad::types::ModelingCmd::DefaultCameraLookAt {
|
||||||
@ -60,6 +61,7 @@ async fn execute_and_snapshot(code: &str, units: kittycad::types::UnitLength) ->
|
|||||||
let resp = ctx
|
let resp = ctx
|
||||||
.engine
|
.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
|
false,
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
kcl_lib::executor::SourceRange::default(),
|
kcl_lib::executor::SourceRange::default(),
|
||||||
kittycad::types::ModelingCmd::TakeSnapshot {
|
kittycad::types::ModelingCmd::TakeSnapshot {
|
||||||
|
@ -49,6 +49,7 @@ async fn setup(code: &str, name: &str) -> Result<(ExecutorContext, Program, uuid
|
|||||||
let plane_id = uuid::Uuid::new_v4();
|
let plane_id = uuid::Uuid::new_v4();
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
|
false,
|
||||||
plane_id,
|
plane_id,
|
||||||
SourceRange::default(),
|
SourceRange::default(),
|
||||||
ModelingCmd::MakePlane {
|
ModelingCmd::MakePlane {
|
||||||
@ -67,6 +68,7 @@ async fn setup(code: &str, name: &str) -> Result<(ExecutorContext, Program, uuid
|
|||||||
// You can however get path info without sketch mode.
|
// You can however get path info without sketch mode.
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
|
false,
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
SourceRange::default(),
|
SourceRange::default(),
|
||||||
ModelingCmd::SketchModeEnable {
|
ModelingCmd::SketchModeEnable {
|
||||||
@ -82,6 +84,7 @@ async fn setup(code: &str, name: &str) -> Result<(ExecutorContext, Program, uuid
|
|||||||
// We can't get control points of an existing sketch without being in edit mode.
|
// We can't get control points of an existing sketch without being in edit mode.
|
||||||
ctx.engine
|
ctx.engine
|
||||||
.send_modeling_cmd(
|
.send_modeling_cmd(
|
||||||
|
false,
|
||||||
uuid::Uuid::new_v4(),
|
uuid::Uuid::new_v4(),
|
||||||
SourceRange::default(),
|
SourceRange::default(),
|
||||||
ModelingCmd::EditModeEnter { target: sketch_id },
|
ModelingCmd::EditModeEnter { target: sketch_id },
|
||||||
|
Reference in New Issue
Block a user