Compare commits
	
		
			3 Commits
		
	
	
		
			v0.60.0
			...
			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] | ||||
| 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-macros = { 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"] } | ||||
| async-recursion = "1.0.5" | ||||
| async-trait = "0.1.77" | ||||
| boxcar = "0.2.4" | ||||
| chrono = "0.4.35" | ||||
| clap = { version = "4.5.2", features = ["cargo", "derive", "env", "unicode"], optional = true } | ||||
| dashmap = "5.5.3" | ||||
|  | ||||
| @ -75,6 +75,7 @@ pub async fn modify_ast_for_sketch( | ||||
|     // Let's get the path info. | ||||
|     let resp = engine | ||||
|         .send_modeling_cmd( | ||||
|             false, | ||||
|             uuid::Uuid::new_v4(), | ||||
|             SourceRange::default(), | ||||
|             ModelingCmd::PathGetInfo { path_id: sketch_id }, | ||||
| @ -99,6 +100,7 @@ pub async fn modify_ast_for_sketch( | ||||
|     for segment in &path_info.segments { | ||||
|         if let Some(command_id) = &segment.command_id { | ||||
|             let h = engine.send_modeling_cmd( | ||||
|                 false, | ||||
|                 uuid::Uuid::new_v4(), | ||||
|                 SourceRange::default(), | ||||
|                 ModelingCmd::CurveGetControlPoints { curve_id: *command_id }, | ||||
|  | ||||
| @ -29,6 +29,7 @@ pub struct EngineConnection { | ||||
|     responses: Arc<DashMap<uuid::Uuid, WebSocketResponse>>, | ||||
|     tcp_read_handle: Arc<TcpReadHandle>, | ||||
|     socket_health: Arc<Mutex<SocketHealth>>, | ||||
|     batch: Arc<Mutex<Vec<WebSocketRequest>>>, | ||||
| } | ||||
|  | ||||
| pub struct TcpRead { | ||||
| @ -154,27 +155,136 @@ impl EngineConnection { | ||||
|             }), | ||||
|             responses, | ||||
|             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] | ||||
| impl EngineManager for EngineConnection { | ||||
|     async fn send_modeling_cmd( | ||||
|         &self, | ||||
|         flush_batch: bool, | ||||
|         id: uuid::Uuid, | ||||
|         source_range: crate::executor::SourceRange, | ||||
|         cmd: kittycad::types::ModelingCmd, | ||||
|     ) -> 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(); | ||||
|  | ||||
|         // Send the request to the engine, via the actor. | ||||
|         self.engine_req_tx | ||||
|             .send(ToEngineReq { | ||||
|                 req: WebSocketRequest::ModelingCmdReq { | ||||
|                     cmd: cmd.clone(), | ||||
|                     cmd_id: id, | ||||
|                 }, | ||||
|                 req: final_req.clone(), | ||||
|                 request_sent: tx, | ||||
|             }) | ||||
|             .await | ||||
| @ -200,6 +310,7 @@ impl EngineManager for EngineConnection { | ||||
|                 }) | ||||
|             })?; | ||||
|  | ||||
|  | ||||
|         // Wait for the response. | ||||
|         let current_time = std::time::Instant::now(); | ||||
|         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 { | ||||
|                     Ok(data.clone()) | ||||
|                 } else { | ||||
| @ -225,7 +337,7 @@ impl EngineManager for EngineConnection { | ||||
|         } | ||||
|  | ||||
|         Err(KclError::Engine(KclErrorDetails { | ||||
|             message: format!("Modeling command timed out `{}`", id), | ||||
|             message: format!("Modeling command timed out `{}`", id_final), | ||||
|             source_ranges: vec![source_range], | ||||
|         })) | ||||
|     } | ||||
|  | ||||
| @ -19,6 +19,7 @@ impl EngineConnection { | ||||
| impl crate::engine::EngineManager for EngineConnection { | ||||
|     async fn send_modeling_cmd( | ||||
|         &self, | ||||
|         _flush_batch: bool, | ||||
|         _id: uuid::Uuid, | ||||
|         _source_range: crate::executor::SourceRange, | ||||
|         _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. | ||||
|     async fn send_modeling_cmd( | ||||
|         &self, | ||||
|         flush_batch: bool, | ||||
|         id: uuid::Uuid, | ||||
|         source_range: crate::executor::SourceRange, | ||||
|         cmd: kittycad::types::ModelingCmd, | ||||
|  | ||||
| @ -1008,6 +1008,7 @@ pub async fn execute( | ||||
|     // Before we even start executing the program, set the units. | ||||
|     ctx.engine | ||||
|         .send_modeling_cmd( | ||||
|             false, | ||||
|             uuid::Uuid::new_v4(), | ||||
|             SourceRange::default(), | ||||
|             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()) | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -206,7 +206,7 @@ impl Args { | ||||
|         id: uuid::Uuid, | ||||
|         cmd: kittycad::types::ModelingCmd, | ||||
|     ) -> 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> { | ||||
|  | ||||
| @ -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"); | ||||
|  | ||||
|     // 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 | ||||
|     //client.set_base_url("http://system76-pc:8080/"); | ||||
|     client.set_base_url("http://localhost:8080/"); | ||||
|  | ||||
|     let ws = client | ||||
|         .modeling() | ||||
| @ -45,6 +45,7 @@ async fn execute_and_snapshot(code: &str, units: kittycad::types::UnitLength) -> | ||||
|  | ||||
|     ctx.engine | ||||
|         .send_modeling_cmd( | ||||
|             false, | ||||
|             uuid::Uuid::new_v4(), | ||||
|             kcl_lib::executor::SourceRange::default(), | ||||
|             kittycad::types::ModelingCmd::DefaultCameraLookAt { | ||||
| @ -60,6 +61,7 @@ async fn execute_and_snapshot(code: &str, units: kittycad::types::UnitLength) -> | ||||
|     let resp = ctx | ||||
|         .engine | ||||
|         .send_modeling_cmd( | ||||
|             false, | ||||
|             uuid::Uuid::new_v4(), | ||||
|             kcl_lib::executor::SourceRange::default(), | ||||
|             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(); | ||||
|     ctx.engine | ||||
|         .send_modeling_cmd( | ||||
|             false, | ||||
|             plane_id, | ||||
|             SourceRange::default(), | ||||
|             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. | ||||
|     ctx.engine | ||||
|         .send_modeling_cmd( | ||||
|             false, | ||||
|             uuid::Uuid::new_v4(), | ||||
|             SourceRange::default(), | ||||
|             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. | ||||
|     ctx.engine | ||||
|         .send_modeling_cmd( | ||||
|             false, | ||||
|             uuid::Uuid::new_v4(), | ||||
|             SourceRange::default(), | ||||
|             ModelingCmd::EditModeEnter { target: sketch_id }, | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	