From 489b1b01d89881724ab8bf4dee3d1e395089101d Mon Sep 17 00:00:00 2001 From: Denis Badurina Date: Thu, 9 Jun 2022 12:42:30 +0200 Subject: [PATCH] fix(client): Retry network errors even if they occur during event emission Closes #27 --- src/__tests__/client.ts | 5 +++++ src/client.ts | 14 ++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/__tests__/client.ts b/src/__tests__/client.ts index f4da21c1..c940d277 100644 --- a/src/__tests__/client.ts +++ b/src/__tests__/client.ts @@ -549,4 +549,9 @@ describe('retries', () => { ); }); }); + + // TODO: how to simulate network errors during emission? calling socket.destroy does nothing (see: https://github.com/enisdenjo/graphql-sse/issues/22) + it.todo( + 'should retry network errors even if they occur during event emission', + ); }); diff --git a/src/client.ts b/src/client.ts index cca4a5dd..27498077 100644 --- a/src/client.ts +++ b/src/client.ts @@ -368,6 +368,9 @@ export function createClient( // all non-network errors are worth reporting immediately if (!(err instanceof NetworkError)) return onNonLazyError?.(err); + // was a network error, get rid of the current connection to ensure retries + conn = undefined; + // retries are not allowed or we tried to many times, report error if (!retryAttempts || retries >= retryAttempts) return onNonLazyError?.(err); @@ -533,6 +536,12 @@ export function createClient( // all non-network errors are worth reporting immediately if (!(err instanceof NetworkError)) throw err; + // was a network error, get rid of the current connection to ensure retries + // but only if the client is running in lazy mode (otherwise the non-lazy lock will get rid of the connection) + if (lazy) { + conn = undefined; + } + // retries are not allowed or we tried to many times, report error if (!retryAttempts || retries >= retryAttempts) throw err; @@ -724,8 +733,9 @@ async function connect( } } } catch (err) { - error = err; - if (waitingForThrow) waitingForThrow(err); + // non-network errors shouldn't ever have "network" in the message, right? + error = /network/i.test(err) ? new NetworkError(err) : err; + if (waitingForThrow) waitingForThrow(error); } finally { Object.values(waiting).forEach(({ proceed }) => proceed()); }