Repository navigation
feat: show each rollout's Swarm tasks and downtime as it happens - #431
Open
PiquelChips wants to merge 9 commits into
Open
PiquelChips wants to merge 9 commits into
PiquelChips wants to merge 9 commits into
Conversation
Contributor
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 59 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
PiquelChips
force-pushed
the
feat/timeline-5-tasks
branch
3 times, most recently
from
November 10, 2026 20:02
83afc70 to
966cf7b
Compare
PiquelChips
force-pushed
the
feat/timeline-5-tasks
branch
from
November 10, 2026 20:32
966cf7b to
93c5ae5
Compare
PiquelChips
marked this pull request as ready for review
November 10, 2026 20:33
PiquelChips
force-pushed
the
feat/timeline-5-tasks
branch
from
November 10, 2026 21:29
93c5ae5 to
711f8d8
Compare
PiquelChips
force-pushed
the
feat/timeline-5-tasks
branch
from
November 10, 2026 21:52
711f8d8 to
eacdd0c
Compare
PiquelChips
force-pushed
the
feat/timeline-5-tasks
branch
from
November 10, 2026 22:13
eacdd0c to
8fdabd0
Compare
PiquelChips
force-pushed
the
feat/timeline-5-tasks
branch
2 times, most recently
from
November 13, 2026 15:00
189954b to
eefc8d4
Compare
While a deployment waits for a service to roll out, it now records the service's Swarm tasks each time one changes state, as `action_progressed` events on the wait's action. The timeline turns them into one lane per task, old and new, with the states it moved through, and `Step::gaps` reports when no task served requests, the downtime of a stop-first rollout. Observed tasks gain their ID, slot, and whether they run the service's current specification, which is how Swarm decides what to replace. The fake engine's slow services now start their tasks and run them once converged.
Updating and waiting for a service were journaled under its Docker name, `piqueld-env-…-servi-6991c03b8095`, which made timelines hard to read and named a service's update and its wait differently. Wait actions now carry the service's logical name, and both steps record it, as plan output already showed.
The dashboard and piquelctl both need the same few facts about a rollout while it happens, so the timeline's steps derive them once: how many new tasks serve (`Step::new_tasks`), the monitor window open now (`Step::monitor`), how long no task served (`Step::downtime`), and whether an old task was seen serving once a new one did (`Step::overlapped`), the only honest ground for saying there was no downtime.
Comparing a task's specification with its service's never matched on a real engine: Docker reports defaults such as `StopGracePeriod` and `Runtime` in the service's and not in its tasks', so every task looked old. A task now runs the current specification when Swarm created it since the service's latest update started, or always for a service never updated.
While a deployment waits for a service, its step's row shows how many new tasks run, how long Docker still watches the newest one, and how long no task served: `1/2 new tasks running · monitor 4.2 s left · down 3.2 s`. Without a terminal, a line prints each time one more new task runs, and the step's last line says how long the service was down; `--json` emits a `step` event on the same changes.
A wait for a service now shows its Swarm tasks in the step detail: a lane per task, old and new, colored by state, with its monitor window striped and counted down by a ring while Docker watches a new task. When no task served, a red striped bar marks it on the step's row and the detail says for how long; when an old task was seen serving until a new one did, it says there was no downtime. Lanes redraw only when their step changes: the shared clock moves one CSS variable that open states reach, and the ring sweeps through CSS.
Docker can list a service's tasks in another order between two polls, which recorded a rollout progress event, and woke every open stream, for no change. The tasks are now compared in slot and ID order.
Rust 1.100's clippy flags `map(..).unwrap_or_default()`, which the downtime bars used.
PiquelChips
force-pushed
the
feat/timeline-5-tasks
branch
from
November 13, 2026 20:05
eefc8d4 to
afd4963
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
While a deployment rolled a service out, the timeline only said "Wait for service web · running". You could not see which tasks Swarm was replacing, whether Docker was still watching a new one for failure, or whether the service was down: a
stop-firstrollout (any service that mounts a volume read-write) stops its old task before the new one serves, and nothing showed that gap.Now the daemon records the service's Swarm tasks each time one changes state while it waits, and both surfaces show the rollout as it happens:
1/2 new tasks running · monitor 4.2 s left, anddown 3.2 swhen the service was down. Without a terminal, a line prints each time one more new task runs, and the step's last line carries the downtime.--jsonemitsstepevents on the same changes.Service steps are also named by their manifest name ("Wait for service web") instead of their long Docker name.
Checked against a dev instance with a 2-replica, health-checked
start-firstservice and a 1-replicastop-firstservice that mounts a volume. That run turned up a bug in the first commit: task and service specifications never compare equal on a real engine, because Docker reports defaults in one and not the other, so every task looked old. Tasks are now told apart by whether Swarm created them since the service's latest update started.Known limit: the daemon polls tasks at least once a second, so a handover shorter than one poll shows neither a gap nor an overlap. In that case the dashboard says nothing about downtime rather than guessing.
Performance: lanes redraw only when their step changes. The shared one-second clock moves one CSS variable that open states grow to, and the ring sweeps through a CSS animation. The CLI fetches nothing extra and redraws on its existing 100 ms tick.
Proved on a dev instance with real Swarm rollouts (start-first and stop-first, task lanes, monitor countdown, downtime) and core, CLI and Playwright tests.
Reviewed with review-loop: 3 rounds with 3× Claude Opus 5.5 (GPT 6.1 Sol was out of credits; a Sol pass is still owed). Verdict: approved
Note
Written by Claude Opus 5.5 in Claude Code and reviewed by Claude Opus 5.5 (via T3 Code)