Each component builds on its own, and stops reporting when it is done
A project's components were decoupled everywhere except the one place it showed: there was a single build slot per project, and a single card state in the app keyed by project alone. So pressing Update on one client of a two-client project disabled the other client's button for the length of a build it shares nothing with, drew this one's progress bar and download percentage under the other's row, and -- had the button been pressable -- would have been a silent no-op on the server, since a second request while one was running returned without starting anything. The slot is now per component. `Inner` has no `building` flag; a component's own `ComponentRun` with an open `step` is the answer, and `claim` writes that entry synchronously under the lock the route answers from, so nothing can read a just-claimed component as idle -- which the phone would take for a build that had already finished. A failure is recorded against the component whose command it was rather than in the project's one error slot, which two components building at once cannot share. A pull stays exclusive with everything, because there is one checkout and it rewrites the files every component builds from. Releasing it and claiming what it decided to build happen under one lock: a phone polling in the gap would find a project neither pulling nor building and call the run over. The app mirrors the split -- `ProjectState` for the pull and the project-wide Rebuild, `ComponentState` keyed by component for everything one component is asked to do. Two hierarchies rather than one keyed by a pair, so a download has nowhere project-wide to be stored. A component's failure is drawn in its own row beside the Retry that acts on it, which is also where a failed service action now reports. And a finished component shows nothing at all: the elapsed times are gone from both halves of the wire, and its button simply goes back to being pressable. A bar, a count and a last line all describe something happening now, and left up they sit there looking live next to a sibling that genuinely is. Verified on the emulator against test-projects/two-clients, which exists for this: while `tablet` built, its row alone carried the bar and its button alone was disabled, `phone` stayed pressable and silent, and both returned to normal with no timing left behind.
This commit is contained in:
1 parent
4641b9ec9b
commit
90082bd286
6 files changed
+862
-318
No files matched your search
@@ -493,6 +493,23 @@ struct ManifestApp {
|
||||
/// one flag for the list, so a card says whether *it* is the one still
|
||||
/// being worked out.
|
||||
check_pending: bool,
|
||||
/// The build running for this project right now, if one is, in the
|
||||
/// same shape `/status` answers.
|
||||
///
|
||||
/// Here so that a build survives leaving the app. The run itself never
|
||||
/// stops -- it owns its own `Arc<BuildState>` and outlives the request
|
||||
/// that started it -- but the phone's record of it lives only in the
|
||||
/// composition, so backgrounding tears down the polling loop and the
|
||||
/// card state together. Without this the list it comes back to cannot
|
||||
/// say a build is still going, and the card reads as one that was
|
||||
/// killed: it offers Update again, and pressing it does nothing,
|
||||
/// because there is already a run in this project's one build slot.
|
||||
///
|
||||
/// Read with [`crate::build_state::BuildState::running`] rather than
|
||||
/// `status`, which also answers `stale` and walks every component's
|
||||
/// directory to do it -- this is on the manifest path.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
build: Option<crate::build_state::RunningBuild>,
|
||||
/// What this project produces, in the order it is built. One entry is
|
||||
/// the ordinary case and the card shows it inline; more than one is
|
||||
/// what the phone draws as a nested list.
|
||||
@@ -656,6 +673,7 @@ async fn describe(state: &Arc<AppState>, entry: &AppEntry) -> Result<ManifestApp
|
||||
.build
|
||||
.as_ref()
|
||||
.is_some_and(|build| build.has_command()),
|
||||
build: entry.build.as_ref().and_then(|build| build.running()),
|
||||
git_ipv4: entry.git_ipv4,
|
||||
built_in: entry.built_in,
|
||||
pending_declaration: pending
|
||||
|
||||
Reference in new issue
Block a user