[ 
https://issues.apache.org/jira/browse/CAMEL-24788?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Work on CAMEL-24788 started by Andrea Cosentino.
------------------------------------------------
> camel-vertx-websocket: a shared websocket host is unregistered when the first 
> of its consumers stops
> ----------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-24788
>                 URL: https://issues.apache.org/jira/browse/CAMEL-24788
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-vertx-websocket
>            Reporter: Andrea Cosentino
>            Assignee: Andrea Cosentino
>            Priority: Major
>
> h3. Summary
> All {{vertx-websocket}} consumers bound to the same host and port share one 
> {{VertxWebsocketHost}}, but the host is dropped from the component registry 
> as soon as the *first* of those consumers stops. Every consumer that stops 
> afterwards is silently ignored, its Vert.x route is never removed, and the 
> HTTP server it runs on is never stopped.
> h3. Detail
> {{VertxWebsocketHostKey}} is {{\{host, port\}}} only (lines 25-26), so 
> {{connectConsumer}} shares a single host across every path on that port:
> {code:java}
> VertxWebsocketHost host = vertxHostRegistry.computeIfAbsent(hostKey, key -> { 
> ... });
> host.connect(consumer);
> {code}
> ({{VertxWebsocketComponent}} line 167)
> but {{disconnectConsumer}} removes that shared host on the first stop:
> {code:java}
> VertxWebsocketHost vertxWebsocketHost = vertxHostRegistry.remove(hostKey);
> if (vertxWebsocketHost != null) {
>     vertxWebsocketHost.disconnect(configuration.getWebsocketURI().getPath());
> }
> {code}
> ({{VertxWebsocketComponent}} line 205)
> With two consumers, {{/a}} and {{/b}}, on the same port:
> * stopping the {{/a}} route removes the shared host from the registry, then 
> {{disconnect("/a")}} removes only that route. 
> {{VertxWebsocketHost.disconnect}} (line 166) stops the server only once its 
> own {{routeRegistry}} is empty, and {{/b}} is still in it, so the server 
> keeps running - correctly, at that point;
> * stopping the {{/b}} route then finds *nothing* in the registry: {{remove}} 
> returns null, the null guard skips, and route {{/b}} is never removed. **The 
> server carries on listening after every Camel route is stopped.**
> * starting a consumer on that host and port again builds a *second* 
> {{VertxWebsocketHost}} with a new Router and calls {{start()}} on a port the 
> first server still holds.
> {{VertxWebsocketComponent.doStop}} (line 157) closes Vert.x only when Camel 
> created it, so when the application supplies its own {{Vertx}} or {{Router}} 
> - the usual arrangement under Spring Boot and Quarkus - nothing ever tears 
> the server down.
> h3. Two smaller problems in the same lifecycle
> * {{VertxWebsocketHost}} line 54 keeps {{routeRegistry}} in a plain 
> {{HashMap}}, mutated by {{connect}} and {{disconnect}}, i.e. on route start 
> and stop. The field right below it is a {{CopyOnWriteArrayList}} carrying an 
> explicit {{// thread-safe}} comment, so the difference looks accidental 
> rather than considered. Route start/stop is concurrent under the supervising 
> route controller.
> * {{VertxWebsocketHost.disconnect}} lines 164-165 do 
> {{routeRegistry.remove(path)}} and then {{route.remove()}} with no null 
> check, so an unknown or repeated path throws a {{NullPointerException}}.
> Found by a source audit of {{components/camel-vertx}} at be3dd651866f.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to