-
Notifications
You must be signed in to change notification settings - Fork 119
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
[gql_websocket_link]: Race condition resulting in multiple channels in a single link #227
Comments
Hi @shyndman |
It's actually simpler than that. The race condition exists because https://dartpad.dev/da5ae0734f2eed81ac682514b3dabc94?null_safety=true |
Is there any reason you can't rely entirely on the current connection state to determine whether or not to connect? It looks like you're already managing state transitions appropriately in |
The latest version includes a fix for a race condition that allows multiple websocket channels to open simultaneously, leading to undefined behavior. gql-dart/gql#227
Hello there,
While debugging the project I'm working on (nhost/nhost-dart#9), I noticed that a websocket link instance was invoking its channel generator multiple times before it connected. Which means more sockets than expected...conceivably misbehaving sockets.
Here's how to reproduce:
WebSocketLink
Stream.listen
and notawait for
.Here are the logs associated with the above, annotated with what's happening (I added logging throughout the code to better understand the flow of things):
Digging a little deeper, it appears the initialization logic doesn't take into account whether a channel is already being created. This check
gql/links/gql_websocket_link/lib/src/link.dart
Lines 136 to 138 in 9b8e44f
While I don't know the specifics of what happens after this point, it doesn't look stable. All those sockets are going to be sharing the same connection state stream and timers...and if any one of those streams hits its onDone handler, it will either trigger a reconnection on the "winning" socket, or just close it outright.
I've also been thinking through solutions, and I think that making an
AsyncMemoizer
responsible for channel creation would do the trick. The only thing to keep in mind is that you'd need to recreate the memoizer every time the socket disconnects, so that it can protect against the next request barrage.Version: 0.3.0
Bonus. Screenshot of the supremely connected link:
![Screen Shot 2021-05-18 at 1 42 20 AM](https://user-images.githubusercontent.com/42326/118597190-5a12b280-b77a-11eb-9533-49cfefa30796.png)
The text was updated successfully, but these errors were encountered: