bun
bun copied to clipboard
Bun doesn't support Apollo Server GraphQL subscription
What version of Bun is running?
1.0.8+2a405f691e80725fe0b97b93afd3b8cfed13fa5f
What platform is your computer?
Darwin 23.1.0 arm64 arm
What steps can reproduce the bug?
Get this project and run it with nodejs and bun. https://github.com/apollographql/docs-examples/blob/main/apollo-server/v4/subscriptions-graphql-ws/src/index.ts
git clone https://github.com/apollographql/docs-examples.git
cd docs-examples/apollo-server/v4/subscriptions-graphql-ws
NodeJS Version
npm install
npm start
Bun Version
bun install
bun --bun run start # make sure to use the --bun flag
# the start script runs bun run compile && node ./dist/index.js
# or run TypeScript directly without compiling to JS
bun src/index.ts
Open http://localhost:4000/graphql
Use subscription query
subscription Subscription {
numberIncremented
}
What is the expected behavior?
GraphQL subscription should work. When running with NodeJS, it works fine.
I see the number incremented messages keep showing up
What do you see instead?
When running with bun, it doesn't connect at all.
Additional information
GraphQL mutation and query works fine with bun runtime, probably because they are in nature simply http post request. Not sure why graphql subscription doesn't work. I believe they use WebSocket, which bun should support, but for some reason doesn't work, and no error is shown.
I don't know where to start debugging. I am guessing apollo uses some nodejs API that bun has not implemented.
@HuakunShen Do you mind to retry with Bun v1.0.15 (https://bun.sh/blog/bun-v1.0.15#stable-websocket-client)
@root-io It still doesn't work after upgrading to v1.0.15
I'm also using v1.0.15 and having problems with this
Your example is using WebSocketServer
from https://github.com/websockets/ws maybe open an issue with them
i'm experiencing this exact issue as well. would love to see it fixed. also if anyone thinks of a work around i would love to hear that as well :wink:
I'm using packages ws
, graphql-ws
, http
and express
and I can't get my Apollo Subscriptions to work. The client websocket appears to connect, but the server never sends any data over the connection. I'm not sure where the problem is originating.
graphql-ws
does ship a Bun integration, but it does not change the fact that there is some kind of Node compatibility issue going on here with Bun.
Brothers, I have some good news: my GraphQL websockets started to work. I upgraded to the latest canary and things seem to be working! 🎉 I'm not sure which commit resolved this though.
The only issue I'm seeing now is this error flooding my console
64 | if (pongWait) {
65 | clearTimeout(pongWait);
66 | pongWait = null;
67 | }
68 | });
69 | socket.ping();
^
TypeError: socket.ping is not a function. (In 'socket.ping()', 'socket.ping' is undefined)
at /home/banks/Development/beep/node_modules/graphql-ws/lib/use/ws.js:69:21
@Jarred-Sumner take a look? 👉👈 🥺
With bun v1.0.22, I now get response for the first subscription query, but no update after that. Then I got errors in console.
Not only socket.ping
, but also socket.terminate()
.
at /Users/hacker/Documents/Learn/graphql/apollographql/docs-examples/apollo-server/v4/subscriptions-graphql-ws/node_modules/graphql-ws/lib/use/ws.mjs:57:25
61 | if (pongWait) {
62 | clearTimeout(pongWait);
63 | pongWait = null;
64 | }
65 | });
66 | socket.ping();
^
TypeError: socket.ping is not a function. (In 'socket.ping()', 'socket.ping' is undefined)
at /Users/user/apollographql/docs-examples/apollo-server/v4/subscriptions-graphql-ws/node_modules/graphql-ws/lib/use/ws.mjs:66:21
52 | ? setInterval(() => {
53 | // ping pong on open sockets only
54 | if (socket.readyState === socket.OPEN) {
55 | // terminate the connection after pong wait has passed because the client is idle
56 | pongWait = setTimeout(() => {
57 | socket.terminate();
^
TypeError: socket.terminate is not a function. (In 'socket.terminate()', 'socket.terminate' is undefined)
at /Users/user/apollographql/docs-examples/apollo-server/v4/subscriptions-graphql-ws/node_modules/graphql-ws/lib/use/ws.mjs:57:25
Getting the same issue
1 | pongWait = setTimeout(() => {
22 | socket.terminate();
23 | }, keepAlive), socket.once("pong", () => {
24 | if (pongWait)
25 | clearTimeout(pongWait), pongWait = null;
26 | }), socket.ping();
^
TypeError: socket.ping is not a function. (In 'socket.ping()', 'socket.ping' is undefined)
at /Users/user/Github/server/node_modules/.pnpm/[email protected][email protected]/node_modules/graphql-ws/lib/use/ws.mjs:26:13
17 | });
18 | let pongWait = null;
19 | const pingInterval = keepAlive > 0 && isFinite(keepAlive) ? setInterval(() => {
20 | if (socket.readyState === socket.OPEN)
21 | pongWait = setTimeout(() => {
22 | socket.terminate();
^
TypeError: socket.terminate is not a function. (In 'socket.terminate()', 'socket.terminate' is undefined)
at /Users/user/Github/server/node_modules/.pnpm/[email protected][email protected]/node_modules/graphql-ws/lib/use/ws.mjs:22:11
on v1.0.26
I've been trying to find a hacky solution to this and I think I've got something that will work for now.
wsServer.on('connection', (socket) => {
// Check if the socket has a ping method
if (!socket.ping) {
socket.ping = () => {
if (socket.readyState === WebSocket.OPEN) {
// Send a keep-alive message expected by Apollo Client
// socket.send(JSON.stringify({ type: 'pong' }));
console.log('Keep-alive message sent');
}
};
}
if (!socket.terminate) {
// If not, polyfill it with a custom implementation
socket.terminate = () => {
console.log('Terminate method called');
if (socket.close) {
socket.close();
} else {
console.warn('Socket does not have a close method');
}
};
}
// const keepAliveInterval = setInterval(() => {
// if (socket.readyState !== WebSocket.OPEN) {
// clearInterval(keepAliveInterval);
// } else {
// socket.ping();
// }
// }, 30000);
});
I've left some comments in there to show some of what I've tried. Would love to see what you guys think :D
@Jarred-Sumner
I had the same issue and went searching into the graphql-ws library to see what goes wrong. Every time the promise "socket.send" is called in the file /lib/server.mjs file, the promise is executed but never resolves (nor rejects).
By removing all those awaits from those calls, the subscription technically works
It also solves the ping problem, since the answer to a ping is also a socket.send_message
I didn't find a way to override this behavior by not fiddling into the library
I hope this can help
This issue seems to be related to https://github.com/oven-sh/bun/issues/7346 - at least the root of the problem in both situations point into the same direction
It seems Bun v1.0.32 fixed the issue with ws.ping()
.
Tried setting up bun again with apollo but when running the subscription I get this error as a subscription message:
Cannot instantiate an arrow function
which is hard to debug as I don't know where it's coming from.
Has anyone else being able to use Apollo with subscriptions?
Errors are gone but connections are not stable and I don't know where to start debugging as it works well using Node
Current situation:
- No error displayed
- Message received from subscription, but not updated every second
The message should be received every second, but now every 26-28 seconds.
Bun Version: 1.1.3
OS: MacOS Arm
On Windows the server won't start at all.
Fixed in v1.1.18!
https://github.com/oven-sh/bun/discussions/12327
Fixed in v1.1.18!
#12327 I got this error instead after upgrading to 1.1.18