Skip to content

Commit

Permalink
Be considerate of variable length utf-8 encodings in InMemoryLRUCache.
Browse files Browse the repository at this point in the history
Previously, this used the `JSON.stringify` length, but this is slightly more
aware.
  • Loading branch information
abernix committed Jan 15, 2019
1 parent 1a9d65d commit 0879a12
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 6 deletions.
8 changes: 4 additions & 4 deletions packages/apollo-server-caching/src/InMemoryLRUCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ export class InMemoryLRUCache<V = string> implements KeyValueCache<V> {
return item.length;
}

// If it's an object, we'll use the length to get an approximate,
// relative size of what it would take to store it. It's certainly not
// 100% accurate, but it's a very, very fast implementation and it
// If it's an object, we'll use JSON.stringify+Buffer.byteLength to
// approximate the size of what it would take to store. It's certainly
// not 100% accurate, but it should be a fast implementation which
// doesn't require bringing in other dependencies or logic which we need
// to maintain. In the future, we might consider something like:
// npm.im/object-sizeof, but this should be sufficient for now.
if (typeof item === 'object') {
return JSON.stringify(item).length;
return Buffer.byteLength(JSON.stringify(item), 'utf8');
}

// Go with the lru-cache default "naive" size, in lieu anything better:
Expand Down
10 changes: 8 additions & 2 deletions packages/apollo-server-core/src/__tests__/runQuery.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,12 @@ describe('runQuery', () => {
return '{\n' + query + '}';
}

// This should use the same logic as the calculation in InMemoryLRUCache:
// https://github.com/apollographql/apollo-server/blob/94b98ff3/packages/apollo-server-caching/src/InMemoryLRUCache.ts#L23
function approximateObjectSize<T>(obj: T): number {
return Buffer.byteLength(JSON.stringify(obj), 'utf8');
}

it('validates each time when the documentStore is not present', async () => {
expect.assertions(4);

Expand Down Expand Up @@ -564,8 +570,8 @@ describe('runQuery', () => {
// size of the two smaller queries. All three of these queries will never
// fit into this cache, so we'll roll through them all.
const maxSize =
JSON.stringify(parse(querySmall1)).length +
JSON.stringify(parse(querySmall2)).length;
approximateObjectSize(parse(querySmall1)) +
approximateObjectSize(parse(querySmall2));

const documentStore = new InMemoryLRUCache<DocumentNode>({ maxSize });

Expand Down

0 comments on commit 0879a12

Please sign in to comment.