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

Work on CAMEL-26577 started by shashank.
----------------------------------------
> camel-core - RebalancingCamelClusterService: every rebalancing pass takes a 
> reference on the views and never releases it, so the view of a removed 
> clustered route keeps the leadership and a released view is started again
> ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-26577
>                 URL: https://issues.apache.org/jira/browse/CAMEL-26577
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-core, camel-kubernetes
>            Reporter: shashank
>            Assignee: shashank
>            Priority: Major
>
> {{RebalancingCamelClusterService}} (camel-support) wraps a 
> {{CamelPreemptiveClusterService}} (the Kubernetes cluster service) and runs 
> {{reconcile()}} on its own scheduled thread every period. Each pass looks at 
> every namespace through {{delegate.getView(namespace)}}, in {{members()}}, 
> {{owned()}} and {{setDisabled()}}, several times per pass, and never calls 
> {{releaseView}}.
> {{AbstractCamelClusterService.getView}} is not a plain lookup: it takes a 
> reference on the view (and starts it on the first one), and {{releaseView}} 
> stops the view when the last reference is released 
> ({{CamelClusterService.releaseView}}: "Release a view if it has no 
> references"; CAMEL-25089 made sure a released view is not started again by a 
> restart of the service). So with the rebalancing service:
> * a namespace whose clustered route is removed keeps its view running: the 
> {{ClusteredRoutePolicy}} releases its reference, but the rebalancer holds one 
> more per pass. This node stays in the election, and when it is the leader of 
> that namespace no other node runs the route (the rebalancer even counts it as 
> one of its partitions);
> * a view that was already released (stopped) is started again by the next 
> pass, as its {{getView}} takes the first reference again;
> * {{members()}} then also compares the members of views nobody uses.
> Found with a TLA+ model of the reference count of one namespace with three 
> actors (the route policy retaining at onInit and releasing at onRemove, the 
> rebalancing thread, the service stop/start). Property: once the last route 
> using the namespace is removed and the rebalancer is between passes, the view 
> is stopped and holds no reference. Short trace on main: route added (count 1, 
> view started) -> route removed (count 0, view stopped) -> reconcile pass 
> {{getView}} (count 1, view started again) -> pass ends, nothing released -> 
> the view keeps running with no user. The same with the pass before the 
> removal: the count never drops to 0. The fixed model (look only at views in 
> use, release every reference taken) holds; both paths are reachable 
> (witnesses).
> Reproduced on the real classes with {{DefaultCamelContext}}, a 
> {{ClusteredRoutePolicy}} route and a test {{CamelPreemptiveClusterService}} 
> extending {{AbstractCamelClusterService}} (no Kubernetes): after 
> {{removeRoute}} the view is still {{Started}}; a view released through the 
> API is {{Started}} again after one {{reconcile()}}. Both tests are 
> deterministic (the passes are run explicitly, the period is one hour).
> Proposed fix: the rebalancer takes a reference only on the views that are in 
> use (a package-private lookup of {{AbstractCamelClusterService}} that does 
> not create or start a view) and releases each one in a {{finally}}; 
> namespaces with no user are not partitions to balance. Delegates that do not 
> extend {{AbstractCamelClusterService}} get {{getView}}/{{releaseView}} pairs.
> Not part of this issue (minor): {{doStop}} does not wait for a pass in 
> flight, which reschedules itself on the {{serializedExecutor}} field, so 
> after a quick stop/start one more chain of passes runs on the new executor.
> _Filed with Claude Code on behalf of allthingssecurity._



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to