Skip to content

Commit

Permalink
Merge pull request #4319 from apollographql/avoid-copying-entire-cach…
Browse files Browse the repository at this point in the history
…e-for-optimistic-reads

Avoid copying entire cache on each optimistic read.
  • Loading branch information
benjamn committed Jan 17, 2019
2 parents d9c5c32 + 4a87022 commit c2295e6
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 234 deletions.
10 changes: 9 additions & 1 deletion CHANGELOG.md
Expand Up @@ -43,11 +43,19 @@

### Apollo Cache In-Memory (vNext)

- The speed and memory usage of optimistic reads and writes has been
improved dramatically using a new layering technique that does not
require copying the non-optimistic contents of the cache.
[PR #4319](https://github.com/apollographql/apollo-client/pull/4319/)

- The `RecordingCache` abstraction has been removed, and thus is no longer
exported from `apollo-cache-inmemory`.
[PR #4319](https://github.com/apollographql/apollo-client/pull/4319/)

- Export the optimism `wrap` function using ES2015 export syntax, instead of
CommonJS. <br/>
[@ardatan](https://github.com/ardatan) in [#4158](https://github.com/apollographql/apollo-client/pull/4158)


## Apollo Client (2.4.8)

### Apollo Client (2.4.8)
Expand Down
68 changes: 38 additions & 30 deletions packages/apollo-cache-inmemory/src/__tests__/recordingCache.ts
@@ -1,43 +1,47 @@
import { RecordingCache } from '../recordingCache';
import { OptimisticCacheLayer } from '../inMemoryCache';
import { ObjectCache } from '../objectCache';
import { NormalizedCacheObject } from '../types';

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

describe('returns correct values during recording', () => {
const data = {
Human: { __typename: 'Human', name: 'Mark' },
Animal: { __typename: 'Mouse', name: '🐭' },
};
const dataToRecord = { Human: { __typename: 'Human', name: 'John' } };
let cache: RecordingCache;

const dataToRecord = {
Human: { __typename: 'Human', name: 'John' },
};

const underlyingCache = new ObjectCache(data);

let cache = makeLayer(underlyingCache);
beforeEach(() => {
cache = new RecordingCache({ ...data });
cache = makeLayer(underlyingCache);
});

it('should passthrough values if not defined in recording', () => {
cache.record(() => {
expect(cache.get('Human')).toBe(data.Human);
expect(cache.get('Animal')).toBe(data.Animal);
});
expect(cache.get('Human')).toBe(data.Human);
expect(cache.get('Animal')).toBe(data.Animal);
});

it('should return values defined during recording', () => {
const recording = cache.record(() => {
cache.set('Human', dataToRecord.Human);
expect(cache.get('Human')).toBe(dataToRecord.Human);
});
expect(recording.Human).toBe(dataToRecord.Human);
cache.set('Human', dataToRecord.Human);
expect(cache.get('Human')).toBe(dataToRecord.Human);
expect(underlyingCache.get('Human')).toBe(data.Human);
});

it('should return undefined for values deleted during recording', () => {
const recording = cache.record(() => {
expect(cache.get('Animal')).toBe(data.Animal);
// delete should be registered in the recording:
cache.delete('Animal');
expect(cache.get('Animal')).toBeUndefined();
});

expect(recording).toHaveProperty('Animal');
expect(cache.get('Animal')).toBe(data.Animal);
// delete should be registered in the recording:
cache.delete('Animal');
expect(cache.get('Animal')).toBeUndefined();
expect(cache.toObject()).toHaveProperty('Animal');
expect(underlyingCache.get('Animal')).toBe(data.Animal);
});
});

Expand All @@ -46,16 +50,20 @@ describe('RecordingCache', () => {
Human: { __typename: 'Human', name: 'Mark' },
Animal: { __typename: 'Mouse', name: '🐭' },
};
const dataToRecord = { Human: { __typename: 'Human', name: 'John' } };
let cache: RecordingCache;

const dataToRecord = {
Human: { __typename: 'Human', name: 'John' },
};

const underlyingCache = new ObjectCache(data);
let cache = makeLayer(underlyingCache);
let recording: NormalizedCacheObject;

beforeEach(() => {
cache = new RecordingCache({ ...data });
recording = cache.record(() => {
cache.set('Human', dataToRecord.Human);
cache.delete('Animal');
});
cache = makeLayer(underlyingCache);
cache.set('Human', dataToRecord.Human);
cache.delete('Animal');
recording = cache.toObject();
});

it('should contain the property indicating deletion', () => {
Expand All @@ -70,7 +78,7 @@ describe('RecordingCache', () => {
});

it('should keep the original data unaffected', () => {
expect(cache.toObject()).toEqual(data);
expect(underlyingCache.toObject()).toEqual(data);
});
});
});

0 comments on commit c2295e6

Please sign in to comment.