From 3f5d33afb19cf0c99269445120f5e985806241ad Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Thu, 7 Mar 2024 14:43:26 +0000 Subject: [PATCH] fix(store-sync): track changed records together in zustand (#2387) --- .changeset/sharp-students-compare.md | 5 +++++ .../src/zustand/createStorageAdapter.ts | 22 +++++++++++-------- 2 files changed, 18 insertions(+), 9 deletions(-) create mode 100644 .changeset/sharp-students-compare.md diff --git a/.changeset/sharp-students-compare.md b/.changeset/sharp-students-compare.md new file mode 100644 index 0000000000..e4e59de3c1 --- /dev/null +++ b/.changeset/sharp-students-compare.md @@ -0,0 +1,5 @@ +--- +"@latticexyz/store-sync": patch +--- + +Fixes an issue with Zustand store sync where multiple updates to a record for a key in the same block did not get tracked and applied properly. diff --git a/packages/store-sync/src/zustand/createStorageAdapter.ts b/packages/store-sync/src/zustand/createStorageAdapter.ts index b8bb5f6974..8a649c0216 100644 --- a/packages/store-sync/src/zustand/createStorageAdapter.ts +++ b/packages/store-sync/src/zustand/createStorageAdapter.ts @@ -20,8 +20,8 @@ export function createStorageAdapter({ return async function zustandStorageAdapter({ blockNumber, logs }) { // TODO: clean this up so that we do one store write per block - const updatedIds: string[] = []; - const deletedIds: string[] = []; + // record id => is deleted + const touchedIds: Map = new Map(); const rawRecords = { ...store.getState().rawRecords }; @@ -54,7 +54,7 @@ export function createStorageAdapter({ encodedLengths: log.args.encodedLengths, dynamicData: log.args.dynamicData, }; - updatedIds.push(id); + touchedIds.set(id, false); } else if (log.eventName === "Store_SpliceStaticData") { debug("splicing static data", { namespace: table.namespace, @@ -75,7 +75,7 @@ export function createStorageAdapter({ ...previousRecord, staticData, }; - updatedIds.push(id); + touchedIds.set(id, false); } else if (log.eventName === "Store_SpliceDynamicData") { debug("splicing dynamic data", { namespace: table.namespace, @@ -98,7 +98,7 @@ export function createStorageAdapter({ encodedLengths, dynamicData, }; - updatedIds.push(id); + touchedIds.set(id, false); } else if (log.eventName === "Store_DeleteRecord") { debug("deleting record", { namespace: table.namespace, @@ -107,14 +107,18 @@ export function createStorageAdapter({ log, }); delete rawRecords[id]; - deletedIds.push(id); + touchedIds.set(id, true); } } - if (!updatedIds.length && !deletedIds.length) return; + if (!touchedIds.size) return; - const records = { - ...Object.fromEntries(Object.entries(store.getState().records).filter(([id]) => !deletedIds.includes(id))), + const updatedIds = Array.from(touchedIds.keys()).filter((id) => touchedIds.get(id) === false); + const deletedIds = Array.from(touchedIds.keys()).filter((id) => touchedIds.get(id) === true); + + const previousRecords = store.getState().records; + const records: typeof previousRecords = { + ...Object.fromEntries(Object.entries(previousRecords).filter(([id]) => !deletedIds.includes(id))), ...Object.fromEntries( updatedIds .map((id) => {