You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
WebSocketClient should reuse the application's Netty event loop instead of creating its own #1567
WebSocketClient in the experimental org.restlet.ext.websocket extension (added in #893) creates its own Netty I/O threads. Its internal NettyWebSocketConnector builds a MultiThreadIoEventLoopGroup with the default thread count (twice the number of cores) in its constructor, and shuts it down when the client stops.
As a result:
An application that already runs the core Netty HTTP client or server gets a second, separate set of I/O threads for WebSocket clients.
The thread count can't be configured, unlike the eventLoopWorkerThreads parameter of the core Netty connectors.
Each WebSocketClient instance starts its own threads, so several clients in one application multiply them.
This goes against the convention adopted for the new MCP, gRPC and Smithy extensions: an extension borrows the application's connector, which the application owns, starts and stops, instead of running its own transport resources.
Why it matters
It blocks WebSocket support in a planned GraphQL extension (subscriptions over graphql-transport-ws). That extension follows the same borrowed-connector convention, and its WebSocket client is on hold until this is fixed. Its HTTP and SSE support uses the core connectors and isn't affected.
Proposed direction
Let WebSocketClient run on the event loop of a borrowed, started org.restlet.Client that uses the Netty HTTP connector, for example through a setClient(Client) setter, in line with the setter-based configuration from #1566. The client would not stop the borrowed connector.
Points to settle:
How the extension gets the event loop from the client connector. NettyClientHelper creates its MultiThreadIoEventLoopGroup in start() and doesn't expose it, so this probably needs a small engine hook, similar to the NettyConnectionUpgrade hook used on the server side.
Whether the client's own event loop stays as the default when no Client is supplied, which keeps the current behavior working.
Whether WebSocket connections can share the client connector's TLS configuration as well as its event loop.
Activity
fix: let WebSocketClient share a borrowed client's event loop
feat: add the GraphQL WebSocket client (G4, graphql-transport-ws)
fix: let WebSocketClient share a borrowed client's event loop
fix: let WebSocketClient share a borrowed client's event loop
feat: add the GraphQL WebSocket client (G4, graphql-transport-ws)