Conversation
1a58c9d to
2ca7187
Compare
|
@launchdarkly/js-sdk-common size report |
|
@launchdarkly/js-sdk-common size report |
|
@launchdarkly/js-client-sdk-common size report |
|
@launchdarkly/js-client-sdk size report |
88698a2 to
6e8b65a
Compare
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 10ebf5c. Configure here.
53f796d to
bb5c1b8
Compare
bb5c1b8 to
8b35e1e
Compare
There was a problem hiding this comment.
Devin Review found 1 new potential issue.
1 flag not posted on this PR by your GitHub settings — view it in Devin Review. (Configure)
| Object.entries(this._allData).forEach(([namespace, items]) => { | ||
| snapshot[namespace] = { ...items }; | ||
| }); |
There was a problem hiding this comment.
🟡 Recovery snapshot changes during serialization
When recovery serializes a segment, getAllRaw() shares its item object with the live store. replacer mutates that object, so the snapshot changes after capture.
Learn more
A raw snapshot copies each namespace map, but it retains references to the original flags and segments. Serializing a segment with generated target sets mutates its object in replacer. That changes both the supposedly fixed snapshot and the live in-memory store when the snapshot is passed to a persistence write. The same alias also lets any later in-place mutation of a stored item change the captured data.
Example: A segment has generated_includedSet = new Set(['alice']). After getAllRaw(), serializing that snapshot adds included: ['alice'] and deletes generated_includedSet on both the snapshot and the live segment; the captured object no longer has its original fields.
Recommended fix: Copy the item objects and nested mutable data when taking the snapshot, preserving Set values and other internal data types used by evaluation. Verify that passing the snapshot through sortDataSet does not mutate the live store or the captured data.
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
This does not affect correctness AFAIK
Summary
This is the wrapper-plumbing layer of the persistent store write-back recovery stack (follows #2009; the recovery engine itself lands in the next PR).
PersistentDataStoreWrappernow forwards the underlying store'sinitandupserterrors to its callbacks instead of dropping them. A failed mirrored write is the signal the transactional store will use to detect an outage.isStoreAvailableonly when the underlyingPersistentDataStoreimplements it, so recovery logic can use the method's presence to decide whether it can poll for the store coming back.InMemoryFeatureStore.getAllRaw()returns a snapshot of the full data set, including deletion tombstones, for writing the in-memory state back into a recovered persistent store.initnow populates the all-items cache with tombstones filtered out, matching the filtering the cache-miss path applies. Write-backinitpayloads can contain tombstones, andall()must never return them from the warm cache.Note
Overview
Persistent store wrapper plumbing for write-back recovery:
initandupsertnow forward underlying store errors to their callbacks instead of swallowing them. On a failedinit, the wrapper logs, clears item/all caches, and leaves_isInitializedfalse so reads andinitialized()reflect persistence, not rejected in-memory data.isStoreAvailableis exposed on the wrapper only when the corePersistentDataStoreimplements it, so recovery can detect poll support.InMemoryFeatureStore.getAllRaw()adds an internal immutable snapshot of every kind, including deletion tombstones, for full-state write-back to a recovered store.Cache fix on
init: the warmall()cache is populated with tombstones filtered out, matching cache-miss behavior soall()never returns deleted items after init payloads that include tombstones.Tests cover raw snapshots, cached
all()with deletes, init/upsert error propagation, failed-init cache clearing, andisStoreAvailableforwarding.Reviewed by Cursor Bugbot for commit 8b35e1e. Bugbot is set up for automated code reviews on this repo. Configure here.