Skip to content

Commit

Permalink
Reference the preload cache only for the first request
Browse files Browse the repository at this point in the history
The logic for preloading middleware in the apiFetch library caches preloaded data. As it stands today, all requests to the preloaded endpoint will reference the cache.

The problem is that the cache is never invalidated during a session. When updates are persisted to the WordPress database, the cache doesn't change, and it will continue to reference the stale, preloaded data.

This fix only allows references to cached data for each preloaded endpoint a single time, after which all subsequent requests to preloaded endpoints will skip preloading middleware.
  • Loading branch information
jeyip committed Sep 23, 2020
1 parent f543ee9 commit a570088
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 21 deletions.
12 changes: 10 additions & 2 deletions packages/api-fetch/src/middlewares/preloading.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ export function getStablePath( path ) {

function createPreloadingMiddleware( preloadedData ) {
const cache = Object.keys( preloadedData ).reduce( ( result, path ) => {
result[ getStablePath( path ) ] = preloadedData[ path ];
result[ getStablePath( path ) ] = {
...preloadedData[ path ],
hasBeenPreloaded: false,
};
return result;
}, {} );

Expand All @@ -45,7 +48,12 @@ function createPreloadingMiddleware( preloadedData ) {
const method = options.method || 'GET';
const path = getStablePath( options.path );

if ( 'GET' === method && cache[ path ] ) {
if (
'GET' === method &&
cache[ path ] &&
! cache[ path ].hasBeenPreloaded
) {
cache[ path ].hasBeenPreloaded = true;
return Promise.resolve(
parse
? cache[ path ].body
Expand Down
94 changes: 75 additions & 19 deletions packages/api-fetch/src/middlewares/test/preloading.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,82 @@ describe( 'Preloading Middleware', () => {
} );
} );

it( 'should return the preloaded data if provided', () => {
const body = {
status: 'this is the preloaded response',
};
const preloadedData = {
'wp/v2/posts': {
body,
},
};
const preloadingMiddleware = createPreloadingMiddleware(
preloadedData
);
const requestOptions = {
method: 'GET',
path: 'wp/v2/posts',
};
describe( 'given preloaded data', () => {
describe( 'when data is requested from a preloaded endpoint', () => {
describe( 'and it is requested for the first time', () => {
it( 'should return the preloaded data', () => {
const body = {
status: 'this is the preloaded response',
};
const preloadedData = {
'wp/v2/posts': {
body,
},
};
const preloadingMiddleware = createPreloadingMiddleware(
preloadedData
);
const requestOptions = {
method: 'GET',
path: 'wp/v2/posts',
};

const response = preloadingMiddleware( requestOptions );
return response.then( ( value ) => {
expect( value ).toEqual( body );
} );
} );
} );

describe( 'and it has already been requested', () => {
it( 'should not return the preloaded data', () => {
const body = {
status: 'this is the preloaded response',
};
const preloadedData = {
'wp/v2/posts': {
body,
},
};
const preloadingMiddleware = createPreloadingMiddleware(
preloadedData
);
const requestOptions = {
method: 'GET',
path: 'wp/v2/posts',
};
const nextSpy = jest.fn();

const response = preloadingMiddleware( requestOptions );
return response.then( ( value ) => {
expect( value ).toEqual( body );
preloadingMiddleware( requestOptions, nextSpy );
expect( nextSpy ).not.toHaveBeenCalled();
preloadingMiddleware( requestOptions, nextSpy );
expect( nextSpy ).toHaveBeenCalled();
} );
} );
} );

describe( 'when the requested data is not from a preloaded endpoint', () => {
it( 'should not return preloaded data', () => {
const body = {
status: 'this is the preloaded response',
};
const preloadedData = {
'wp/v2/posts': {
body,
},
};
const preloadingMiddleware = createPreloadingMiddleware(
preloadedData
);
const requestOptions = {
method: 'GET',
path: 'wp/v2/fake_resource',
};
const nextSpy = jest.fn();

preloadingMiddleware( requestOptions, nextSpy );
expect( nextSpy ).toHaveBeenCalled();
} );
} );
} );

Expand Down

0 comments on commit a570088

Please sign in to comment.