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
@@ -388,17 +388,56 @@ mutable at runtime from the phone.
|
||||
the time one after the other does. The saving only appears when more than
|
||||
one has work, which is what a pull produces.
|
||||
The status is per component (`ComponentStatus`), so a card draws each
|
||||
component's bar, timing and last line inside that component's own row;
|
||||
component's bar and last line inside that component's own row;
|
||||
the project's own area at the bottom keeps only what belongs to the whole
|
||||
project, which is fetching and pulling. A bar under the card could only
|
||||
ever say that *something* was happening, and with everything building at
|
||||
once that is exactly what the reader is trying to find out.
|
||||
A failure no longer stops the others -- they are already running -- so
|
||||
the first failure in declaration order is the one reported, which is what
|
||||
a walk in that order would have said. The phone draws every component in
|
||||
A failure no longer stops the others -- they are already running -- and
|
||||
it is reported against the component whose command it was, never as the
|
||||
project's. The phone draws every component in
|
||||
a card of its own, including a project with only one: the flat layout it
|
||||
used to get meant two shapes to keep in step, and put that APK's size up
|
||||
beside the card's corner controls where it read as belonging to them.
|
||||
- **There is a build slot per component, not per project, and the two
|
||||
halves have to agree on that.** A component being built neither blocks
|
||||
another's build nor disables its controls: `Inner` has no `building`
|
||||
flag, only a `ComponentRun` per component whose open `step` *is* the
|
||||
answer, and `claim` writes that entry synchronously under the same lock
|
||||
the route answers from -- so nothing can read a component the request
|
||||
just claimed as idle, which the phone would take for "the build is
|
||||
over". `RunningBuild::building` stays, but it means "anything at all is
|
||||
happening here" and is only for the controls that act on the whole
|
||||
checkout; anything about one component reads that component's `step`.
|
||||
The app mirrors the split exactly: `ProjectState` for the pull and the
|
||||
project-wide Rebuild, `ComponentState` keyed by component name for
|
||||
everything a single component is asked to do. One map keyed by project
|
||||
alone is what the bug was -- pressing Update on one client of a
|
||||
two-client project disabled the other's button and drew this one's
|
||||
download bar under it -- and two hierarchies rather than one keyed by a
|
||||
pair is what stops it coming back, since a download has no
|
||||
project-wide meaning to be stored with.
|
||||
The exception, and it is worth keeping visible so it does not read as
|
||||
more of the same: **a pull really is exclusive with everything.** There
|
||||
is one checkout, and it rewrites the files every component builds from,
|
||||
so `Inner::pulling` blocks any component from being claimed and waits
|
||||
for any still building. Ending the pull and claiming what it decided to
|
||||
build happen under one lock for the same reason `claim` is
|
||||
synchronous -- a phone polling in the gap would see a project that is
|
||||
neither pulling nor building and call the run finished.
|
||||
- **A finished component shows nothing, and its button goes back to
|
||||
normal.** Iris's call, 2026-09-01: "you shouldn't see the time it took
|
||||
once it finishes, it should just go back to its normal enabled button
|
||||
state." So `ComponentBuildProgress` draws only while the step is open,
|
||||
and the elapsed times are gone from both halves of the wire -- a bar, a
|
||||
count and a last line all describe something happening *now*, and every
|
||||
one of them sits there looking live beside a sibling that genuinely is.
|
||||
What says the build landed is the control becoming pressable again and
|
||||
the card's own freshness. The failure is the exception, because it is an
|
||||
outcome rather than residue; it is drawn by the component card next to
|
||||
the Retry that acts on it, in the one place that reports that
|
||||
component's failures whether they came from a build, a download or a
|
||||
service action.
|
||||
- **A project's own `.dev-updater.ron` is a request, never an
|
||||
instruction.** It only runs once accepted from the phone, which copies
|
||||
it into `config.ron`; `AppEntry::pending_declaration` is the whole gate.
|
||||
|
||||
Reference in new issue
Block a user