Skip to content

Commit

Permalink
Fix partially completed commutative chains
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
kitten committed Mar 3, 2020
1 parent 1359234 commit 4c81797
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 4 deletions.
35 changes: 35 additions & 0 deletions exchanges/graphcache/src/store/data.test.ts
Expand Up @@ -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);
});
});
18 changes: 14 additions & 4 deletions exchanges/graphcache/src/store/data.ts
Expand Up @@ -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]);
}
}
}

Expand Down

0 comments on commit 4c81797

Please sign in to comment.