Skip to content

fix(settings): write pending settings when Settings closes - #2259

Merged
chhoumann merged 2 commits into
masterfrom
fix/settings-close-save
Oct 24, 2026
Merged

chhoumann merged 2 commits into
masterfrom
fix/settings-close-save

Conversation

@chhoumann

@chhoumann chhoumann commented Oct 24, 2026 •

Copy link
Copy Markdown
Owner

Fixes #2213.

This changes product behaviour. Do not merge without review.

What changes for users

Closing Settings now writes any pending QuickAdd settings change to data.json at once. Before, the write waited on a 1 s debounce timer on the main window. The behaviour changes most when Settings is a popout and the main window is hidden or minimised. The OS throttles that window's timers, so the write could land seconds late. #2213 measured more than 3 s in 6 of 8 loaded macOS runs, and more than 15 s once. Until the write landed, a sync client or a crash would see the old settings. Nothing else changes. While Settings stays open, writes stay debounced.

Change

Test

settings-popout-save used to poll data.json for 3 s. It now asserts two things for both the visible and the hidden main window. The write is still pending when the popout closes, so the spec cannot pass because the debounce already fired. And the change is on disk once the write that closing started has finished. No timing budget is left.

Evidence (Linux, isolated instance under a cgroup CPU quota)

  • Without the fix, the write lands 1.06 to 1.81 s after close in 11 probe runs. That includes one run after the main window had been hidden 5.5 minutes, at 30%, 25% and 6% CPU. Linux does not show the macOS multi-second delay. The latency is the debounce plus timer alignment on a hidden window, not CPU starvation.
  • The new spec on master's product code: 4 of 4 runs failed at 12% CPU, and 3 of 3 at 25%.
  • The new spec with the fix: 20 of 20 at 12% CPU, plus 3 of 3 at 25%.
  • pnpm run test (6962 passed) and pnpm run lint pass.

Not verified: the macOS run from #2213. On macOS the write still starts at close, so the throttled timer no longer matters. That conclusion is inferred, not measured on macOS. The unexplained 15 s case there could also have been a write that never landed. This fix covers it if the timer was the cause. It does not cover it if the persist chain itself was stuck.

No migration impact.


Note

Medium Risk
Changes when settings hit disk (product behavior) and touches the core persistSettings path, though it reuses existing flush-on-exit logic rather than a new persistence mechanism.

Overview
Closing QuickAdd Settings now flushes any pending debounced write to data.json immediately, instead of leaving it on the main window’s 1 s timer (which the OS can throttle when Settings is a popout and the main window is hidden).

QuickAddSettingsTab.hide() calls the plugin’s flushPendingSave() after tearing down Svelte views, reusing the same queued persistSettings path as plugin unload/quit. flushPendingSave() is public so the settings tab can invoke it.

The settings-popout-save e2e spec now requires a pending save at close, awaits the persist chain after close, and asserts disk matches in-memory order without a multi-second poll—so the test only passes when close triggers the write.

Reviewed by Cursor Bugbot for commit 8daa994. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Flush pending debounced settings saves when Settings closes

  • QuickAdd.flushPendingSave is no longer private, and QuickAddSettingsTab.hide calls it after the settings views are hidden and destroyed. A debounced settings write now also runs when the tab closes, not only on the timer.
  • Updates the e2e reorder test in settings-popout-save.test.ts to close the settings popout and require the pending save to be flushed before checking on-disk order, removing the 3-second polling loop.

Macroscope summarized 8daa994.

Summary by CodeRabbit

  • Bug Fixes
    • Changes made in the Settings popout are now saved when the popout closes, including when it closes before the usual delayed save occurs. This helps ensure your latest settings are retained and match what you see in the app.

…osed

The spec polled data.json for 3 s after the popout closed. The write waits
on a 1 s debounce on the main window's timer, which the OS throttles while
that window is hidden, so under load it often landed later (#2213). Assert
instead that the change is pending when the popout closes and on disk once
the write that closing starts has finished.

Refs #2213
A settings change is written by a 1 s debounce on the main window's timer.
While a Settings popout covers a hidden main window, the OS throttles that
timer, and under load the write landed seconds late, once more than 15 s.
Closing Settings now writes the pending change at once.

Fixes #2213
@chhoumann chhoumann linked an issue Oct 24, 2026 that may be closed by this pull request
@coderabbitai

coderabbitai Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 022e65d6-f784-4b5b-a4b3-0076c1a3993e
Commits

Reviewing files that changed from the base of the PR and between 9d132a3 and 8daa994.

Files selected for processing: 3
  • src/main.ts
  • src/quickAddSettingsTab.ts
  • tests/e2e/settings-popout-save.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 4 remain after this review.

Walkthrough

The Settings popout now starts a pending-save flush when it closes. The end-to-end test checks that a save was pending at close and that the saved order matches the in-memory order.

Changes: Settings popout persistence

Layer / File(s) Summary
Flush pending saves on close
src/main.ts, src/quickAddSettingsTab.ts
flushPendingSave is now public. QuickAddSettingsTab.hide() invokes it after teardown and mounted-view cleanup, without awaiting it.
Verify the persisted order
tests/e2e/settings-popout-save.test.ts
The test records whether a save was pending at close, awaits persistChain, and checks the on-disk order against the captured in-memory order.

Priority: Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Possibly related PRs

  • chhoumann/quickadd#2253: It establishes the settings persistence path that this change flushes when the Settings popout closes.
Merge Risk: Minimal · up to 8daa9

No actionable merge-blocking risk is established by the supplied evidence.

Pre-merge checks: Passed 5
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: flushing pending settings writes when Settings closes.
Linked Issues check Passed #2213 requires the Settings-popout change to reach data.json after close and requires an automated test that verifies the resulting state without an unsuitable fixed polling window. `QuickAddSetting…
Out of Scope Changes check Passed The changed files are limited to the save method visibility, the Settings tab close path, and the related settings-popout-save e2e test. Each change supports #2213 or verifies its required behavior.…
Docstring Coverage Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 3…
Full details: Linked Issues check

Explanation

#2213 requires the Settings-popout change to reach data.json after close and requires an automated test that verifies the resulting state without an unsuitable fixed polling window. QuickAddSettingsTab.hide() now calls flushPendingSave() after view teardown. The method starts the existing queued persistSettings path. The updated e2e test confirms that the save is pending at close, awaits persistChain, and compares disk order with in-memory order for visible and hidden main windows. The reported load-tested runs also support the fix.

Full details: Out of Scope Changes check

Explanation

The changed files are limited to the save method visibility, the Settings tab close path, and the related settings-popout-save e2e test. Each change supports #2213 or verifies its required behavior. No unrelated product behavior is introduced.

Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 3 files.

Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

❤️ Share

A rabbit closes Settings with care,
A pending save is sent from there.
The order waits on disk to land,
Checked against the order close at hand.
Then hops away, content and grand.

Comment @coderabbitai help to get the list of available commands.

@chhoumann
chhoumann merged commit 0d57fe9 into master Oct 24, 2026
17 of 22 checks passed
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.

e2e: settings popout save lands late or not at all under load

1 participant