From 1a2c5f223a7cd5345dee7d0033f978130cc4849e Mon Sep 17 00:00:00 2001 From: Phil Pluckthun Date: Thu, 19 Dec 2019 15:37:11 +0000 Subject: [PATCH 1/3] Enable resolvers to cause cache misses by returning undefined --- src/extras/relayPagination.test.ts | 5 +---- src/operations/query.ts | 25 ++++++++++++++----------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/extras/relayPagination.test.ts b/src/extras/relayPagination.test.ts index 31b7589..423708a 100644 --- a/src/extras/relayPagination.test.ts +++ b/src/extras/relayPagination.test.ts @@ -530,10 +530,7 @@ it('prevents overlapping of pagination on different arguments', () => { ); expect(resTwo.data).toHaveProperty('items.edges.length', 1); - expect(resThree.data).toEqual({ - __typename: 'Query', - items: null, - }); + expect(resThree.data).toEqual(null); }); it('returns an empty array of edges when the cache has zero edges stored', () => { diff --git a/src/operations/query.ts b/src/operations/query.ts index ac46041..4fd4068 100644 --- a/src/operations/query.ts +++ b/src/operations/query.ts @@ -281,7 +281,7 @@ const readSelection = ( data[fieldAlias] = fieldValue; } - const resolverValue: DataField | undefined = resolvers[fieldName]( + dataFieldValue = resolvers[fieldName]( data, fieldArgs || makeDict(), store, @@ -298,15 +298,18 @@ const readSelection = ( key, getSelectionSet(node), (data[fieldAlias] as Data) || makeDict(), - resolverValue + dataFieldValue ); - } else { - // Otherwise we set the resolverValue, and normalise it to null when there's - // no schema data to check with whether this field is nullable - dataFieldValue = - resolverValue === undefined && schemaPredicates === undefined - ? null - : resolverValue; + } + + if ( + schemaPredicates !== undefined && + dataFieldValue === null && + !schemaPredicates.isFieldNullable(typename, fieldName) + ) { + // Special case for when null is not a valid value for the + // current field + return undefined; } } else if (node.selectionSet === undefined) { // The field is a scalar and can be retrieved directly @@ -481,7 +484,7 @@ const resolveResolverResult = ( select: SelectionSet, prevData: void | Data | Data[], result: void | DataField -): DataField | undefined => { +): DataField | void => { if (Array.isArray(result)) { const { schemaPredicates } = ctx; // Check whether values of the list may be null; for resolvers we assume @@ -512,7 +515,7 @@ const resolveResolverResult = ( return data; } else if (result === null || result === undefined) { - return null; + return result; } else if (isDataOrKey(result)) { const data = prevData === undefined ? makeDict() : prevData; return typeof result === 'string' From 73d401256ec0e035d52a148e642a3408837beaeb Mon Sep 17 00:00:00 2001 From: Phil Pluckthun Date: Thu, 19 Dec 2019 15:47:22 +0000 Subject: [PATCH 2/3] Add cache miss logic to simplePagination --- src/extras/simplePagination.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/extras/simplePagination.ts b/src/extras/simplePagination.ts index 015cb5f..41f37fc 100644 --- a/src/extras/simplePagination.ts +++ b/src/extras/simplePagination.ts @@ -88,6 +88,14 @@ export const simplePagination = ({ prevOffset = currentOffset; } - return result; + const hasCurrentPage = cache.resolve(entityKey, fieldName, fieldArgs); + if (hasCurrentPage) { + return result; + } else if ((info as any).schemaPredicates === undefined) { + return undefined; + } else { + info.partial = true; + return result; + } }; }; From db595b318fdfb20010fbb1a8e45837e51c9b14b8 Mon Sep 17 00:00:00 2001 From: Phil Pluckthun Date: Thu, 19 Dec 2019 15:55:02 +0000 Subject: [PATCH 3/3] Update simplePagination tests for cache misses --- src/extras/simplePagination.test.ts | 35 +++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/src/extras/simplePagination.test.ts b/src/extras/simplePagination.test.ts index 6d356f3..fa9e0ac 100644 --- a/src/extras/simplePagination.test.ts +++ b/src/extras/simplePagination.test.ts @@ -43,17 +43,32 @@ it('works with simple pagination', () => { { query: Pagination, variables: { skip: 0, limit: 3 } }, pageOne ); + const pageOneResult = query(store, { + query: Pagination, + variables: { skip: 0, limit: 3 }, + }); + expect(pageOneResult.data).toEqual(pageOne); + write( store, { query: Pagination, variables: { skip: 3, limit: 3 } }, pageTwo ); - const result = query(store, { query: Pagination }); - expect(result.data).toEqual({ - __typename: 'Query', - persons: [...pageOne.persons, ...pageTwo.persons], + const pageTwoResult = query(store, { + query: Pagination, + variables: { skip: 3, limit: 3 }, }); + expect((pageTwoResult.data as any).persons).toEqual([ + ...pageOne.persons, + ...pageTwo.persons, + ]); + + const pageThreeResult = query(store, { + query: Pagination, + variables: { skip: 6, limit: 3 }, + }); + expect(pageThreeResult.data).toEqual(null); }); it('handles duplicates', () => { @@ -102,7 +117,10 @@ it('handles duplicates', () => { pageTwo ); - const result = query(store, { query: Pagination }); + const result = query(store, { + query: Pagination, + variables: { skip: 2, limit: 3 }, + }); expect(result.data).toEqual({ __typename: 'Query', persons: [...pageOne.persons, pageTwo.persons[1], pageTwo.persons[2]], @@ -155,7 +173,10 @@ it('should preserve the correct order', () => { pageOne ); - const result = query(store, { query: Pagination }); + const result = query(store, { + query: Pagination, + variables: { skip: 3, limit: 3 }, + }); expect(result.data).toEqual({ __typename: 'Query', persons: [...pageOne.persons, ...pageTwo.persons], @@ -215,5 +236,5 @@ it('prevents overlapping of pagination on different arguments', () => { expect(resTwo.data).toHaveProperty(['persons', 0, 'id'], 'two'); expect(resTwo.data).toHaveProperty('persons.length', 1); - expect(resThree.data).toEqual({ __typename: 'Query', persons: [] }); + expect(resThree.data).toEqual(null); });