Mirror: The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.

fix(core): Fix regression that broke cache-and-network (#3174)

Changed files
+68 -1
.changeset
packages
+5
.changeset/moody-hats-attend.md
···
+
---
+
'@urql/core': patch
+
---
+
+
Fix regression which would disallow `network-only` operations after `cache-and-network` completed.
+52
packages/core/src/client.test.ts
···
expect(onOperation).toHaveBeenCalledTimes(1);
expect(onResult).toHaveBeenCalledTimes(3);
});
+
+
it('does not deduplicate cache-and-network’s follow-up operations', () => {
+
const onOperation = vi.fn();
+
const onResult = vi.fn();
+
+
const operationOne = makeOperation('query', queryOperation, {
+
...queryOperation.context,
+
requestPolicy: 'cache-and-network',
+
});
+
+
const operationTwo = makeOperation('query', queryOperation, {
+
...queryOperation.context,
+
requestPolicy: 'network-only',
+
});
+
+
let shouldSend = true;
+
const exchange: Exchange = () => ops$ =>
+
pipe(
+
ops$,
+
onPush(onOperation),
+
map(op => ({
+
hasNext: false,
+
stale: true,
+
data: 'test',
+
operation: op,
+
})),
+
filter(() => {
+
if (shouldSend) {
+
shouldSend = false;
+
client.reexecuteOperation(operationTwo);
+
return true;
+
} else {
+
return false;
+
}
+
})
+
);
+
+
const client = createClient({
+
url: 'test',
+
exchanges: [exchange],
+
});
+
+
const operationThree = makeOperation('query', queryOperation, {
+
...queryOperation.context,
+
requestPolicy: 'network-only',
+
});
+
+
pipe(client.executeRequestOperation(operationOne), subscribe(onResult));
+
pipe(client.executeRequestOperation(operationThree), subscribe(onResult));
+
+
expect(onOperation).toHaveBeenCalledTimes(2);
+
});
});
describe('shared sources behavior', () => {
+11 -1
packages/core/src/client.ts
···
result$,
// Store replay result
onPush(result => {
-
if (!result.hasNext && !result.stale)
+
if (result.stale) {
+
// If the current result has queued up an operation of the same
+
// key, then `stale` refers to it
+
for (const operation of queue) {
+
if (operation.key === result.operation.key) {
+
dispatched.delete(operation.key);
+
break;
+
}
+
}
+
} else if (!result.hasNext) {
dispatched.delete(operation.key);
+
}
replays.set(operation.key, result);
}),
// Cleanup active states on end of source