-
Notifications
You must be signed in to change notification settings - Fork 305
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
[Question] Detecting closed web sockets for subscriptions #528
Comments
There is currently no support for sending PING messages from the server. We could add a feature along those lines, either to configure a For the "Broken pipe", we have support in the Spring Framework to treat such exceptions as unnecessary noise (normal case of client disconnecting) and only log them with a special logger at DEBUG without a stacktrace, and at TRACE with the full stacktrace. That means in production you won't see them. Is this what you're looking for? If yes, we can make this change, but it will likely need to be in the spring-websocket module, i.e. on the Spring Framework side rather than here. For detecting lost connection or cancelled subscription, you can add As an aside, I simplified your method a bit like this: @SubscriptionMapping
public Flux<Order> orders(@Argument Long id) {
return Flux.generate(() -> id, (lastOrderId, sink) -> {
List<Order> orders = getNewOrdersFromDB(lastOrderId);
orders.forEach(sink::next);
return (!orders.isEmpty() ? getLastOrderId(orders) : lastOrderId);
});
} |
Thanks for the quick response, I really appreciate it! I think it would be very useful to add the ability to send pings from the server. We are currently testing our subscription server in a ECS container in AWS, and the load balancer is closing the websocket connection if it is idle longer than the idle timeout, which has a maximum setting or 4000 seconds or 66 minutes. Having the server send a ping periodically would keep the connection from going idle thus prohibiting our load balancer from closing the connection during periods of no activity. Having the ability to send pings from the server would help with idle time outs in the load balancer and quicker detection of closed connections. It would be nice to specify an interval to constantly send pings on, or to specify an idle time to send a ping if a period of no activity on the connection was detected. It looks like Apollo Server actually has a feature like this called keepAlive, see the documentation here: https://www.apollographql.com/docs/apollo-server/v2/api/apollo-server/
What is the process to request a keepAlive feature be added to your backlog? Thanks for the code suggestion, I also found my code to be a bit complicated, but the reason it is complicated is because a generator only allows 1 Sink.next call per generator run. Your code works in my simplified example where I'm just returning 1 Order from the DB, but unfortunately does not work when multiple orders are returned from the DB. orders.forEach(sink::next); The only way I could figure out how to send multiple elements, in this case Orders, in one generator run was to add them all to a new Flux, then Sink.next that Flux, and then finally call Flux.concat on the generator itself to "flatten" back out the flux returned by the SubscriptionMapping method. This approach also allows me to call Sink.next when no Orders are returned from the DB as well. I'm afraid I am not fully understanding Reactive Streams though, and am actually surprised my solution worked at all. Also I was wondering if the Flux.concat call might be interfering with the downstream signal requesting more Orders? |
Thanks for the extra details. I've created #534 to add support for server pings. You're right that type Subscription {
orders(id: ID): [Order!]
} Yet another option to consider is to use https://r2dbc.io/. |
Closing for now as superseded by #534 but feel free to comment. |
We are creating a new API and would like to push Order events to our partners via graphql subscriptions.
I am new to reactive streams but have come up with a basic concept to retrieve order updates from our database and publish them to a flux with a generator and send them out a graphql subscription like so:
Testing this with graphiql I see two problems when I close the window and close the websocket:
So my question: is there a way for the server to periodically ping the client through the websocket and shut down the Flux generator in a graceful manner if the connection is closed?
It seems that in the graphqlws spec provides a message type for 'ping' and 'pong' messages, see https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md#ping, maybe the time interval of these could be configurable, or if no messages have been received in certain time period a ping could be sent.
Thanks, for any and all advice or info you can provide.
The sample project that can reproduce this behavior can be found here: https://github.com/erikdrewdunning/subscription-demo
Also here is a simple graphql subscription request that works against the server:
The text was updated successfully, but these errors were encountered: