Skip to content

ROCMAI-52: Modularize engines/lemonade/src/lib.rs - #457

Open
jussielo-amd wants to merge 3 commits into
ROCm:mainfrom
jussielo-amd:worktree-rocmai-52-lemonade-modularize
Open

jussielo-amd wants to merge 3 commits into
ROCm:mainfrom
jussielo-amd:worktree-rocmai-52-lemonade-modularize

Conversation

@jussielo-amd

Copy link
Copy Markdown
Collaborator

Summary

  • Phase 2 of epic ROCMAI-27's modularization plan. Splits engines/lemonade/src/lib.rs (7,886 lines — the ticket's stated 4,915-line estimate was stale, per the epic's own re-verification rule) into six modules following the full-domain-extraction convention established by Phase 1 (engines/vllm, PR EAI-8033: Modularize engines/vllm/src/lib.rs #436):
    • install.rs — embeddable-runtime archive download/verify/extract, cache locking, manifest persistence
    • backend_alignment.rs (new, not in the ticket's original 4-module list) — the ROCm-SDK-to-llama.cpp-backend Tier1/2/3 alignment state machine, a ~800-line self-contained subsystem the stale estimate didn't account for
    • process.rs — lemond/llama-server spawn, env/path setup, backend install/pull/model-load, direct-serve readiness polling
    • runtime_dir.rs (new) — XDG_RUNTIME_DIR tier1/2/3 hardening, a ~500-line security-critical subsystem with its own 25 dedicated tests
    • direct_llama.rs — Hugging Face checkpoint/GGUF resolution and the direct-llama-server serve path
    • state.rs — service state file I/O, device-policy/GPU-selection parsing, port/endpoint helpers
    • lib.rs keeps only CLI/envelope dispatch and the service-lifecycle orchestration that calls across the six modules
  • Updates docs/architecture.md in the same PR (per ROCMAI-72/EAI-7768's rule — not deferred).
  • Why 6 modules instead of the ticket's stated 4: re-verifying the actual file against main (per the epic's own rule to never trust a child ticket's stored line ranges) surfaced two large, genuinely self-contained subsystems — backend alignment and runtime-dir hardening — that the epic's own "full domain extraction" convention says deserve their own files rather than being folded into process.rs as a second god-file.
  • No behavior change: pure code motion. All 121 pre-split tests were partitioned across the new files (verified exact 1:1 test-count match) and moved in this PR, not deferred.

Test plan

  • cargo build, cargo test -p rocm-engine-lemonade — 120/121 tests pass (1 is #[cfg(windows)]-gated and doesn't compile on this Linux host, same as pre-split behavior)
  • cargo clippy -p rocm-engine-lemonade --all-targets -- -D warnings — clean
  • cargo build --workspace, cargo clippy --workspace --all-targets -- -D warnings, cargo test --workspace --all-targets --exclude e2e-cucumber — all clean
  • cargo xtask manifest --check — no-op (no dependency changes)
  • cargo fmt --all --check / prek run --all-files --no-group local-tools — clean
  • cargo xtask e2e -- -n "^serve-18" (mock-lane lemonade canary) — passes. GPU-gated scenarios (serve-07, serve-08, runtime-16, runtime-17) could not run in this sandbox (no GPU device) — deferred to CI's GPU lane
  • Verified the CLI/envelope dispatch table (run_cli/handle_envelope) is structurally unchanged: same CommandKind/EngineMethod arms in the same order, calling the same handler functions
  • Verified via automated diff that all 232 top-level production items (fns/structs/enums/consts) from the original file are accounted for exactly once across the new files — no dropped or duplicated code

Split the 7,886-line lib.rs (actual size, not the ticket's stale
4,915-line estimate) into six modules following the full-domain-extraction
convention established by vllm's Phase 1 split: install.rs (archive
download/verify/extract, cache locking), backend_alignment.rs (ROCm-SDK
to llama.cpp backend Tier1/2/3 alignment), process.rs (spawn/env,
backend install/pull/model-load, direct-llama-server readiness),
runtime_dir.rs (XDG_RUNTIME_DIR hardening), direct_llama.rs (HF
checkpoint/GGUF resolution), and state.rs (service state I/O, device
policy). lib.rs keeps only CLI/envelope dispatch and the service-lifecycle
orchestration that calls across those modules.

No behavior change: verified via cargo build/clippy/test across the
workspace, all 121 pre-split tests partitioned and passing, and the
mock-lane e2e scenario (serve-18). Updates the architecture doc in the
same PR per EAI-7768's rules.

Signed-off-by: Jussi Elo <jussi.elo@amd.com>
@jussielo-amd
jussielo-amd requested a review from a team as a code owner September 29, 2026 07:59
@jussielo-amd
jussielo-amd requested review from fredespi and a balanced review from Copilot September 29, 2026 07:59

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The private backend-alignment module unintentionally hides a previously public constant, introducing an API compatibility regression.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)
What changed in this PR

Refactors the Lemonade engine adapter into focused domain modules while preserving dispatch and lifecycle orchestration in lib.rs.

Changes:

  • Extracts installation, backend alignment, process, runtime-directory, direct-llama, and state logic.
  • Moves associated unit tests alongside each domain.
  • Updates the architecture documentation.
File Description
engines/​lemonade/​src/​lib.rs Retains dispatch and lifecycle orchestration.
engines/​lemonade/​src/​install.rs Handles runtime installation and archive caching.
engines/​lemonade/​src/​backend_alignment.rs Handles ROCm backend alignment and selection.
engines/​lemonade/​src/​process.rs Manages processes, environment, and readiness.
engines/​lemonade/​src/​runtime_dir.rs Secures runtime-directory preparation.
engines/​lemonade/​src/​direct_llama.rs Handles GGUF resolution and direct serving.
engines/​lemonade/​src/​state.rs Manages service state and device selection.
docs/​architecture.md Documents the new module structure.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread engines/lemonade/src/lib.rs
… root

backend_alignment is a private module, so moving this constant into it
silently dropped a path that was pub at the crate root before the split.
rocm-engine-lemonade is consumed as a lib by apps/rocm, so this is a real
(if currently unused) API surface change, not the "every pub item in a
binary crate is unreachable" case docs/architecture.md's disabled
unreachable_pub lint covers. Re-export restores the pre-split path.

Flagged by Copilot review on PR ROCm#457.

Signed-off-by: Jussi Elo <jussi.elo@amd.com>
windows-build-and-test failed: rocm-engine-lemonade no longer built on
Windows once split, because several imports are only used by unix-only
(runtime_dir.rs) or non-Windows (state.rs's spawn_serve_http_background)
code paths. In the monolithic file these were folded in among hundreds of
other always-used imports and never went unused on any one platform;
isolated per-module, the platform-specific half becomes visible per file.

- runtime_dir.rs: `anyhow!`/`bail!`/`OsStr` are only reachable from
  `#[cfg(unix)]` functions; gate the imports the same way. Also gate the
  test module's `use super::*`/`use crate::process::{...}` behind
  `#[cfg(target_os = "linux")]`, since their only consumer
  (`mod child_runtime_dir`) is itself Linux-only.
- state.rs: `Command as ProcessCommand`/`Stdio` are only used by
  `spawn_serve_http_background`'s `#[cfg(not(windows))]` variant.

Verified via `cargo build --workspace --all-targets --target
x86_64-pc-windows-gnu` with `RUSTFLAGS=-D warnings` (matching
actions-rust-lang/setup-rust-toolchain's default, which is what turned
these warnings into the CI failure) — clean, 0 warnings.

Signed-off-by: Jussi Elo <jussi.elo@amd.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.

2 participants