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

@ -0,0 +1,9 @@
#[cfg(not(target_arch = "wasm32"))]
pub mod tasks;
#[cfg(target_arch = "wasm32")]
pub mod tasks_wasm;
#[cfg(not(target_arch = "wasm32"))]
pub use tasks::AsyncTasks;
#[cfg(target_arch = "wasm32")]
pub use tasks_wasm::AsyncTasks;

View File

@ -0,0 +1,51 @@
//! This module contains the `AsyncTasks` struct, which is used to manage a set of asynchronous
//! tasks.
use std::sync::Arc;
use tokio::sync::RwLock;
use crate::errors::KclError;
#[derive(Debug, Clone)]
pub struct AsyncTasks {
pub tasks: Arc<RwLock<tokio::task::JoinSet<anyhow::Result<(), KclError>>>>,
}
impl AsyncTasks {
pub fn new() -> Self {
Self {
tasks: Arc::new(RwLock::new(tokio::task::JoinSet::new())),
}
}
pub async fn spawn<F>(&mut self, task: F)
where
F: std::future::Future<Output = anyhow::Result<(), KclError>>,
F: Send + 'static,
{
self.tasks.write().await.spawn(task);
}
// Wait for all tasks to finish.
// Return an error if any of them failed.
pub async fn join_all(&mut self) -> anyhow::Result<(), KclError> {
let tasks = std::mem::take(&mut *self.tasks.write().await);
let results = tasks.join_all().await;
for result in results {
result?;
}
Ok(())
}
pub async fn clear(&mut self) {
*self.tasks.write().await = tokio::task::JoinSet::new();
}
}
impl Default for AsyncTasks {
fn default() -> Self {
Self::new()
}
}

View File

@ -0,0 +1,89 @@
//! This module contains the `AsyncTasks` struct, which is used to manage a set of asynchronous
//! tasks.
use std::{ops::AddAssign, sync::Arc};
use tokio::sync::RwLock;
use crate::errors::KclError;
#[derive(Debug, Clone)]
pub struct AsyncTasks {
pub sender: Arc<RwLock<tokio::sync::mpsc::Sender<Result<(), KclError>>>>,
pub receiver: Arc<RwLock<tokio::sync::mpsc::Receiver<Result<(), KclError>>>>,
pub sent: Arc<RwLock<usize>>,
}
impl AsyncTasks {
pub fn new() -> Self {
let (results_tx, results_rx) = tokio::sync::mpsc::channel(1);
Self {
sender: Arc::new(RwLock::new(results_tx)),
receiver: Arc::new(RwLock::new(results_rx)),
sent: Arc::new(RwLock::new(0)),
}
}
pub async fn spawn<F>(&mut self, task: F)
where
F: std::future::Future<Output = anyhow::Result<(), KclError>>,
F: Send + 'static,
{
// Add one to the sent counter.
self.sent.write().await.add_assign(1);
// Spawn the task and send the result to the channel.
let sender_clone = self.sender.clone();
wasm_bindgen_futures::spawn_local(async move {
let result = task.await;
let sender = sender_clone.read().await;
if let Err(_) = sender.send(result).await {
web_sys::console::error_1(&"Failed to send result".into());
}
});
}
// Wait for all tasks to finish.
// Return an error if any of them failed.
pub async fn join_all(&mut self) -> anyhow::Result<(), KclError> {
if *self.sent.read().await == 0 {
return Ok(());
}
let mut results = Vec::new();
let mut receiver = self.receiver.write().await;
// Wait for all tasks to finish.
while let Some(result) = receiver.recv().await {
results.push(result);
// Check if all tasks have finished.
if results.len() == *self.sent.read().await {
break;
}
}
// Check if any of the tasks failed.
for result in results {
result?;
}
Ok(())
}
pub async fn clear(&mut self) {
// Clear the sent counter.
*self.sent.write().await = 0;
// Clear the channel.
let (results_tx, results_rx) = tokio::sync::mpsc::channel(1);
*self.sender.write().await = results_tx;
*self.receiver.write().await = results_rx;
}
}
impl Default for AsyncTasks {
fn default() -> Self {
Self::new()
}
}