From 4c817978e657a9fef24d71a6a4026d9173df1af1 Mon Sep 17 00:00:00 2001 From: Phil Pluckthun Date: Tue, 3 Mar 2020 20:45:16 +0000 Subject: [PATCH] Fix partially completed commutative chains Previously when the lowest operation completed, the entire commutative chain would be squashed and deleted. Instead only the completed operations until the next lowest uncompleted operation should be squashed. --- exchanges/graphcache/src/store/data.test.ts | 35 +++++++++++++++++++++ exchanges/graphcache/src/store/data.ts | 18 ++++++++--- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/exchanges/graphcache/src/store/data.test.ts b/exchanges/graphcache/src/store/data.test.ts index e75c93d531..24c6cd207f 100644 --- a/exchanges/graphcache/src/store/data.test.ts +++ b/exchanges/graphcache/src/store/data.test.ts @@ -278,4 +278,39 @@ describe('commutative changes', () => { InMemoryData.initDataState(data, null); expect(InMemoryData.readRecord('Query', 'index')).toBe(1); }); + + it('continues applying optimistic layers even if the first one completes', () => { + InMemoryData.reserveLayer(data, 1); + InMemoryData.reserveLayer(data, 2); + InMemoryData.reserveLayer(data, 3); + InMemoryData.reserveLayer(data, 4); + + InMemoryData.initDataState(data, 1); + InMemoryData.writeRecord('Query', 'index', 1); + InMemoryData.clearDataState(); + + InMemoryData.initDataState(data, null); + expect(InMemoryData.readRecord('Query', 'index')).toBe(1); + + InMemoryData.initDataState(data, 3); + InMemoryData.writeRecord('Query', 'index', 3); + InMemoryData.clearDataState(); + + InMemoryData.initDataState(data, null); + expect(InMemoryData.readRecord('Query', 'index')).toBe(3); + + InMemoryData.initDataState(data, 4); + InMemoryData.writeRecord('Query', 'index', 4); + InMemoryData.clearDataState(); + + InMemoryData.initDataState(data, null); + expect(InMemoryData.readRecord('Query', 'index')).toBe(4); + + InMemoryData.initDataState(data, 2); + InMemoryData.writeRecord('Query', 'index', 2); + InMemoryData.clearDataState(); + + InMemoryData.initDataState(data, null); + expect(InMemoryData.readRecord('Query', 'index')).toBe(4); + }); }); diff --git a/exchanges/graphcache/src/store/data.ts b/exchanges/graphcache/src/store/data.ts index defc85c333..402e80786c 100644 --- a/exchanges/graphcache/src/store/data.ts +++ b/exchanges/graphcache/src/store/data.ts @@ -101,10 +101,20 @@ export const clearDataState = () => { // and is the "first" one and hence blocking all others, we squash all // results and empty the list of commutative keys if (blockingKey === optimisticKey) { - for (let i = data.optimisticOrder.length - 1; i >= commutativeIndex; i--) - squashLayer(data.optimisticOrder[i]); - data.optimisticOrder.length = commutativeIndex; - data.commutativeKeys.clear(); + const squash: number[] = []; + const orderSize = data.optimisticOrder.length; + // Collect all completed, commutative layers until and excluding the first + // pending one that overrides the others + for (let i = commutativeIndex; i < orderSize; i++) { + const layerKey = data.optimisticOrder[i]; + if (!data.refLock[layerKey]) break; + squash.unshift(layerKey); + } + + // Apply all completed, commutative layers + for (let i = 0, l = squash.length; i < l; i++) { + squashLayer(squash[i]); + } } }