Bound persistentIds in their own store and mirror the client's clears - #9
Draft
cassiostp wants to merge 1 commit into
Draft
Bound persistentIds in their own store and mirror the client's clears#9cassiostp wants to merge 1 commit into
cassiostp wants to merge 1 commit into
Conversation
cassiostp
force-pushed
the
cs/bounded-persistent-ids
branch
from
August 13, 2026 21:28
4b71837 to
e3dbea4
Compare
The persistentIds list in the shared config.json only ever grows: the client clears its in-memory copy when the MCS login response acks the ids, but the disk copy was append-only. Field reports show 35MB+ config files rewritten synchronously on every notification (~200ms main-process block each) and the full list uploaded to Google on every connect. Persistence is now a mirror of the client's 'persistentIds' snapshot event (push-receiver 2.1.8) in its own config file, push-receiver.json, capped at the most recent 5000 entries, so notification writes stop rewriting the host app's shared config and the file cannot regrow. A one-time idempotent migration trims the shared list into the new file and deletes the old key; hosts can run it early via the exported migratePersistentIds() before their own config traffic starts. The legacy behavior remains selectable per START_NOTIFICATION_SERVICE via fcmConfig.persistentIds (renderer payload wins over the static setup option), so a host can revert storage modes with a web deploy. The module-scope Config was made lazy: its constructor rewrites the whole config file, which cost a full-file write at require() time. Also guards webContents.send calls with isDestroyed() and tolerates missing credentials on the started short-circuit.
cassiostp
force-pushed
the
cs/bounded-persistent-ids
branch
from
August 17, 2026 18:28
e3dbea4 to
3c1ccfe
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
persistentIds in the shared config.json only ever grow: the client clears its in-memory copy when the MCS login response acks the ids, but the disk copy was append-only, and every notification rewrote the whole 35MB+ file synchronously (~200ms main-process block; superhuman/desktop CLI-2311, ~54k desktop devices receive >100 pushes/day).
The renderer payload is the only switch: when
fcmConfig.persistentIdsonSTART_NOTIFICATION_SERVICEsaysstorage: 'v2', persistence becomes a dumb mirror of the client'spersistentIdssnapshot event (push-receiver 2.1.8, superhuman/push-receiver#16 must merge and publish first) in its own file,push-receiver.json, capped (maxPersistedIds, default 5000; desktop will pass 20000 from a LaunchDarkly flag). The first v2 start runs ahas()-guarded idempotent migration that trims the shared list into the new file and deletes the old key. With no payload, behavior is byte-for-byte today's legacy append — a bare package bump changes nothing, activation and same-day revert are both a flag flip, andsetup()'s signature is unchanged from master.Worth a close look: the module-scope
new Config()is now lazy (electron-config's constructor rewrites the entire file — a full 35MB write at require() time on bloated configs);webContents.sendgoes through oneisDestroyed()-guarded helper; thestartedshort-circuit tolerates missing credentials. Worst-case failure of the cap is redelivery of ids beyond the newest entries — duplicate notifications after a restart, never missed ones; desktop is adding alog.duplicate_notificationmetric to watch exactly that. yarn.lock intentionally untouched — it regenerates once push-receiver 2.1.8 is on the registry. Tests:yarn jest(new; the repo had no test setup).🤖 Generated with Claude Code