Parallelize the artifact graph only time suck (#6482)

* parallelize the artifact only time suck

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

make wasm safe

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* artifact graph things

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
Jess Frazelle
2025-04-26 21:21:26 -07:00
committed by GitHub
parent d0b0365f75
commit 24465cf463
253 changed files with 73547 additions and 55353 deletions

View File

@ -1,5 +1,6 @@
//! Functions for managing engine communications.
pub mod async_tasks;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(feature = "engine")]
pub mod conn;
@ -16,10 +17,12 @@ use std::{
},
};
pub use async_tasks::AsyncTasks;
use indexmap::IndexMap;
#[cfg(feature = "artifact-graph")]
use kcmc::id::ModelingCmdId;
use kcmc::{
each_cmd as mcmd,
id::ModelingCmdId,
length_unit::LengthUnit,
ok_response::OkModelingCmdResponse,
shared::Color,
@ -35,9 +38,11 @@ use serde::{Deserialize, Serialize};
use tokio::sync::RwLock;
use uuid::Uuid;
#[cfg(feature = "artifact-graph")]
use crate::execution::ArtifactCommand;
use crate::{
errors::{KclError, KclErrorDetails},
execution::{types::UnitLen, ArtifactCommand, DefaultPlanes, IdGenerator, Point3d},
execution::{types::UnitLen, DefaultPlanes, IdGenerator, Point3d},
SourceRange,
};
@ -74,11 +79,15 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
fn responses(&self) -> Arc<RwLock<IndexMap<Uuid, WebSocketResponse>>>;
/// Get the artifact commands that have accumulated so far.
#[cfg(feature = "artifact-graph")]
fn artifact_commands(&self) -> Arc<RwLock<Vec<ArtifactCommand>>>;
/// Get the ids of the async commands we are waiting for.
fn ids_of_async_commands(&self) -> Arc<RwLock<IndexMap<Uuid, SourceRange>>>;
/// Get the async tasks we are waiting for.
fn async_tasks(&self) -> AsyncTasks;
/// Take the batch of commands that have accumulated so far and clear them.
async fn take_batch(&self) -> Vec<(WebSocketRequest, SourceRange)> {
std::mem::take(&mut *self.batch().write().await)
@ -90,11 +99,13 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
}
/// Clear all artifact commands that have accumulated so far.
#[cfg(feature = "artifact-graph")]
async fn clear_artifact_commands(&self) {
self.artifact_commands().write().await.clear();
}
/// Take the artifact commands that have accumulated so far and clear them.
#[cfg(feature = "artifact-graph")]
async fn take_artifact_commands(&self) -> Vec<ArtifactCommand> {
std::mem::take(&mut *self.artifact_commands().write().await)
}
@ -145,6 +156,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
self.batch().write().await.clear();
self.batch_end().write().await.clear();
self.ids_of_async_commands().write().await.clear();
self.async_tasks().clear().await;
}
/// Send a modeling command and do not wait for the response message.
@ -186,6 +198,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
// Ensure artifact commands are cleared so that we don't accumulate them
// across runs.
#[cfg(feature = "artifact-graph")]
self.clear_artifact_commands().await;
// Do the after clear scene hook.
@ -253,6 +266,18 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
self.ensure_async_command_completed(id, Some(source_range)).await?;
}
// Make sure we check for all async tasks as well.
// The reason why we ignore the error here is that, if a model fillets an edge
// we previously called something on, it might no longer exist. In which case,
// the artifact graph won't care either if its gone since you can't select it
// anymore anyways.
if let Err(err) = self.async_tasks().join_all().await {
crate::log::logln!("Error waiting for async tasks (this is typically fine and just means that an edge became something else): {:?}", err);
}
// Flush the batch to make sure nothing remains.
self.flush_batch(true, SourceRange::default()).await?;
Ok(())
}
@ -273,6 +298,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
Ok(())
}
#[cfg(feature = "artifact-graph")]
async fn handle_artifact_command(
&self,
cmd: &ModelingCmd,
@ -413,6 +439,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
self.ids_of_async_commands().write().await.insert(id, source_range);
// Add to artifact commands.
#[cfg(feature = "artifact-graph")]
self.handle_artifact_command(cmd, id.into(), &HashMap::from([(id, source_range)]))
.await?;
@ -486,6 +513,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
}
// Do the artifact commands.
#[cfg(feature = "artifact-graph")]
for (req, _) in orig_requests.iter() {
match &req {
WebSocketRequest::ModelingCmdBatchReq(ModelingBatch { requests, .. }) => {