Skip to content

Commit

Permalink
fix(cacheMiddleware): do not cache responses with errors by default (#35
Browse files Browse the repository at this point in the history
)

* [cacheMiddleware] Do not cache responses with errors

* Add option on cacheMiddleware to allow store errors

* Update README.
  • Loading branch information
helielson authored and nodkz committed Sep 13, 2018
1 parent 2aefb95 commit c16e42d
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 5 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ import { RelayNetworkLayer } from 'react-relay-network-modern/es';
* `allowMutations` - allow to cache Mutation requests (default: `false`)
* `allowFormData` - allow to cache FormData requests (default: `false`)
* `clearOnMutation` - clear the cache on any Mutation (default: `false`)
* `cacheErrors` - cache responses with errors (default: `false`)
* **authMiddleware** - for adding auth token, and refreshing it if gets 401 response from server.
* `token` - string which returns token. Can be function(req) or Promise. If function is provided, then it will be called for every request (so you may change tokens on fly).
* `tokenRefreshPromise`: - function(req, res) which must return promise or regular value with a new token. This function is called when server returns 401 status code. After receiving a new token, middleware re-run query to the server seamlessly for Relay.
Expand Down
4 changes: 2 additions & 2 deletions src/__mocks__/mockReq.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type RelayResponse from '../RelayResponse';

type ReqData = {
query?: string,
varaibles?: Object,
variables?: Object,
files?: any,
};

Expand Down Expand Up @@ -36,7 +36,7 @@ class MockReq {
}
getVariables(): Object {
return this.reqData.varaibles || {};
return this.reqData.variables || {};
}
getFiles(): any {
Expand Down
42 changes: 42 additions & 0 deletions src/middlewares/__tests__/cache-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,46 @@ describe('middlewares/cache', () => {
expect(res2.data).toBe('PAYLOAD');
expect(fetchMock.calls('/graphql')).toHaveLength(2);
});

it('do not use cache for responses with errors', async () => {
fetchMock.mock({
matcher: '/graphql',
response: {
status: 200,
body: { data: 'PAYLOAD', errors: [{ type: 'timeout' }] },
},
method: 'POST',
});

const rnl = new RelayNetworkLayer([cacheMiddleware()]);

// try fetch
await expect(mockReq('FirstQuery').execute(rnl)).rejects.toThrow();
expect(fetchMock.calls('/graphql')).toHaveLength(1);

// try fetch again
await expect(mockReq('FirstQuery').execute(rnl)).rejects.toThrow();
expect(fetchMock.calls('/graphql')).toHaveLength(2);
});

it('use cache for responses with errors and cacheErrors flag', async () => {
fetchMock.mock({
matcher: '/graphql',
response: {
status: 200,
body: { data: 'PAYLOAD', errors: [{ type: 'timeout' }] },
},
method: 'POST',
});

const rnl = new RelayNetworkLayer([cacheMiddleware({ cacheErrors: true })]);

// try fetch
await expect(mockReq('FirstQuery').execute(rnl)).rejects.toThrow();
expect(fetchMock.calls('/graphql')).toHaveLength(1);

// try fetch again
await expect(mockReq('FirstQuery').execute(rnl)).rejects.toThrow();
expect(fetchMock.calls('/graphql')).toHaveLength(1);
});
});
11 changes: 8 additions & 3 deletions src/middlewares/cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ type CacheMiddlewareOpts = {|
allowMutations?: boolean,
allowFormData?: boolean,
clearOnMutation?: boolean,
cacheErrors?: boolean,
|};

export default function queryMiddleware(opts?: CacheMiddlewareOpts): Middleware {
const { size, ttl, onInit, allowMutations, allowFormData, clearOnMutation } = opts || {};
const { size, ttl, onInit, allowMutations, allowFormData, clearOnMutation, cacheErrors } = opts || {};
const cache = new QueryResponseCache({
size: size || 100, // 100 requests
ttl: ttl || 15 * 60 * 1000, // 15 minutes
Expand Down Expand Up @@ -43,7 +44,9 @@ export default function queryMiddleware(opts?: CacheMiddlewareOpts): Middleware
const variables = req.getVariables();
const res = await next(req);

cache.set(queryId, variables, res);
if (!res.errors || (res.errors && cacheErrors)) {
cache.set(queryId, variables, res);
}
return res;
}

Expand All @@ -57,7 +60,9 @@ export default function queryMiddleware(opts?: CacheMiddlewareOpts): Middleware
}

const res = await next(req);
cache.set(queryId, variables, res);
if (!res.errors || (res.errors && cacheErrors)) {
cache.set(queryId, variables, res);
}

return res;
} catch (e) {
Expand Down

0 comments on commit c16e42d

Please sign in to comment.