Skip to content

Commit

Permalink
fix(persisted): Add dev warning for persisted-miss results for an alr…
Browse files Browse the repository at this point in the history
…eady persisted-miss errored operation (repeated retries) (#3442)
  • Loading branch information
kitten authored Dec 1, 2023
1 parent 8ff4e3e commit f7684a0
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/late-plants-poke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@urql/exchange-persisted': patch
---

Warn about cached persisted-miss results in development, when a `persistedExchange()` sees a persisted-miss error for a result that's already seen a persisted-miss error (i.e. two misses). This shouldn't happen unless something is caching persisted errors and we should warn about this appropriately.
34 changes: 34 additions & 0 deletions exchanges/persisted/src/persistedExchange.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,40 @@ it('retries query persisted query resulted in unsupported', async () => {
expect(operations[2].extensions).toEqual(undefined);
});

it('fails gracefully when an invalid result with `PersistedQueryNotFound` is always delivered', async () => {
const { result, operations, exchangeArgs } = makeExchangeArgs();

result.mockImplementation(operation => ({
...queryResponse,
operation,
error: new CombinedError({
graphQLErrors: [{ message: 'PersistedQueryNotFound' }],
}),
}));

const res = await pipe(
fromValue(queryOperation),
persistedExchange()(exchangeArgs),
take(1),
toPromise
);

expect(res.operation.context.persistAttempt).toBe(true);
expect(operations.length).toBe(2);

expect(operations[1].extensions).toEqual({
persistedQuery: {
version: 1,
sha256Hash: expect.any(String),
miss: true,
},
});

expect(console.warn).toHaveBeenLastCalledWith(
expect.stringMatching(/two misses/i)
);
});

it('skips operation when generateHash returns a nullish value', async () => {
const { result, operations, exchangeArgs } = makeExchangeArgs();

Expand Down
12 changes: 12 additions & 0 deletions exchanges/persisted/src/persistedExchange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,18 @@ export const persistedExchange =
retries.next(followupOperation);
return null;
} else if (result.error && isPersistedMiss(result.error)) {
if (result.operation.extensions.persistedQuery.miss) {
if (process.env.NODE_ENV !== 'production') {
console.warn(
'persistedExchange()’s results include two misses for the same operation.\n' +
'This is not expected as it means a persisted error has been delivered for a non-persisted query!\n' +
'Another exchange with a cache may be delivering an outdated result. For example, a server-side ssrExchange() may be caching an errored result.\n' +
'Try moving the persistedExchange() in past these exchanges, for example in front of your fetchExchange.'
);
}

return result;
}
// Update operation with unsupported attempt
const followupOperation = makeOperation(
result.operation.kind,
Expand Down

0 comments on commit f7684a0

Please sign in to comment.