Skip to content

Improve server handling of WebSocket connection closing and subscription completion #276

Closed
@tiparega

Description

@tiparega

We need to do some work whenever a client websocket is closed.
We tried to use afterConnectionClosed(WebSocketSession, CloseStatus) inside GraphQlWebSocketHandler, but it only works if disconnected though messages, not if the TCP connection is closed.

We were able to do it wrapping GraphQlWebSocketHandler:

	@Bean
	public GraphQlWebSocketHandler graphQlWebSocketHandler(WebGraphQlHandler webGraphQlHandler,
			GraphQlProperties properties, ServerCodecConfigurer configurer) {
		return new MyHandler(webGraphQlHandler, configurer,
				properties.getWebsocket().getConnectionInitTimeout());
	}

And then adding this:

	class MyHandler extends GraphQlWebSocketHandler {

		public MyHandler(WebGraphQlHandler graphQlHandler, ServerCodecConfigurer configurer,
				Duration connectionInitTimeout) {
			super(graphQlHandler, configurer, connectionInitTimeout);
		}
		
		@Override
		public Mono<Void> handle(WebSocketSession session) {
			log.info("Handle websocket session");
			return super.handle(session).then().doFinally(v -> {				
				log.info("Finished websocket session");
				//Some work
			});
		}		
	}

This is ok, just would be great if added to documentation.

Still, we have the problem of identifying the connection. Here we have websocket connection id and handshakeInfo, but nothing about content (that's ok, this is not the place).
What we did was to add a query param to /subscription, so we can have that information inside handshakeInfo in MyHandler:

String clientId = util.getQueryParam(session.getHandshakeInfo().getUri().getQuery()).get("clientId");

That way, we can correlate session closed with a specific client. Still, this is a very unclean trick.

I think the right place should be on connection_init payload and I've seen WebSocketInterceptor that can read this information. But there is no way to pass that information to previous custom handler. I've also checked handleConnectionCompletion method, but it's not triggered when TCP connection is suddenly closed.

Would it be possible to create a handler that is also called whenever the websocket connection is closed? We would also need to have some context information within this method (connection_init payload at least).
Another solution could be to add websocket session id inside WebInput and also pass WebInput to handleConnectionInitialization in WebsocketInterceptor. This way we could correlate payload information with session Id, which is accesible inside GraphQlWebSocketHandler.

It's a little bit tricky. I hope it's understandable.

Metadata

Metadata

Assignees

Labels

in: webIssues related to web handlingtype: enhancementA general enhancement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions