From 1d639f45cab59b7821874c12534c20b2d59c806c Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Thu, 6 Nov 2025 02:41:58 +0100 Subject: [PATCH] Restart graphql subscriptions after ws client recreation Disposing the client does not restart active subscriptions. --- src/lib/requests/RequestManager.ts | 7 ++++++- src/lib/requests/client/GraphQLClient.ts | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/lib/requests/RequestManager.ts b/src/lib/requests/RequestManager.ts index cb8aeaf1..f32433c3 100644 --- a/src/lib/requests/RequestManager.ts +++ b/src/lib/requests/RequestManager.ts @@ -1186,11 +1186,16 @@ export class RequestManager { abortRequest, }; case GQLMethod.USE_SUBSCRIPTION: - return useSubscription(operation, { + // eslint-disable-next-line no-case-declarations + const subscription = useSubscription(operation, { client: this.graphQLClient.client, variables, ...(options as SubscriptionHookOptions), }); + + this.graphQLClient.useRestartSubscription(subscription.restart); + + return subscription; default: throw new Error(`unexpected GQLRequest type "${method}"`); } diff --git a/src/lib/requests/client/GraphQLClient.ts b/src/lib/requests/client/GraphQLClient.ts index 2025217b..f961769b 100644 --- a/src/lib/requests/client/GraphQLClient.ts +++ b/src/lib/requests/client/GraphQLClient.ts @@ -26,6 +26,8 @@ import { getMainDefinition } from '@apollo/client/utilities'; import { TypePolicies } from '@apollo/client/cache'; import { removeTypenameFromVariables } from '@apollo/client/link/remove-typename'; import { d } from 'koration'; +import { useId } from '@mantine/hooks'; +import { useEffect } from 'react'; import { BaseClient } from '@/lib/requests/client/BaseClient.ts'; import { StrictTypedTypePolicies } from '@/lib/graphql/generated/apollo-helpers.ts'; import { AuthManager } from '@/features/authentication/AuthManager.ts'; @@ -197,6 +199,8 @@ export class GraphQLClient extends BaseClient< private wsClientAliveCheckInterval: NodeJS.Timeout | undefined = undefined; + private activeConnectionSubscriptions = new Map void>(); + constructor(handleRefreshToken: (refreshToken: string) => AbortableApolloMutationResponse) { super(handleRefreshToken); @@ -335,6 +339,8 @@ export class GraphQLClient extends BaseClient< this.createWSClient(false); this.client.setLink(this.createLink()); + + this.activeConnectionSubscriptions.forEach((callback) => callback()); } }, checkHeartbeatInterval); } @@ -356,4 +362,19 @@ export class GraphQLClient extends BaseClient< } public override updateConfig() {} + + public useRestartSubscription(restart: () => void) { + const id = useId(); + + this.activeConnectionSubscriptions.set(id, () => { + restart(); + }); + + useEffect( + () => () => { + this.activeConnectionSubscriptions.delete(id); + }, + [id], + ); + } }