Preserve every config change during rapid storage updates - #1037
Preserve every config change during rapid storage updates#1037PeterDaveHello wants to merge 1 commit into
Conversation
📝 WalkthroughWalkthroughThe change extracts configuration storage-change handling into ChangesConfig storage synchronization
Estimated code review effort: 2 (Simple) | ~10 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
Greptile SummaryThe PR replaces stale-closure config merges with functional state updates and keeps the storage listener stable across config changes.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains, and the previously requested disabled-session-filter coverage is now present.
|
| Filename | Overview |
|---|---|
| src/hooks/config-storage-listener.mjs | Extracts storage patch processing and uses functional updates while preserving session-filter behavior. |
| src/hooks/use-config.mjs | Installs the extracted listener and limits effect recreation to changes in the session-filter option. |
| tests/unit/hooks/config-storage-listener.test.mjs | Covers queued config merges and session-only or mixed events with filtering both enabled and disabled. |
Sequence Diagram
sequenceDiagram
participant Storage as Browser storage
participant Listener as Config storage listener
participant State as Config state
Storage->>Listener: onChanged(changes)
alt Session-only and filtering enabled
Listener-->>Storage: Ignore event
else Update accepted
Listener->>State: "setConfig(current => merge(current, changes))"
State-->>Listener: Latest queued config preserved
end
Reviews (2): Last reviewed commit: "Preserve every config change during rapi..." | Re-trigger Greptile
PR Summary by QodoFix config storage race with functional updates and stable listener
AI Description
Diagram
High-Level Assessment
Files changed (3)
|
Code Review by Qodo🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)
Great, no issues found!Qodo reviewed your code and found no material issues that require reviewTo customize comments, go to the Qodo configuration screen, or learn more in the docs. |
Storage callbacks can queue before Preact refreshes the hook closure. A second object update built from that stale snapshot can overwrite the change queued immediately before it. Use functional state updates and keep the listener stable until its session-filter option changes. Cover both filtering modes in tests.
182115c to
3bd3e61
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Refactors the configuration storage onChanged handler into a reusable listener factory and updates the React hook to use it, with new unit tests verifying queue-safe merging and session filtering behavior.
Changes:
- Added
createConfigStorageListenerto centralize storage-change -> config-update logic. - Updated
useConfigto use a functionalsetConfigupdate (avoids staleconfigclosures) and reduced effect re-subscriptions. - Added unit tests covering merge behavior and session filtering modes.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| tests/unit/hooks/config-storage-listener.test.mjs | Adds unit tests validating listener merge semantics and session filtering behavior. |
| src/hooks/use-config.mjs | Switches to shared storage listener and updates effect dependencies. |
| src/hooks/config-storage-listener.mjs | Introduces a factory for the storage change listener using functional state updates. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const configUpdate = {} | ||
| for (const key of Object.keys(changes)) { | ||
| configUpdate[key] = changes[key].newValue | ||
| } | ||
| setConfig((currentConfig) => ({ ...currentConfig, ...configUpdate })) |
| if (ignoreSession && Object.keys(changes).length === 1 && 'sessions' in changes) return | ||
|
|
||
| const configUpdate = {} | ||
| for (const key of Object.keys(changes)) { |
Problem
useConfigmerged each storage event into theconfigobject captured by the current render. Multiple storage callbacks can run before Preact refreshes that closure, so a later object update could overwrite an earlier queued change.The effect also removed and re-added the storage listener after every config update because
configwas in its dependency list.Changes
Validation
node --test tests/unit/hooks/config-storage-listener.test.mjs— 4 tests passed.node --checkpassed for the changed JavaScript modules.