Repository navigation
refactor(services): move managed-service process control out of services_text.rs into service_control.rs - #902
Conversation
…ces_text.rs into service_control.rs services_text.rs is named for rendering, but about a third of its production lines stopped and restarted managed local servers. Move that process-control cluster into its own apps/rocm/src/service_control.rs: run_internal_sandbox_tool, the stop path (terminate_recorded_service_pids, MANAGED_STOP_GRACE, the RecordedPidOutcome and RecordedStopTermination types, the e2e-test-hooks scripted_stop_outcome seam, stop_internal_managed_service and its _with and _confirmed_with forms, unload_lemonade_service_model) and the restart path (apply_restart_runtime_pin, load_service_for_restart, restart_child_argv, restart_internal_managed_service and its _with form, update_restarting_record, record_restarted_child, record_restart_readiness), together with the tests that drive them and their cfg gates. This is a pure move: every moved line is unchanged. The only edits besides relocating code and tests are the imports, two items widened from private to pub(crate) so service_control.rs can reach them (read_managed_service_manifest, and process_check_command for the moved tests), and doc comments that named the old location. Importers (main.rs, services_cmd.rs, service_launch.rs, runtime_services.rs) now import from crate::service_control directly rather than through a services_text re-export, which would have made the two modules import each other. internal_stop_server_value, service_stop_unconfirmed and the unconfirmed-stop renderer stay in services_text.rs with the other stop_server answer code. docs/architecture.md, the moved-from module's own //! doc, the sibling module docs that named the old location, and the comment in main.rs's use block are updated in the same change. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
There was a problem hiding this comment.
🟢 Approval recommended
No active review issues remain for the process-control module extraction.
No open issues 🎉
What changed in this PR
Separates managed-service process control from text rendering by moving the stop/restart implementation into service_control.rs, continuing the CLI’s module split without intended user-visible changes.
Changes:
- Relocates process-control helpers and their 26 tests, preserving platform and feature gates.
- Updates callers to import directly from
service_control. - Revises module and architecture documentation to reflect the new ownership.
| File | Description |
|---|---|
docs/architecture.md |
Documents the process-control module and revised dependencies. |
apps/rocm/src/services_text.rs |
Removes process control and its tests; retains rendering and record helpers. |
apps/rocm/src/services_cmd.rs |
Imports the sandbox runner from service_control and updates module docs. |
apps/rocm/src/service_launch.rs |
Redirects the sandbox-runner import. |
apps/rocm/src/runtime_services.rs |
Imports restart control from its new module. |
apps/rocm/src/main.rs |
Registers service_control and updates the runner import. |
apps/rocm/src/gpu_policy.rs |
Updates documentation naming the restart helper’s module. |
apps/rocm/src/engine_runtime_select.rs |
Updates documentation identifying process-control callers. |
Review effort: Balanced
juhovainio
left a comment
There was a problem hiding this comment.
Reviewed the diff and found nothing blocking. The move looks behavior-preserving: the relocated code matches what was removed, apart from imports, the mod service_control; declaration, the tests wrapper, and the two pub(crate) widenings (process_check_command, read_managed_service_manifest), both needed and called out in the description. cfg gates and tests travel with the code.
Non-blocking notes:
- The branch currently conflicts with main and needs a rebase; the other open PRs listed in the description will need re-applying afterwards, so merge ordering matters.
- The two Strix Halo Ubuntu E2E lanes (release and nightly) were red when I looked, and MI300X/W7900 were still pending. I couldn't see the logs, so please confirm those are hardware-lane flakes (and not something this PR causes) before merging.
- Please cite the tracking ticket key in the description.
This is a diff-only read; I did not build or run the tests locally.
…t-move-service-control Resolves the import and architecture.md conflicts: the service_control.rs import in runtime_services.rs and the services_text.rs import list keep this branch's moved-out imports and add main's shell_quote import; architecture.md keeps main's updated freeform_planner and service_hints entries together with this branch's service_control entry and the trimmed gpu_policy and service_launch mentions. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
…t-move-service-control Conflicts were the services_text.rs module doc and the freeform_planner/gpu_policy entries in docs/architecture.md: kept main's updated wording about validate_service_id and rocm_argv.rs together with this branch's service_control.rs references. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
|
Thanks for the approval. Merged |
Summary
apps/rocm/src/services_text.rsis named for rendering (the logs browser, therocm servicesstatus text), but about a third of its production code stops and restarts managed local servers: the sandbox-tool runner, the stop path with its verified process termination, and the restart path with its record bookkeeping. Anyone looking for howrocm services stop|restartactually works has to find it inside a text-rendering module of about 1,570 production lines. This PR moves that process-control cluster into its ownapps/rocm/src/service_control.rs. It is a pure move: no behaviour changes, no renames, and every moved line is byte-identical. This is part of the Phase 8.2-G follow-up work.This is part of the ongoing
apps/rocmmodule split; further moves follow.The importers switch to the new path instead of going through a
services_textre-export, because a re-export would makeservices_textandservice_controlimport each other.What moved
Everything below went from
services_text.rstoservice_control.rs, with itscfggates intact (cfg(windows),cfg(not(windows)),cfg(feature = "e2e-test-hooks"), andcfg(unix)on the process tests).run_internal_sandbox_tool(pub(crate))service_control.rsMANAGED_STOP_GRACE,terminate_recorded_service_pidsservice_control.rsRecordedPidOutcome,RecordedStopTermination(private types the stop path returns; not in the ticket's list, but the moved functions cannot be separated from them)service_control.rsscripted_stop_outcome(bothe2e-test-hooksvariants)service_control.rsstop_internal_managed_service,stop_internal_managed_service_with,stop_internal_managed_service_confirmed_with,unload_lemonade_service_modelservice_control.rsapply_restart_runtime_pin,load_service_for_restart,restart_child_argvservice_control.rsrestart_internal_managed_service(pub(crate)),restart_internal_managed_service_withservice_control.rsupdate_restarting_record,record_restarted_child,record_restart_readinessservice_control.rsservices_stop_*report tests, themanaged_stop_*process tests) and their helpersservice_control.rsmod testsImporters now use
crate::service_control::...directly:main.rsandservices_cmd.rsandservice_launch.rs(run_internal_sandbox_tool), andruntime_services.rs(restart_internal_managed_service). The ticket named three importers;services_cmd.rsis a fourth that the earlier services-family split created.What stays in
services_text.rs: the logs browser, status rendering,render_service_action_result,render_unconfirmed_service_stop,read_managed_service_manifest,load_managed_service,validate_service_id,render_internal_status_text, and alsointernal_stop_server_value,stop_report_confirmedandservice_stop_unconfirmed. The last three are not in the ticket's list; I left them with the renderer that reads the samestop_unconfirmedstatus rather than widen the move, andservice_control.rsimportsinternal_stop_server_valuefrom there. Two items are widened from private topub(crate)because the new module reaches them:read_managed_service_manifest, andprocess_check_command(used only by one moved test). Nothing else changed visibility.Documentation updated in the same commit:
docs/architecture.md(a new entry forservice_control.rs, theservices_text.rsentry narrowed, and the entries forengine_runtime_select.rs,gpu_policy.rs,engines_cmd.rs,service_launch.rsandservices_cmd.rsthat namedservices_text.rsas the caller of moved code), the//!docs ofservices_text.rs,engine_runtime_select.rs,gpu_policy.rsandservices_cmd.rs, two doc comments inservices_text.rsthat linked to moved functions, and the comment inmain.rs'suseblock that namedservices_text.rsas home ofrestart_internal_managed_service. A grep of docs, AGENTS.md, CONTRIBUTING.md, xtask, tests, .github and .pre-commit-config.yaml found no path pin (inxtask/src/ascii_output_contract.rs,advised_commands.rsor elsewhere) that names the moved code.Verification
Ran, on Linux (
-j 4, private target dir):cargo fmt --all --check: clean.cargo clippy -p rocm --all-targets -- -D warnings: clean. Also clean with--features e2e-test-hooks, which compiles thescripted_stop_outcomehook variant.cargo test -p rocm --no-fail-fast: 1,473 passed, 0 failed, 8 ignored across allrocmtest binaries.cargo test -p rocm -- --listand-- --list --ignored,origin/mainagainst this branch: empty for both (1,480 and 8 names; module paths change for the moved tests, leaf names do not).services_text.rsappears in the newservices_text.rsorservice_control.rsexcept doc-comment and import lines and the twopub(crate)widenings listed above.cargo test -p rocm advised_commands,cargo xtask manifest --check,cargo xtask check-crate-edges,cargo xtask lycheeandcargo test -p xtask: all pass (advised_commands20 passed and 1 ignored;xtask398 passed).git diff origin/main...HEAD: every hit is an existing identifier (internal_*function names, Rustprivatevisibility) or a pre-existing sentence indocs/architecture.md; no internal names, hosts, trackers or addresses.Not run:
cargo clippy -p rocm --target x86_64-pc-windows-msvccannot finish on this host: theringandaws-lc-sysbuild scripts fail first (nolib.exe, MSVC C headers missing), beforerocmis reached. Thecfg(windows)code moved verbatim (the restart's Windows spawn block and its two Windows-only imports), and the Windows lane's "Clippy (Windows targets)" step inwindows-debugis the check for it; please treat that lane as the authority for this PR.cargo xtask e2e,scripts/smoke_local.pyand the full workspace gate (CI carries them).User-visible behaviour
None. This is a pure move of internal process-control code; nothing a user of the CLI can observe changes (output, exit codes, files, engine selection), so no new scenario is needed. The existing scenarios that exercise stop and restart keep covering it:
service-stop-yes-stops-a-running-service,service-stop-confirms-a-stop-and-cleans-up,service-stop-unconfirmed-fails-and-keeps-the-record,service-stop-unverified-fails-without-a-retryandservice-stop-unconfirmed-keyless-keeps-only-the-record(stop; the unconfirmed ones use thee2e-test-hooksROCM_E2E_STOP_OUTCOMEseam that moved here),service-unknown-stopandservice-unknown-restart(the shared not-found error through both paths), andruntime-lifecycle-failed-service-restart-is-reported(restart;runtime-lifecycle-activate-restart-services-succeedsneeds a GPU and runs on the GPU lane). All of these run on the mock lane on every PR except the GPU-gated one. The Windows lane runs only the@lifecyclescenarios plus a short list of named ones, so it does not exercise stop or restart end to end; on Windows the moved code is covered by its clippy step and the workspace unit tests (themanaged_stop_*process tests arecfg(unix)).Notes for reviewers
Reading order:
service_control.rsfirst (the module//!doc lists what it owns and who calls it), then the shrunkservices_text.rs, then the one-line import changes inmain.rs,services_cmd.rs,service_launch.rsandruntime_services.rs, thendocs/architecture.md.Import cycles. The ticket expected this move to carry the existing
services_text<->service_launchcycle over toservice_control<->service_launch, neither adding nor removing one. On current main that is not quite what happens, and I would rather say so than let the PR text claim it.service_launch.rsimportsrun_internal_sandbox_toolfrom the new module and the new module importsensure_public_service_has_endpoint_keyand the spawn helpers fromservice_launch.rs, soservice_control<->service_launchis a pair.services_text.rsalso still reachescrate::service_launch::background_helper_note(inrender_service_action_result_with_helper_note, added after the audit) andservice_launch.rsstill importsrender_service_action_result,read_optional_tail_linesand others fromservices_text.rs, so that pair remains too. Sibling pairs that import each other go from one to two. Breaking either is a structure change, not a move, and stays out of scope. There is no cycle betweenservice_controlandservices_text:service_controlreads records andinternal_stop_server_valuefromservices_text, andservices_textimports nothing fromservice_controloutside its tests.The new module's
use crate::edges (production):endpoint_keys;engine_ipc(builtin_engine_serve_http_args,engine_request);engine_runtime_select(http_post_local_service_json,managed_service_launcher_path,parse_engine_recipe_json_arg,wait_for_service_http_ready, plusapply_app_path_envoff Windows andapp_path_env_var_refs/app_path_env_var_valueson Windows);engines_cmd(env_root_for_service);gpu_policy(parse_device_policy);managed_service_status(load_managed_services);service_launch(ensure_public_service_has_endpoint_key, plusattach_background_stdio,detach_background_command,managed_engine_startup_failure_detailandmanaged_service_process_commandoff Windows);services_text(internal_stop_server_value,load_managed_service,read_managed_service_manifest); and the crate root (SandboxToolArg,status_for_readiness). Test-only edges:runtime_services,services_cmd(finish_service_action),services_text::tests::assert_no_retry_line,services_text(process_check_command,render_service_action_result) andcrate::testsfixtures.check-crate-edgescovers crate-level edges only, so none of this is checked mechanically.Test assignment. The
services_stop_*tests assert both the rendered unconfirmed-stop text and the record, key and audit state on disk, throughfinish_service_action. I moved them with the stop path because each drivesstop_internal_managed_service_withwith a stand-in termination, which needs the privateRecordedStopTerminationtypes; keeping them inservices_text.rswould have widened those types and their fields topub(crate).assert_no_retry_linestays inservices_text::testsbecauseservice_launch.rs's tests import it there.service_commands_report_an_unknown_id_without_an_os_causestays inservices_text.rs: its subject isload_managed_service's not-found error, and it merely calls the moved runner.The ticket's line numbers and some assumptions were stale:
services_text.rsis about 1,573 lines before its test module on main (885 after this PR), and the moved production code is about 650 lines including doc comments and blanks (465 non-comment code lines in the new file) rather than 565.Open PRs that touch the same ground. Four open PRs edit the moved functions and will need their hunks re-applied onto
service_control.rs(git cannot follow the move): #859 (restart_internal_managed_service_with,record_restarted_child,record_restart_readiness), #854 (same functions), #299 (run_internal_sandbox_tool,stop_internal_managed_service,stop_internal_managed_service_with,MANAGED_STOP_GRACE) and #243 (stop_internal_managed_service,restart_internal_managed_serviceand_with). #889 (the clap command tree move intocli.rs, a proposal) editsmain.rs,runtime_services.rs,service_launch.rs,services_cmd.rsanddocs/architecture.md, including theservice_launch.rsandservices_cmd.rsentries this PR also edits; expect import-line anddocs/architecture.mdconflicts that are rebase-only. #883, #857, #723, #678, #563, #437, #631 and #888 touchservices_text.rsoutside the moved production code (rendering, and test-module hunks that may need to follow a moved test); #891 and #892 edit themain.rsuse block anddocs/architecture.mdonly.