Skip to content

Commit

Permalink
Reapply remaining layers in removeOptimistic by rerunning transactions.
Browse files Browse the repository at this point in the history
  • Loading branch information
benjamn committed Jan 17, 2019
1 parent acca75c commit 531aa32
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 21 deletions.
12 changes: 8 additions & 4 deletions packages/apollo-cache-inmemory/src/__tests__/recordingCache.ts
Expand Up @@ -3,6 +3,10 @@ import { ObjectCache } from '../objectCache';
import { NormalizedCacheObject } from '../types';

describe('OptimisticCacheLayer', () => {
function makeLayer(root: ObjectCache) {
return new OptimisticCacheLayer('whatever', root, () => {});
}

describe('returns correct values during recording', () => {
const data = {
Human: { __typename: 'Human', name: 'Mark' },
Expand All @@ -15,9 +19,9 @@ describe('OptimisticCacheLayer', () => {

const underlyingCache = new ObjectCache(data);

let cache = new OptimisticCacheLayer('whatever', underlyingCache);
let cache = makeLayer(underlyingCache);
beforeEach(() => {
cache = new OptimisticCacheLayer('whatever', underlyingCache);
cache = makeLayer(underlyingCache);
});

it('should passthrough values if not defined in recording', () => {
Expand Down Expand Up @@ -52,11 +56,11 @@ describe('OptimisticCacheLayer', () => {
};

const underlyingCache = new ObjectCache(data);
let cache = new OptimisticCacheLayer('whatever', underlyingCache);
let cache = makeLayer(underlyingCache);
let recording: NormalizedCacheObject;

beforeEach(() => {
cache = new OptimisticCacheLayer('whatever', underlyingCache);
cache = makeLayer(underlyingCache);
cache.set('Human', dataToRecord.Human);
cache.delete('Animal');
recording = cache.toObject();
Expand Down
46 changes: 29 additions & 17 deletions packages/apollo-cache-inmemory/src/inMemoryCache.ts
Expand Up @@ -52,23 +52,12 @@ const hasOwn = Object.prototype.hasOwnProperty;
export class OptimisticCacheLayer extends ObjectCache {
constructor(
public readonly optimisticId: string,
public parent: NormalizedCache | null = null,
public readonly parent: NormalizedCache,
public readonly transaction: Transaction<NormalizedCacheObject>,
) {
super(Object.create(null));
}

public prune(idToRemove: string) {
if (this.parent instanceof OptimisticCacheLayer) {
this.parent = this.parent.prune(idToRemove);
}

if (this.optimisticId === idToRemove) {
return this.parent;
}

return this;
}

public toObject(): NormalizedCacheObject {
return this.parent ? {
...this.parent.toObject(),
Expand Down Expand Up @@ -233,11 +222,33 @@ export class InMemoryCache extends ApolloCache<NormalizedCacheObject> {
return Promise.resolve();
}

public removeOptimistic(id: string) {
if (this.optimisticData instanceof OptimisticCacheLayer) {
this.optimisticData = this.optimisticData.prune(id);
public removeOptimistic(idToRemove: string) {
const toReapply: OptimisticCacheLayer[] = [];
let removedCount = 0;
let layer = this.optimisticData;

while (layer instanceof OptimisticCacheLayer) {
if (layer.optimisticId === idToRemove) {
++removedCount;
} else {
toReapply.push(layer);
}
layer = layer.parent;
}

if (removedCount > 0) {
// Reset this.optimisticData to the first non-OptimisticCacheLayer object,
// which is almost certainly this.data.
this.optimisticData = layer;

// Reapply the layers whose optimistic IDs do not match the removed ID.
while (toReapply.length > 0) {
const layer = toReapply.pop();
this.performTransaction(layer.transaction, layer.optimisticId);
}

this.broadcastWatches();
}
this.broadcastWatches();
}

public performTransaction(
Expand All @@ -253,6 +264,7 @@ export class InMemoryCache extends ApolloCache<NormalizedCacheObject> {
this.data = this.optimisticData = new OptimisticCacheLayer(
optimisticId,
this.optimisticData,
transaction,
);
}

Expand Down

0 comments on commit 531aa32

Please sign in to comment.