Skip to content

review C: desktop output ownership, converter preflight, cancel race (docs/29 findings 5, 13, 14) - #64

Merged
RobbinBouwmeester merged 1 commit into
review/b-workersfrom
review/c-desktop
Sep 8, 2026
Merged

RobbinBouwmeester merged 1 commit into
review/b-workersfrom
review/c-desktop

Conversation

@RobbinBouwmeester

Copy link
Copy Markdown
Member

Third of the four stacked code-review PRs (docs/29_code_review_2026-09-07.md, work package C). Base is review/b-workers (#63); merge A, B, then this.

What changes

#5, output ownership. The desktop frontend refuses a Start while one is in progress (guard before the first await) or while the run it follows is still running. The backend reserves a run's results folder by canonical path before spawning the engine and releases it when the run's end is published; a request for an active folder is refused with the owning run named. run-experiment --run-names rejects names that differ only in case on every platform.

#13, converter preflight. thermo::converters(config) probes doctor --json --config <request config>, so converters named in convert.thermo_raw_parser / convert.msconvert count. thermo::converter_verdict restates the engine's rule (raw::ensure_mzml): Thermo with the parser at auto and only msconvert present runs with a note; an explicitly configured parser that is missing blocks; other vendors need msconvert. A probe that cannot run is a warning, not a block.

#14, cancel race. Run::publish_exit is the single writer of the terminal status. cancel records intent (cancel_requested in the snapshot, atomic flag read by the waiter) and kills; the waiter publishes cancelled, done (successful exit before the kill landed) or failed, releases the folder reservation first, and sweeps temp files after the reap.

Coverage. Dependabot entry for /desktop; CI audits desktop/Cargo.lock (--ignore RUSTSEC-2024-0429, glib 0.18 pinned by Tauri 2's gtk 0.18, documented in the workflow).

Tests

  • run.rs: controlled interleavings of Stop and the engine's own exit (cancel before the waiter wakes, failure before Stop, success under Stop, wait error), intent-only cancel, reservation refusal, spelling alias, case alias (asserts per what the filesystem reports), release on publish.
  • thermo.rs: Thermo with only msconvert (note, no block); explicit missing parser blocks despite msconvert; off-PATH configured converters pass; nothing installed blocks Thermo and Bruker; probe argv carries --config; report parsing.
  • run_experiment.rs: case-only and repeated run names rejected, distinct pass.

Local: desktop cargo fmt --check, clippy -D warnings, cargo test --lib (78), engine clippy + cargo test --workspace, ci/check_desktop_ui.py, ci/check_workflows.py, cargo audit --file desktop/Cargo.lock ... --ignore RUSTSEC-2024-0429.

🤖 Generated with Claude Code

… per request, publish one terminal state

Code review C (docs/29 findings 5, 13, 14).

Output ownership (#5). A repeated Start in the desktop application launched a
second engine into the same results folder: the start flow had several awaits
and no in-progress guard, and the backend launched every request. The frontend
now refuses a Start while one is in progress or while the run it follows is
still running. The backend reserves a run's results folder by canonical path
before spawning the engine and releases it when the run's end is published, so
a request for an active folder is refused with the owning run named. The CLI's
--run-names check compares names without regard to case on every platform,
because RunA and runa are one directory on Windows, macOS and most network
shares.

Converter preflight (#13). The desktop asked `doctor --json` without the
request's configuration, so a converter named in convert.thermo_raw_parser or
convert.msconvert was reported missing and the search refused; it also required
ThermoRawFileParser for Thermo .raw even when msconvert, the engine's fallback
for a parser left at auto, was present. The probe now carries the configuration
and the verdict is the engine's rule: only msconvert present runs with a note,
an explicitly configured parser that is missing blocks.

Cancel race (#14). `cancel` and the process waiter both wrote the terminal
status, whichever ran second won, and the cancellation flag was never read, so
a stopped run could be shown as failed with the last log line as its error. The
waiter is the only writer now: it reads the intent after reaping the engine and
publishes cancelled, done (the engine had already finished) or failed; until
then the snapshot carries cancel_requested and the interface shows Stopping.

Also: Dependabot for /desktop and a cargo audit of desktop/Cargo.lock in CI
(one documented ignore, RUSTSEC-2024-0429 via Tauri 2's gtk 0.18).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant