Skip to content

Commit e340e2b

Browse files
authored
fix: prevent race condition in KeyValueStore.getAutoSavedValue() (#2193)
This was painful to discover the hard way :( Code to test this: ```js const store = await Actor.openKeyValueStore("test", { forceCloud: true }); const key = "something"; const res = await Promise.all([ store.getAutoSavedValue(key, { foo: [] }), new Promise((r) => setTimeout(r, Math.random() * 1000)).then(() => store.getAutoSavedValue(key, { foo: [] }) ), ]); res[0].foo.push("test"); console.log(res); ``` Run this a few times and at some point you will get two different values in the console.log. (Note that it's using `forceCloud` to make `this.GetValue()` run for a little longer.)
1 parent a2d7f49 commit e340e2b

File tree

1 file changed

+9
-0
lines changed

1 file changed

+9
-0
lines changed

packages/core/src/storages/key_value_store.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,15 @@ export class KeyValueStore {
227227
}
228228

229229
const value = await this.getValue<T>(key, defaultValue);
230+
231+
// The await above could have run in parallel with another call to this function. If the other call finished more quickly,
232+
// the value will in cache at this point, and returning the new fetched value would introduce two different instances of
233+
// the auto-saved object, and only the latter one would be persisted.
234+
// Therefore we re-check the cache here, and if such race condition happened, we drop the fetched value and return the cached one.
235+
if (this.cache.has(key)) {
236+
return this.cache.get(key) as T;
237+
}
238+
230239
this.cache.set(key, value!);
231240
this.ensurePersistStateEvent();
232241

0 commit comments

Comments
 (0)