Skip to content

nvx-rs: make the host module's dependency graph acyclic #897

Open

Description

Parent: #896. Needs: nothing. Unblocks: #898, #899.

Goal. Make the production dependency graph between nvx::host's direct children acyclic by moving three misplaced items, with no behavioral or public API change, and add a guard that keeps it acyclic.

Today (dev 6af32ba0): the references between host's children, as #896 defines them, form one strongly connected component of 8 children: artifacts, filesystem, launch, platform, process, sandbox, store and supervisor. Three back-edges close it:

  1. platform → supervisor. Inherited, with its Borrowed alias and its impls, is defined in nvx-rs/src/host/supervisor/child.rs:30-113, and platform/linux.rs:12, platform/windows.rs:64 and platform/other.rs:8 import crate::host::supervisor::Inherited.
  2. store → supervisor. The rest of supervisor::child, VmmCommand, spawn and Launched (child.rs:115-405), imports only platform, process and protocol (child.rs:24-28). But store/mod.rs:242 imports super::supervisor::Launched, while supervisor imports store (supervisor/mod.rs:109-112).
  3. artifacts → sandbox. require_artifact (pub(crate), sandbox/mod.rs:154-158) and the private require_existing (160-170) and require_pure_file (464-471) live in sandbox, and artifacts.rs:42 imports require_artifact for required (artifacts.rs:871-876), while sandbox/distro.rs:49 imports artifacts::DISTRO_MANIFEST_SUFFIX.

Changes:

  • Move Inherited and Borrowed into a new crate-visible module, host::platform::inherit. Inherited stays pub, and is re-exported only as nvx::host::supervisor::Inherited.
  • Move supervisor/child.rs to a private host::spawn module, with git mv. supervisor re-exports Launched, VmmCommand and spawn (supervisor/mod.rs:106 today), and store imports super::spawn::Launched. The link [launch](super::launch) (child.rs:166) gets a crate:: path (nvx-rs: break the host module into finer-grained modules #896, invariant 6), as does the link to spawn in Inherited's documentation (child.rs:45).
  • Move require_artifact, require_existing and require_pure_file into host::artifacts, as pub(crate). The public sandbox::require_file (sandbox/mod.rs:146-152) stays, and calls artifacts::require_existing. Their other users import them from artifacts: cli/run.rs:41, cli/sandbox/mod.rs:48-52 and sandbox/plan.rs:114-117.
  • Guard: nvx-rs/tests/host_modules.rs, a std-only integration test that reads the sources under src/host and builds the production graph between host's children as nvx-rs: break the host module into finer-grained modules #896 defines it. It resolves crate::, super:: and self:: paths in use trees and expressions, and the crate-root re-exports, and skips comments and cfg(test) code, so the links of child.rs:165 and 216 to store::Launch::record_process are not edges. It fails with a list of each cycle, with one example reference per edge. It runs in check-nvx-rs's existing cargo test steps (.github/actions/check-nvx-rs/action.yml:57-69), with no new dependency and no workflow change. It must fail on today's dev and pass after the three moves.

Resulting order of host's children, lowest first, from the graph of 6af32ba0 with the three moves applied:

Layer Children
0 sys, python, network, seal, report
1 platform
2 filesystem, nvxs, process
3 session, spawn
4 store
5 artifacts
6 launch
7 supervisor
8 instance, sandbox
9 cli

The template stack (#896). At the head of #888 (a2d5ddf9), the new host::template joins the cycle, which grows to 12 children. With the three moves, two of its edges still close one: store → template (template::Lease, from #886) and sandbox → template (template::BlockGeometry, in sandbox/{mod,distro,scratch}.rs, from #888). Without those two, the graph is acyclic, with template beside cli at the top. Whichever lands second, this issue or the stack, resolves them, for example by moving the items that store and sandbox take below them.

Evidence from a prototype on dev 8522cc4e:

  • 14 files, +151/-136.
  • The public API surface from rustdoc JSON is identical: 2,278 entries on Windows and 3,095 on Linux, with 0 differences.
  • 706 library tests pass on Windows, and the Windows test list is unchanged.
  • On Linux, the four Linux-only tests of supervisor::child (child.rs:407-554 today) become host::spawn::tests::*. No coverage family or bundling filter is affected.

Tests: the guard; the public API diff (#896, invariant 1); and cargo test -- --list on Linux and Windows, which changes only by the rename of those four Linux tests.

Acceptance. The graph between host's children is acyclic in production code. The guard is green on the PR and demonstrably red on today's dev. The public API diff is zero on Linux and Windows. CI is green.

Metadata

Metadata

Labels

No labels
No labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions