-
Notifications
You must be signed in to change notification settings - Fork 655
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WebSockets: better separate common code and protocol-specific code #3405
Conversation
...ime/src/appleMain/kotlin/com/apollographql/apollo3/network/ws/NSURLSessionWebSocketEngine.kt
Show resolved
Hide resolved
apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/network/ws/AppSyncWsProtocol.kt
Outdated
Show resolved
Hide resolved
apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/network/ws/GraphQLWsProtocol.kt
Outdated
Show resolved
Hide resolved
override fun parseMessage(message: String, webSocketConnection: WebSocketConnection): WsServerMessage { | ||
val map = AnyAdapter.fromJson(BufferedSourceJsonReader(Buffer().writeUtf8(message))) as Map<String, Any?> | ||
/** | ||
* A factory that for [WsProtocol] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* A factory that for [WsProtocol] | |
* A factory for [WsProtocol] |
@martinbonnin I'm testing the changes but cannot establish a websocket connection now... "Connection initialization timeout"
I noticed a couple things..
|
apollo-runtime/src/commonMain/kotlin/com/apollographql/apollo3/network/ws/GraphQLWsProtocol.kt
Show resolved
Hide resolved
Damn, this means that
Indeed, fixed.
Is that important ultimately? What would you do if the pong is not received? |
@martinbonnin the connection issue is because the message was being sent out as binary instead of string... but I don't see WsFrameType.TEXT anymore? |
Aaaah got it, thanks! I'll make it configurable again. |
Alright, it should be configurable again, sorry about that. I took this opportunity to default to Let me know about what to do with "pong" failures. If required, we can tunnel an error to the subscriptions. |
Currently, we don't do anything if the Pong is not received from the server, nor do we send any payload. However, this could change if we want to report the backend is not responding or we want to send/receive latency metrics in the payload... which could be different for each Ping/Pong. |
I see. Thanks for providing details, that helps a ton 👍 What I'm leaning to is that for more advanced use cases, you could implement class CustomWsProtocol(
webSocketConnection: WebSocketConnection,
listener: Listener,
) : WsProtocol(webSocketConnection, listener) {
override suspend fun connectionInit() {
GraphQLWsProtocol.connectionInit(connectionPayload, timeout, webSocketConnection)
}
override suspend fun startOperation() {
GraphQLWsProtocol.startOperation(request, webSocketConnection)
}
override suspend fun stopOperation() {
GraphQLWsProtocol.stopOperation(request, webSocketConnection)
}
override fun run(scope: CoroutineScope) {
scope.launch {
// Send ping here
}
super.run(scope)
}
override fun handleServerMessage(messageMap: Map<String, Any?>) {
GraphQLWsProtocol.handleServerMessage(messageMap)
// Handle pong here
} Ultimately, it gives full control over the websocket without adding tons of constructor parameters to |
Everything is working for me with your latest changes, Thanks! |
Follow up from #3401
WebSocketNetworkTransport
now takes aWsProtocol.Factory
instead of aWsProtocol
.WebSocketNetworkTransport
handles the opening/closing of the websocket and will create a newWsProtocol
for each new websocket. TheWsProtocol
is responsible for the actual sending/receiving messages:WsProtocol.startOperation
andWsProtocol.stopOperation
WebSocketNetworkTransport
withlistener.operationResponse
,listener.operationError
,listener.operationComplete
andlistener.networkError
Flow control:
This change makes all buffers
UNLIMITED
so as to avoid any deadlock. This means that there is no flow control. If the client writes messages faster than what the server can handle, OkHttp will throw when trying to write more than 16MB and native will most likely OOM. I think it's OK as messages are very small and if that ever happens, it'll be the manifestation of another bug somewhere else that needs to be fixed.Graphql-ws "ping":
Because "ping" is a
graphql-ws
specific message, sending "ping" messages has been moved toGraphQLWsProtocol
. It is now controlled withpingIntervalMillis
(disabled by default):@dchappelle let me know how that works for you. Also, I'm curious what server you're using. I've been trying to test with https://github.com/martinbonnin/graphql-ws-server and the server responds to any "ping" message with