Skip to content

Retry and the next start try an unfinished backend update again when it left OpenBot running but not working - #1503

Open
guidovizoso wants to merge 5 commits into
mainfrom
guido/retry-update-on-degraded-stack
Open

guidovizoso wants to merge 5 commits into
mainfrom
guido/retry-update-on-degraded-stack

Conversation

@guidovizoso

Copy link
Copy Markdown
Collaborator

What was wrong

A dogfooding report: OpenBot Desktop 1.0.1 updated to 1.0.2 on a Mac. On first start, the backend update (Intelligence 0.16.0-rc.10 to rc.11) paused the services (update-quiesce) and then failed once at dependencies-install. That left the stack running with its checks failing (readiness degraded) and the update on record (unfinishedUpdate).

The window then said OpenBot is stopped, with "OpenBot tries again the next time it starts" on the update row, but every Retry asked for local status once and gave up in 0.0s. The update was never tried again, so the person was stuck.

The wait loop in desktop/src/LocalIntelligence.tsx re-ran an unfinished update only on a stack that was ready, stopped, or still on the release it had with every check passing (kept). A degraded stack with failing checks matched none of these. start is skipped while an update is on record (the CLI refuses it), and degraded is not starting, so the wait stopped at once.

The fix

  • A stack that is stopped or degraded with an update on record now runs local update again. That is the only call that gets it going, since the CLI refuses start. The old kept case is one of these degraded stacks, so the condition now covers it without listing it separately.
  • This still runs at most once per wait (updatedIntelligence). If the update fails again, the wait stops at once on the failed row ("It stopped while updating where OpenBot keeps your data"). It does not wait the way it does after waking a stopped stack, because nothing on a degraded stack comes back by itself. Each Retry is one more attempt.
  • The comments ("AN UPDATE THAT DID NOT FINISH" and woken) now explain this.
  • No user-facing text changed.

The repair before an update (local_update.rs)

The repair rolls back only a release that Helm left pending-*, and puts back Learning Deployments that are missing. A release that a failed dependencies-install left failed is not touched. Helm 3 upgrades a failed release from its last deployed revision, so it needs no repair. A new fake-CLI case pins this down: the repair does not roll back or re-apply anything, and the next update runs to the end.

Tests

  • LocalIntelligence.test.tsx, "a backend an update left not working runs the update again, and opens once it finishes": status degraded with dependencies-install on record and updateTo set, then local update completes, status is ready and OpenBot starts. Before the fix it failed (no update, nothing started). After the fix it passes.
  • LocalIntelligence.test.tsx, "an update that stops again is tried once per Start, and Retry tries it once more": the first update fails, the wait stops after status, update, status with the failed row and Retry, and there is no second update. Retry runs status, update, status again, that update completes, and OpenBot starts. Before the fix it failed (no update, so no update row). After the fix it passes.
  • App.test.tsx, "a backend whose check fails is still not healthy, with an update on record or not": this test now expects the update to be tried once (status, update, status). Its point is unchanged: a failing check is still not treated as running on the release the stack had, nothing is started and Retry is offered.
  • local_eval.rs, a_release_an_update_left_failed_is_not_repaired_and_the_next_update_finishes: this uses the fake CLI and Helm. The first helm upgrade -f stopped.yaml fails and leaves the release failed. The repair checks the release and does nothing, the update is not retried in the same call, and the next local update completes with no rollback.

Run locally: bun test desktop/src (407 pass, 0 fail), bun run typecheck in desktop, bun run typecheck:tests, Biome format and lint, cargo fmt --check, cargo clippy --all-targets -- -D warnings, cargo test --locked --lib --bins (1087 + 304 pass).

Not reproduced in the real product

I did not reproduce this in a real Desktop build. The CLI keeps every local stack in one shared config folder, and the machine I worked on also runs an installed OpenBot and other people's stacks. To reproduce, I would have had to make a real rc.10 to rc.11 helm upgrade fail on a live stack. Verification is the tests above, including the fake-CLI test of the native update and repair path.

…it left OpenBot running but not working, instead of giving up at once
…d runs the version it had

A degraded backend whose disk OpenBot found short (or still recovering) now shows the free-space
message at once instead of re-running an update that downloads images and fails there again after
up to ten minutes. The Retry after space is freed runs the update.

When a failed update leaves the backend degraded with its checks failing, the update row no longer
says OpenBot runs the version it had (its services are paused) and says Retry tries the update again.
@davidmckayv

Copy link
Copy Markdown
Contributor

Review. The core fix is right: a degraded stack with an update on record can only be brought back by local update, the old kept case is a subset of the new condition (onInstalledRelease already requires degraded plus an update on record), and updatedIntelligence keeps it to one attempt per Start or Retry. The tests pin the exact command sequence, which is what matters here.

Findings, both fixed on this branch in e211ce7 (plus a merge of main):

  1. desktop/src/LocalIntelligence.tsx:643 (retry condition). A degraded stack whose disk OpenBot found short, or still recovering (found.shortfall, set by checked_when_unhealthy), now re-runs the update before saying anything. Before this PR it showed the free-space message at once. An update that failed because the disk filled while downloading images is a likely way to land here, and each Retry would download again and fail after up to ten minutes before the free-space message appears. Fixed: the retry is skipped while shortfall is set, so the row says to free space, and the Retry after that runs the update. Regression test: "a backend an update left not working on a full disk says so, and updates on the Retry after space is freed" (fails on 2ca85a7, passes now).

  2. desktop/src/LocalIntelligence.tsx:217 (updateFailedSaid). After the update fails on a degraded stack, the update row said "OpenBot couldn't finish updating, so it runs the version it had ... OpenBot tries again the next time it starts", right above "OpenBot is running but not working properly". Its services are paused, so it does not run the version it had, and with this PR Retry is what tries again. Fixed: when the failed update leaves the stack degraded with its checks failing (and the update did not wake it from stopped), the row says "OpenBot couldn't finish updating. It stopped while ... Your data is kept. Retry to try the update again." Every other failure keeps the existing text. Covered by the updated expectations in "an update that stops again is tried once per Start, and Retry tries it once more" and "an update that fails says the step it stopped at and that the data is kept" (both fail on 2ca85a7, pass now).

Checked and fine: a healthy stack (ready, no updateTo) is never updated; a degraded stack with no update on record is not updated; the next app start takes the same path (App.test "a backend whose check fails ..."); the local_eval.rs fake Helm case matches Helm 3 behaviour for a failed release.

bun test desktop/src 412 pass, desktop typecheck and Biome format clean after the merge of main.

…efore it settles not working

Found on Windows, rc.11 to rc.12: an interrupted update left the services at 0 replicas with the
update still prepared and no failed step. After the retried update failed, the first status said
starting and the next degraded. The failed update was forgotten on the starting answer, so the row
kept "so it runs the version it had" over a back end that did not run.

The failed update is now kept while the back end says starting with the update on record, and the
row is decided once it settles. A back end that starts with no update on record is unaffected.
@davidmckayv

Copy link
Copy Markdown
Contributor

Follow-up from a live run on Windows (rc.11 to rc.12): Retry brought the stack back, but on the broken screen the update row still said "so it runs the version it had". The first status after the failed update answered starting and the next degraded, and the failed update was forgotten on the starting answer. Fixed in 36ead0e (desktop/src/LocalIntelligence.tsx, where failedTo is cleared): it is now kept while the back end says starting with the update on record, and the row is decided once it settles. A back end starting with no update on record is unaffected. Regression test "an update that fails again says Retry once the back end settles not working, after a first answer of starting" fails before and passes after, plus a guard test for a plain start. CI green on this head. Not merging yet: the Windows screen gets re-checked on this build first.

This branch has not been deployed

No deployments
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