Skip to main content

execute_reloaders_concurrently

Function execute_reloaders_concurrently 

Source
pub async fn execute_reloaders_concurrently(
    reloaders: HashMap<String, ReloaderConfig>,
    run_one: ReloaderRunFn,
    shutdown: Pin<Box<dyn Future<Output = ()> + Send>>,
) -> Result<()>
Expand description

Port of runAndWait’s concurrent core: launches every edit-mode reloader’s run_one concurrently, waits for all of them to finish (whether they succeed, fail, or a shutdown signal arrives first), and collects any real failures.

Uses [tokio::task::JoinSet] for structured concurrency: every spawned task is owned by the JoinSet and is guaranteed to be awaited (via join_next) before this function returns, unlike Go’s bare goroutines-plus-sync.WaitGroup, where nothing at the type level stops a goroutine from leaking past wg.Done().

Structural gap, not a stub (see PORT_NOTES.md): Go’s runReloader runs inside a context that’s cancelled on shutdown, and its reloader.Manager.Run(ctx, ...) implementations react to ctx.Done() to actually stop early. This port’s xianyun_deploy::reloader::Manager-shaped run calls (mirror/ skaffold’s concrete managers) take no context/cancellation parameter at all – they block until the underlying subprocess exits on its own. So when shutdown resolves while reloaders are still running, this function has no way to make them stop early either; it can only stop waiting new work and, like Go’s wg.Wait() after cancelRun(), still block until every already -running task finishes naturally. In practice (a real terminal delivering SIGINT to the whole foreground process group) the underlying mirrord/local child processes receive the signal directly regardless of this crate’s own cancellation plumbing, which is the same mechanism Go’s version ultimately relies on for a process that ignores ctx.Done().

§Errors

Returns whatever collect_reloader_errors reports once every reloader has finished.