Skip to content

Commit 22a1dd7

Browse files
authored
fix(apollo): use registerApolloClient to prevent memory leak (#1422)
1 parent da00a47 commit 22a1dd7

4 files changed

Lines changed: 54 additions & 27 deletions

File tree

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
"dependencies": {
77
"@algolia/autocomplete-js": "1.7.1",
88
"@algolia/autocomplete-theme-classic": "1.7.1",
9-
"@apollo/client": "^3.10.1",
10-
"@apollo/experimental-nextjs-app-support": "^0.11.9",
9+
"@apollo/client": "^3.14.0",
10+
"@apollo/client-integration-nextjs": "^0.12.0",
1111
"@dnd-kit/core": "^6.1.0",
1212
"@dnd-kit/sortable": "^8.0.0",
1313
"@dnd-kit/utilities": "^3.2.2",

src/js/auth/initializeUserInDb.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import { getClient } from '../graphql/ServerClient'
1+
import { getGlobalClient } from '../graphql/ServerClient'
22
import { MUTATION_UPDATE_PROFILE, QUERY_GET_USERNAME_BY_UUID } from '../graphql/gql/users'
33
import { updateUser } from './ManagementClient'
44
import { Username } from '../types'
5+
56
export interface UpdateUsernameInput {
67
userUuid: string
78
username: string
@@ -14,18 +15,17 @@ interface InitializeUserInDBParams extends UpdateUsernameInput {
1415
auth0UserId: string
1516
}
1617

17-
const serverClient = getClient()
18-
1918
/**
2019
* Look up in our db (not Auth0) to see whether a user by uuid exists. If it doesn't then insert a new user profile.
2120
*/
2221
export const initializeUserInDB = async (params: InitializeUserInDBParams): Promise<boolean> => {
2322
const { auth0UserId, accessToken, userUuid, username, email, avatar } = params
24-
const existed = await doesUserByUuidExist(userUuid)
23+
const client = getGlobalClient()
24+
const existed = await doesUserByUuidExist(client, userUuid)
2525
if (existed != null) {
2626
return false
2727
}
28-
const res = await serverClient.mutate<{ updateUserProfile?: boolean }, UpdateUsernameInput>({
28+
const res = await client.mutate<{ updateUserProfile?: boolean }, UpdateUsernameInput>({
2929
mutation: MUTATION_UPDATE_PROFILE,
3030
variables: {
3131
userUuid,
@@ -52,8 +52,8 @@ export const initializeUserInDB = async (params: InitializeUserInDBParams): Prom
5252
return success
5353
}
5454

55-
const doesUserByUuidExist = async (userUuid: string): Promise<Username | null> => {
56-
const res = await serverClient.query<{ getUsername?: Username }, { userUuid: string }>({
55+
const doesUserByUuidExist = async (client: ReturnType<typeof getGlobalClient>, userUuid: string): Promise<Username | null> => {
56+
const res = await client.query<{ getUsername?: Username }, { userUuid: string }>({
5757
query: QUERY_GET_USERNAME_BY_UUID,
5858
variables: {
5959
userUuid

src/js/graphql/ServerClient.ts

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1-
import { ApolloClient, HttpLink, InMemoryCache, from } from '@apollo/client'
2-
import { registerApolloClient } from '@apollo/experimental-nextjs-app-support'
1+
import { ApolloLink, HttpLink } from '@apollo/client'
2+
import {
3+
registerApolloClient,
4+
ApolloClient,
5+
InMemoryCache
6+
} from '@apollo/client-integration-nextjs'
37
import { dynamicTagsLink } from './dynamicTagsLink'
48

59
const uri: string = process.env.OPENBETA_API_SERVER ?? ''
@@ -12,14 +16,31 @@ console.log('###################################################################
1216
console.log(' API Server', uri)
1317
console.log('#######################################################################')
1418

15-
const httpLink = new HttpLink({ uri })
19+
const httpLink = new HttpLink({
20+
uri,
21+
fetchOptions: {
22+
signal: AbortSignal.timeout(30000) // 30 second timeout
23+
}
24+
})
1625

1726
/**
18-
* Apollo client to be used in React Server Components.
27+
* Apollo client for React Server Components.
28+
* Uses registerApolloClient to share one client instance per request.
1929
*/
20-
export const { getClient } = registerApolloClient(() => {
30+
export const { getClient, query, PreloadQuery } = registerApolloClient(() => {
2131
return new ApolloClient({
2232
cache: new InMemoryCache(),
23-
link: from([dynamicTagsLink, httpLink])
33+
link: ApolloLink.from([dynamicTagsLink, httpLink])
2434
})
2535
})
36+
37+
/**
38+
* Apollo client for non-RSC contexts (API routes, auth callbacks).
39+
* Creates a fresh client per call.
40+
*/
41+
export function getGlobalClient (): ApolloClient<any> {
42+
return new ApolloClient({
43+
cache: new InMemoryCache(),
44+
link: ApolloLink.from([dynamicTagsLink, httpLink])
45+
})
46+
}

yarn.lock

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,23 @@
4747
resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30"
4848
integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==
4949

50-
"@apollo/client-react-streaming@0.11.11":
51-
version "0.11.11"
52-
resolved "https://registry.yarnpkg.com/@apollo/client-react-streaming/-/client-react-streaming-0.11.11.tgz#7606cc998371be42f759056795e1b763ae52c2e6"
53-
integrity sha512-h7u/D5GDq5mn2BXaWBiK9z+i90mzmBCnOeRt4Iarc1qwTt40Q4u2yEXPw8ma1BywZ2uLJyVuAb6EyA605eqeEQ==
50+
"@apollo/client-integration-nextjs@^0.12.0":
51+
version "0.12.3"
52+
resolved "https://registry.yarnpkg.com/@apollo/client-integration-nextjs/-/client-integration-nextjs-0.12.3.tgz#154c9d7fbb52d8a1c8220fad8ae9029e4e52fa04"
53+
integrity sha512-kX/PwWYJqwNBusnxm5AEM/0eEgkRJWAG04iKcJE2wAg1M+81X+sojlZXdFK5oQB2tc5+H2atzwWiLBq+mk5ddQ==
5454
dependencies:
55+
"@apollo/client-react-streaming" "0.12.3"
56+
57+
"@apollo/client-react-streaming@0.12.3":
58+
version "0.12.3"
59+
resolved "https://registry.yarnpkg.com/@apollo/client-react-streaming/-/client-react-streaming-0.12.3.tgz#f0123a25550af56cc4ff776481387f5d930aa282"
60+
integrity sha512-RyLHV29R79lJQ/qVhXevDV0lVgTujFsbzr4RzyhtjWRknDX4GP7CGKTESHu8/JDM1y6XC8AdNwnXT3dkSBjUsw==
61+
dependencies:
62+
"@types/react-dom" "^19.0.0"
5563
"@wry/equality" "^0.5.6"
5664
ts-invariant "^0.10.3"
5765

58-
"@apollo/client@^3.10.1":
66+
"@apollo/client@^3.14.0":
5967
version "3.14.0"
6068
resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.14.0.tgz#eda34b85ee03c6c0828ba21782419c8699feaf0b"
6169
integrity sha512-0YQKKRIxiMlIou+SekQqdCo0ZTHxOcES+K8vKB53cIDpwABNR0P0yRzPgsbgcj3zRJniD93S/ontsnZsCLZrxQ==
@@ -74,13 +82,6 @@
7482
tslib "^2.3.0"
7583
zen-observable-ts "^1.2.5"
7684

77-
"@apollo/experimental-nextjs-app-support@^0.11.9":
78-
version "0.11.11"
79-
resolved "https://registry.yarnpkg.com/@apollo/experimental-nextjs-app-support/-/experimental-nextjs-app-support-0.11.11.tgz#5d70a6d1ff6ad9dc0e645dfbd546bdac1c0d6440"
80-
integrity sha512-q/vtKn2V9NE1YPU7WpPx2PGpLsYSGwRcPy8pa90glrHqlEVVqTWTGraDLe3wG0K/0NnnO1U4IcFoRYKoBfjRag==
81-
dependencies:
82-
"@apollo/client-react-streaming" "0.11.11"
83-
8485
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.27.1":
8586
version "7.27.1"
8687
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be"
@@ -2864,6 +2865,11 @@
28642865
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.7.tgz#b89ddf2cd83b4feafcc4e2ea41afdfb95a0d194f"
28652866
integrity sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==
28662867

2868+
"@types/react-dom@^19.0.0":
2869+
version "19.2.3"
2870+
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-19.2.3.tgz#c1e305d15a52a3e508d54dca770d202cb63abf2c"
2871+
integrity sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==
2872+
28672873
"@types/react@*":
28682874
version "19.2.2"
28692875
resolved "https://registry.yarnpkg.com/@types/react/-/react-19.2.2.tgz#ba123a75d4c2a51158697160a4ea2ff70aa6bf36"

0 commit comments

Comments
 (0)