Skip to content

reliability(mainmenu): SafeWrite migration — 4 client-side save sites#289

Merged
CoreyRDean merged 1 commit into
developfrom
reliability/mainmenu-safewrite
May 26, 2026
Merged

reliability(mainmenu): SafeWrite migration — 4 client-side save sites#289
CoreyRDean merged 1 commit into
developfrom
reliability/mainmenu-safewrite

Conversation

@CoreyRDean
Copy link
Copy Markdown
Collaborator

Summary

Closes the client-side counterpart to PR #279's server/editor SafeWrite sweep. 4 sites in MainMenu.bb that wrote directly to production files now use the established atomic SafeWriteOpen/SafeWriteCommit pair, with .bak retention on a 1-cycle recovery window.

Non-technical

A crash, disk-full, or process kill during one of these client-side save operations previously left the file empty or partially-written. The user would see locked-out login pre-fill, broken project load, or a corrupted partial download. After this PR, any of those failure modes leaves the prior file intact.

Sites migrated (4)

File Line Function Purpose
Data\Last Username.dat 857 LogIn() Username/password cache for login pre-fill
Data\Game Data\Misc.dat 1500 LogIn() Music checkbox update (in login screen settings)
Data\Game Data\Misc.dat 3694 GameOptionsMenu() Music checkbox update (in in-game options)
SaveTo$ (HTTP downloader) 3847 Inside DownloadFile() Atomic only on BytesIn = BytesToRead; partial downloads abort the temp

The downloader path (site 4) is the most-complex: it writes incrementally in a read-bytes loop and only commits if the full content-length arrived. Partial downloads (EOF before completion, TCP drop, user cancellation) abort the temp and leave the prior file (if any) intact. Same shape as RC Terrain Editor's pad_or_optimize site already migrated in #279.

Acceptance criteria

  • All 4 sites use SafeWriteOpen/SafeWriteCommit (or SafeWriteAbort on partial-download path)
  • Logging.bb is included in Client.bb (verified — no new include needed)
  • Two MMFinal$/MMTemp$ locals don't conflict (different functions)
  • compile.bat -t clean
  • All 26 tests pass (on retry; documented OnlinePlayerChainTest intermittent flake)

Test plan

  • compile.bat -t exit 0
  • test.bat — 26/26 pass (retry needed for the documented OnlinePlayerChainTest flake; passes on second run)

Trade-offs / deferred

  • Client-side MainMenu SafeWrite is now complete. Any other client/UI saves discovered in a future per-Tools or per-MainMenu audit would land in a separate PR.
  • OnlinePlayerChainTest CI flake (~30% rate per the saved memory) remains an open investigation item; not caused by this PR.

🤖 Generated with Claude Code

Closes the client-side counterpart to the #279 server/editor SafeWrite
sweep. 4 sites in MainMenu.bb that wrote directly to production
files now use the established atomic SafeWriteOpen/SafeWriteCommit
pair, with .bak retention on a 1-cycle recovery window.

## Sites migrated (4)

1. **`Data\Last Username.dat`** (line 857, inside `LogIn()`) -- the
   username/password cache. WriteFile failure would leave the cache
   empty, locking the user out of the pre-fill on next login (forcing
   manual re-entry).

2. **`Data\Game Data\Misc.dat`** (line 1500, inside `LogIn()`) --
   Music checkbox update. Empty Misc.dat would cause the next launch
   to read "no game name, no version" and fail project load.

3. **`Data\Game Data\Misc.dat`** (line 3694, inside
   `GameOptionsMenu()`) -- duplicate of site 2 in the in-game
   options screen. Same fix.

4. **`SaveTo$`** (line 3847, inside the HTTP downloader) -- the
   most-complex site. The write happens incrementally in a read-
   bytes loop with a content-length-completion check. The temp is
   only promoted on `BytesIn = BytesToRead`; partial downloads
   (EOF before completion, TCP drop, user cancellation) abort the
   temp and leave the prior on-disk file (if any) intact.

   This is meaningful because the downloader fetches game-update
   files and a corrupted partial write previously could leave a
   half-downloaded .dat in place; the next launch would read it
   and either crash or run with corrupt data.

## Lifecycle differences from server SafeWrite migration

* MainMenu.bb is included only by Client.bb, which already includes
  Logging.bb (verified). No new include needed.
* `LogIn()` and `GameOptionsMenu()` are different functions, so the
  `Local MMFinal$ / MMTemp$` declarations don't conflict despite
  both Misc.dat sites using the same local names.
* The downloader path needs `SafeWriteAbort` on the partial path
  (BytesIn != BytesToRead) -- distinct from the success-path
  `SafeWriteCommit`. Pattern matches the RC Terrain Editor's
  `pad_or_optimize` site already migrated in PR #279.

## Verification

* `compile.bat -t` clean (Client compiles).
* `test.bat` -- 26/26 pass on retry. First run hit the documented
  OnlinePlayerChainTest CI/local intermittent flake (~30% rate per
  the feedback_blitzforge_test_handle_object_gc memory).

## Deferred

The client-side SafeWrite migration is now complete for MainMenu.bb.
Other remaining client/UI writes (if any) would be discovered by the
next per-Tools or per-MainMenu audit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@CoreyRDean CoreyRDean requested a review from a team as a code owner May 26, 2026 17:03
@CoreyRDean CoreyRDean closed this May 26, 2026
@CoreyRDean CoreyRDean reopened this May 26, 2026
@CoreyRDean CoreyRDean merged commit 86bae43 into develop May 26, 2026
1 of 2 checks passed
@CoreyRDean CoreyRDean deleted the reliability/mainmenu-safewrite branch May 26, 2026 17:07
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6c31d9ceff

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/Modules/MainMenu.bb
Comment on lines +3906 to +3907
If BytesIn = BytesToRead
SafeWriteCommit%(DLTemp$, SaveTo$, Save)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Propagate SafeWriteCommit failure in DownloadFile

DownloadFile ignores the return value of SafeWriteCommit%, so a full network read is reported as success even when the local promote step fails (e.g., destination not writable or copy failure). In that case this function still returns BytesIn > 0, and its callers treat non-zero as a successful download, which can make them continue with stale/missing on-disk data. Capture the commit result and convert failure to a 0 return (and/or abort path) so call sites can handle it as a failed download.

Useful? React with 👍 / 👎.

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.

1 participant