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.