Files
Interlap 4764434857 fix: address review findings on the concurrency rework
Four defects found reviewing the previous commit.

**Batch completion could erase a newer reservation.** `slim` and `restore`
cleared their own reservation in a `defer`, and `runConcurrently` cleared it
again when the result arrived. Those run in different MainActor tasks, so
another operation could claim the device in the gap and have its reservation
wiped by the batch's stale clear — leaving the device shown as free while work
ran on it. The runner is now the sole owner.

**Overlapping operations could lose their final refresh.** `refresh()` dropped
any request made while one was in flight. That was safe when every mutation was
globally exclusive; now that two devices finish independently, the second one's
refresh could be dropped after the first had already read the device list, and
its row would stay stale indefinitely. Requests made during a refresh are
coalesced into a follow-up run, mirroring `diskReloadRequested`.

**Batch controls were enabled but silently did nothing.** Relaxing the view
gating left `runBatch`, `cleanDisk`, `analyzeDisk` and `runManagementBatch`
guarding on `batchProgress == nil`, so Slim/Unslim/Erase/Delete/Clean on an
idle device during a batch returned without doing anything. They now gate on
`canStartBatchOnSelection` / `isBatchRunning`; per-device actions (boot,
shutdown, clone, rename, measure) stay live as intended.

**`ensure` read a booted device without waiting for boot.** `simctl list`
reports Booted from the moment a boot starts, so `readDisabled` on a device
that is still coming up would fail the whole command instead of waiting. The
booted branch calls `BootAndWait` first; on a device that really is booted
that costs ~0.2s.

Also assert full transition coverage in the applyDelta concurrency test — it
pinned the bound but would have passed an implementation that ran only the
first `spawnWorkers` labels.
2026-09-21 10:43:54 +02:00
..