-
Notifications
You must be signed in to change notification settings - Fork 5.5k
fix: cp-12.22.3 Fix frequent writes from CronjobController #34413
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
🔍 Existing Issues For ReviewYour pull request is modifying functions with the following pre-existing issues: 📄 File: app/scripts/background.js
Did you find this useful? React with a 👍 or 👎 |
✨ Files requiring CODEOWNER review ✨🫰 @MetaMask/snaps-devs (2 files, +17 -1)
|
Prevent frequent high-volume writes caused by state updates from the CronjobController. The controller state includes an event with a timestamp that can be updated very frequently if the user has a snap installed with a scheduled recurring event with a short interval. It can even run while the wallet is otherwise idle, causing the entirety of wallet state to be written to disk repeatedly. We have temporarily mitigated the problem by moving the CronjobController state to a new top-level storage key, so that it can be written to independently of other state. This controller's state is very small and should not cause any significant amount of write volume.
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** This patches the cronjob controller to add `stateManager` support. [](https://codespaces.new/MetaMask/metamask-extension/pull/34414?quickstart=1) ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: ## **Related issues** Fixes: ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.
ff0a241 to
826ea86
Compare
Builds ready [1b2abad]
UI Startup Metrics (1238 ± 52 ms)
Benchmark value 210 exceeds gate value 10 for chrome browserify home mean backgroundConnect Benchmark value 4 exceeds gate value 1 for chrome browserify home mean initialActions Benchmark value 851 exceeds gate value 830 for chrome browserify home mean loadScripts Benchmark value 43 exceeds gate value 41 for chrome browserify home p95 domInteractive Benchmark value 225 exceeds gate value 18 for chrome browserify home p95 backgroundConnect Benchmark value 16 exceeds gate value 1.2 for chrome browserify home p95 initialActions Benchmark value 2412 exceeds gate value 2192 for chrome webpack home mean uiStartup Benchmark value 1915 exceeds gate value 1711 for chrome webpack home mean load Benchmark value 1908 exceeds gate value 1704 for chrome webpack home mean domContentLoaded Benchmark value 11 exceeds gate value 7 for chrome webpack home mean initialActions Benchmark value 1899 exceeds gate value 1699 for chrome webpack home mean loadScripts Benchmark value 2629 exceeds gate value 2454 for chrome webpack home p95 uiStartup Benchmark value 2245 exceeds gate value 2030 for chrome webpack home p95 load Benchmark value 2242 exceeds gate value 2005 for chrome webpack home p95 domContentLoaded Benchmark value 72 exceeds gate value 57 for chrome webpack home p95 domInteractive Benchmark value 345 exceeds gate value 334 for chrome webpack home p95 firstPaint Benchmark value 29 exceeds gate value 7 for chrome webpack home p95 initialActions Benchmark value 2239 exceeds gate value 1970 for chrome webpack home p95 loadScripts Benchmark value 1498 exceeds gate value 1405 for firefox browserify home mean uiStartup Benchmark value 1290 exceeds gate value 1245 for firefox browserify home mean load Benchmark value 1290 exceeds gate value 1239 for firefox browserify home mean domContentLoaded Benchmark value 27 exceeds gate value 25 for firefox browserify home mean backgroundConnect Benchmark value 29 exceeds gate value 25 for firefox browserify home mean firstReactRender Benchmark value 19 exceeds gate value 11 for firefox browserify home mean getState Benchmark value 5 exceeds gate value 1 for firefox browserify home mean initialActions Benchmark value 1267 exceeds gate value 1230 for firefox browserify home mean loadScripts Benchmark value 10 exceeds gate value 9 for firefox browserify home mean setupStore Benchmark value 1792 exceeds gate value 1660 for firefox browserify home p95 uiStartup Benchmark value 217 exceeds gate value 195 for firefox browserify home p95 domInteractive Benchmark value 167 exceeds gate value 24 for firefox browserify home p95 getState Benchmark value 26 exceeds gate value 2 for firefox browserify home p95 initialActions Benchmark value 1779 exceeds gate value 1615 for firefox webpack home mean uiStartup Benchmark value 1488 exceeds gate value 1380 for firefox webpack home mean load Benchmark value 1487 exceeds gate value 1380 for firefox webpack home mean domContentLoaded Benchmark value 29 exceeds gate value 26 for firefox webpack home mean backgroundConnect Benchmark value 54 exceeds gate value 38 for firefox webpack home mean firstReactRender Benchmark value 13 exceeds gate value 1 for firefox webpack home mean initialActions Benchmark value 1463 exceeds gate value 1360 for firefox webpack home mean loadScripts Benchmark value 23 exceeds gate value 13 for firefox webpack home mean setupStore Benchmark value 2239 exceeds gate value 1935 for firefox webpack home p95 uiStartup Benchmark value 1808 exceeds gate value 1660 for firefox webpack home p95 load Benchmark value 1807 exceeds gate value 1660 for firefox webpack home p95 domContentLoaded Benchmark value 218 exceeds gate value 156 for firefox webpack home p95 domInteractive Benchmark value 53 exceeds gate value 49 for firefox webpack home p95 backgroundConnect Benchmark value 63 exceeds gate value 50 for firefox webpack home p95 firstReactRender Benchmark value 38 exceeds gate value 32 for firefox webpack home p95 getState Benchmark value 64 exceeds gate value 2 for firefox webpack home p95 initialActions Benchmark value 1780 exceeds gate value 1630 for firefox webpack home p95 loadScripts Benchmark value 113 exceeds gate value 28 for firefox webpack home p95 setupStore Sum of mean exceeds: 1828ms | Sum of p95 exceeds: 2469.8ms Sum of all benchmark exceeds: 4297.8ms Bundle size diffs [🚨 Warning! Bundle size has increased!]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Cronjob State Loss Due to Async Storage Errors
The CronjobControllerStorageManager.set() method uses a fire-and-forget pattern for browser.storage.local.set() operations, calling it asynchronously without awaiting and silently swallowing errors with .catch(console.error). This leads to silent data loss: the CronjobController assumes state is persisted even if the storage operation fails (e.g., due to quota limits), causing in-memory state to diverge from persisted state and resulting in lost cronjob state on restart without any indication of failure.
app/scripts/lib/CronjobControllerStorageManager.ts#L49-L57
metamask-extension/app/scripts/lib/CronjobControllerStorageManager.ts
Lines 49 to 57 in 123a239
| */ | |
| set(data: Json) { | |
| if (!this.#initialized) { | |
| throw new Error('CronjobControllerStorageManager not yet initialized'); | |
| } | |
| browser.storage.local | |
| .set({ [CronjobControllerStorageKey]: data }) | |
| .catch(console.error); | |
| } |
Was this report helpful? Give feedback by reacting with 👍 or 👎
Builds ready [123a239]
UI Startup Metrics (1252 ± 71 ms)
Benchmark value 1074 exceeds gate value 1070 for chrome browserify home mean load Benchmark value 1067 exceeds gate value 1061 for chrome browserify home mean domContentLoaded Benchmark value 209 exceeds gate value 10 for chrome browserify home mean backgroundConnect Benchmark value 4 exceeds gate value 1 for chrome browserify home mean initialActions Benchmark value 865 exceeds gate value 830 for chrome browserify home mean loadScripts Benchmark value 224 exceeds gate value 18 for chrome browserify home p95 backgroundConnect Benchmark value 16 exceeds gate value 1.2 for chrome browserify home p95 initialActions Benchmark value 947 exceeds gate value 940 for chrome browserify home p95 loadScripts Benchmark value 2327 exceeds gate value 2192 for chrome webpack home mean uiStartup Benchmark value 1829 exceeds gate value 1711 for chrome webpack home mean load Benchmark value 1818 exceeds gate value 1704 for chrome webpack home mean domContentLoaded Benchmark value 49 exceeds gate value 40 for chrome webpack home mean backgroundConnect Benchmark value 8 exceeds gate value 7 for chrome webpack home mean initialActions Benchmark value 1810 exceeds gate value 1699 for chrome webpack home mean loadScripts Benchmark value 2539 exceeds gate value 2454 for chrome webpack home p95 uiStartup Benchmark value 2123 exceeds gate value 2030 for chrome webpack home p95 load Benchmark value 2101 exceeds gate value 2005 for chrome webpack home p95 domContentLoaded Benchmark value 288 exceeds gate value 90 for chrome webpack home p95 backgroundConnect Benchmark value 28 exceeds gate value 7 for chrome webpack home p95 initialActions Benchmark value 2092 exceeds gate value 1970 for chrome webpack home p95 loadScripts Benchmark value 1467 exceeds gate value 1405 for firefox browserify home mean uiStartup Benchmark value 1265 exceeds gate value 1245 for firefox browserify home mean load Benchmark value 1264 exceeds gate value 1239 for firefox browserify home mean domContentLoaded Benchmark value 114 exceeds gate value 110 for firefox browserify home mean domInteractive Benchmark value 29 exceeds gate value 25 for firefox browserify home mean backgroundConnect Benchmark value 28 exceeds gate value 25 for firefox browserify home mean firstReactRender Benchmark value 12 exceeds gate value 11 for firefox browserify home mean getState Benchmark value 5 exceeds gate value 1 for firefox browserify home mean initialActions Benchmark value 1241 exceeds gate value 1230 for firefox browserify home mean loadScripts Benchmark value 12 exceeds gate value 9 for firefox browserify home mean setupStore Benchmark value 1776 exceeds gate value 1660 for firefox browserify home p95 uiStartup Benchmark value 335 exceeds gate value 195 for firefox browserify home p95 domInteractive Benchmark value 56 exceeds gate value 55 for firefox browserify home p95 firstReactRender Benchmark value 41 exceeds gate value 24 for firefox browserify home p95 getState Benchmark value 21 exceeds gate value 2 for firefox browserify home p95 initialActions Benchmark value 38 exceeds gate value 27 for firefox browserify home p95 setupStore Benchmark value 1773 exceeds gate value 1615 for firefox webpack home mean uiStartup Benchmark value 1497 exceeds gate value 1380 for firefox webpack home mean load Benchmark value 1497 exceeds gate value 1380 for firefox webpack home mean domContentLoaded Benchmark value 101 exceeds gate value 100 for firefox webpack home mean domInteractive Benchmark value 32 exceeds gate value 26 for firefox webpack home mean backgroundConnect Benchmark value 53 exceeds gate value 38 for firefox webpack home mean firstReactRender Benchmark value 9 exceeds gate value 1 for firefox webpack home mean initialActions Benchmark value 1473 exceeds gate value 1360 for firefox webpack home mean loadScripts Benchmark value 15 exceeds gate value 13 for firefox webpack home mean setupStore Benchmark value 2142 exceeds gate value 1935 for firefox webpack home p95 uiStartup Benchmark value 1854 exceeds gate value 1660 for firefox webpack home p95 load Benchmark value 1854 exceeds gate value 1660 for firefox webpack home p95 domContentLoaded Benchmark value 286 exceeds gate value 156 for firefox webpack home p95 domInteractive Benchmark value 63 exceeds gate value 49 for firefox webpack home p95 backgroundConnect Benchmark value 64 exceeds gate value 50 for firefox webpack home p95 firstReactRender Benchmark value 28 exceeds gate value 2 for firefox webpack home p95 initialActions Benchmark value 1826 exceeds gate value 1630 for firefox webpack home p95 loadScripts Benchmark value 35 exceeds gate value 28 for firefox webpack home p95 setupStore Sum of mean exceeds: 1428ms | Sum of p95 exceeds: 2128.8ms Sum of all benchmark exceeds: 3556.8ms Bundle size diffs [🚨 Warning! Bundle size has increased!]
|
|
Tested and LGTM ! |
Description
Prevent frequent high-volume writes caused by state updates from the CronjobController. The controller state includes an event with a timestamp that can be updated very frequently if the user has a snap installed with a scheduled recurring event with a short interval. It can even run while the wallet is otherwise idle, causing the entirety of wallet state to be written to disk repeatedly.
We have temporarily mitigated the problem by moving the CronjobController state to a new top-level storage key, so that it can be written to independently of other state. This controller's state is very small and should not cause any significant amount of write volume.
Changelog
CHANGELOG entry: Prevent frequent writes while the wallet UI is closed
Related issues
Fixes: #33879
Manual testing steps
To test that cronjobs work correctly:
You can restart the client in between steps to ensure persistence works
To test that write volume has been reduced:
Screenshots/Recordings
Before
After
Pre-merge author checklist
Pre-merge reviewer checklist