[
https://issues.apache.org/jira/browse/CAMEL-25883?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
shashank updated CAMEL-25883:
-----------------------------
Description:
The {{raftHandle}} option of the JGroups Raft component (a {{RaftHandle}} with
its {{JChannel}}, Raft log and state machine) is given to every endpoint the
component creates ({{JGroupsRaftComponent.createEndpoint}}). Each
{{JGroupsRaftEndpoint}} (main 20cdb309f7d0) counts only its own producers and
consumers in {{connectCount}}, and closes the channel and the Raft log when it
stops:
{code:java}
public void disconnect() {
if (connectCount.decrementAndGet() == 0) {
resolvedRaftHandle.channel().disconnect();
}
}
protected void doStop() throws Exception {
if (resolvedRaftHandle != null && resolvedRaftHandle.channel() != null) {
resolvedRaftHandle.channel().close();
}
if (resolvedRaftHandle != null && resolvedRaftHandle.log() != null) {
resolvedRaftHandle.log().close();
}
...
{code}
With the component {{raftHandle}}, two endpoints of the same cluster that
differ in their options (for example a producer to {{jgroups-raft:orders}} and
a consumer from {{jgroups-raft:orders?enableRoleChangeEvents=true}}) share the
handle but not the count. When the producer route stops, its endpoint
disconnects the shared channel, so the node leaves the Raft cluster while the
consumer route stays started. When the producer route is removed, its endpoint
is stopped and closes the channel and the Raft log of the shared handle, and
the other endpoints cannot use the handle again. Nothing is logged at WARN or
ERROR.
This is the same pattern as CAMEL-25852 (camel-jgroups, the {{channel}} option
of the component); it was left out of that fix to keep it to one component.
*Fix*: as in CAMEL-25852, the component counts the producers and consumers of a
handle that the endpoints did not create (the component {{raftHandle}}, or a
handle given to one endpoint with {{raftHandle=#bean}}) and disconnects its
channel when the last of them stops; an endpoint closes only a handle it
created itself (from {{channelProperties}} or the default), and the component
closes the other handles when it stops. A handle an endpoint creates itself is
unchanged. A producer or consumer disconnects the handle only when it connected
it (a consumer whose route never started is stopped as well), and the component
closes each handle in its own try, so a failure to close one does not leave the
others open.
*How it was found*: variant analysis of CAMEL-25852 during the review of its
pull request, reading {{JGroupsRaftEndpoint}} and {{JGroupsRaftComponent}},
then a JUnit test ({{JGroupsRaftComponentHandleEndpointsTest}}: component
{{raftHandle}} on a single member cluster, a producer route to
{{jgroups-raft:<cluster>}} and a consumer route from
{{jgroups-raft:<cluster>?enableRoleChangeEvents=true}}). On main, after
stopping the producer route the shared channel is no longer connected ({{the
consumer route still uses the handle ==> expected: <true> but was: <false>}}),
and after removing the producer route it is closed ({{the consumer route still
uses the handle ==> expected: <false> but was: <true>}}). In review,
{{JGroupsRaftNeverStartedConsumerTest}} (a consumer route with
{{autoStartup(false)}} next to a producer route on the component handle) showed
that stopping the never started route disconnected the handle ({{after
stopRoute of the never started route ==> expected: <true> but was: <false>}});
fixed with a connected flag in the producer and the consumer.
camel-jgroups-raft unit tests with the fix: 19 run, 0 failures.
*Affected*: main, camel-4.23.x, camel-4.22.x, camel-4.18.x and camel-4.14.x
(the same per-endpoint {{connectCount}} and {{close}} in {{doStop}}; read, not
run).
_Filed with Claude Code on behalf of allthingssecurity._
was:
The {{raftHandle}} option of the JGroups Raft component (a {{RaftHandle}} with
its {{JChannel}}, Raft log and state machine) is given to every endpoint the
component creates ({{JGroupsRaftComponent.createEndpoint}}). Each
{{JGroupsRaftEndpoint}} (main 20cdb309f7d0) counts only its own producers and
consumers in {{connectCount}}, and closes the channel and the Raft log when it
stops:
{code:java}
public void disconnect() {
if (connectCount.decrementAndGet() == 0) {
resolvedRaftHandle.channel().disconnect();
}
}
protected void doStop() throws Exception {
if (resolvedRaftHandle != null && resolvedRaftHandle.channel() != null) {
resolvedRaftHandle.channel().close();
}
if (resolvedRaftHandle != null && resolvedRaftHandle.log() != null) {
resolvedRaftHandle.log().close();
}
...
{code}
With the component {{raftHandle}}, two endpoints of the same cluster that
differ in their options (for example a producer to {{jgroups-raft:orders}} and
a consumer from {{jgroups-raft:orders?enableRoleChangeEvents=true}}) share the
handle but not the count. When the producer route stops, its endpoint
disconnects the shared channel, so the node leaves the Raft cluster while the
consumer route stays started. When the producer route is removed, its endpoint
is stopped and closes the channel and the Raft log of the shared handle, and
the other endpoints cannot use the handle again. Nothing is logged at WARN or
ERROR.
This is the same pattern as CAMEL-25852 (camel-jgroups, the {{channel}} option
of the component); it was left out of that fix to keep it to one component.
*Fix*: as in CAMEL-25852, the component counts the producers and consumers of a
handle that the endpoints did not create (the component {{raftHandle}}, or a
handle given to one endpoint with {{raftHandle=#bean}}) and disconnects its
channel when the last of them stops; an endpoint closes only a handle it
created itself (from {{channelProperties}} or the default), and the component
closes the other handles when it stops. A handle an endpoint creates itself is
unchanged.
*How it was found*: variant analysis of CAMEL-25852 during the review of its
pull request, reading {{JGroupsRaftEndpoint}} and {{JGroupsRaftComponent}},
then a JUnit test ({{JGroupsRaftComponentHandleEndpointsTest}}: component
{{raftHandle}} on a single member cluster, a producer route to
{{jgroups-raft:<cluster>}} and a consumer route from
{{jgroups-raft:<cluster>?enableRoleChangeEvents=true}}). On main, after
stopping the producer route the shared channel is no longer connected ({{the
consumer route still uses the handle ==> expected: <true> but was: <false>}}),
and after removing the producer route it is closed ({{the consumer route still
uses the handle ==> expected: <false> but was: <true>}}).
*Affected*: main, camel-4.23.x, camel-4.22.x, camel-4.18.x and camel-4.14.x
(the same per-endpoint {{connectCount}} and {{close}} in {{doStop}}; read, not
run).
_Filed with Claude Code on behalf of allthingssecurity._
> camel-jgroups-raft - with the raftHandle option of the component, an endpoint
> whose producer stops, or whose route is removed, disconnects or closes the
> RaftHandle under the other endpoints
> ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
> Key: CAMEL-25883
> URL: https://issues.apache.org/jira/browse/CAMEL-25883
> Project: Camel
> Issue Type: Bug
> Components: camel-jgroups
> Reporter: shashank
> Assignee: shashank
> Priority: Major
>
> The {{raftHandle}} option of the JGroups Raft component (a {{RaftHandle}}
> with its {{JChannel}}, Raft log and state machine) is given to every endpoint
> the component creates ({{JGroupsRaftComponent.createEndpoint}}). Each
> {{JGroupsRaftEndpoint}} (main 20cdb309f7d0) counts only its own producers and
> consumers in {{connectCount}}, and closes the channel and the Raft log when
> it stops:
> {code:java}
> public void disconnect() {
> if (connectCount.decrementAndGet() == 0) {
> resolvedRaftHandle.channel().disconnect();
> }
> }
> protected void doStop() throws Exception {
> if (resolvedRaftHandle != null && resolvedRaftHandle.channel() != null) {
> resolvedRaftHandle.channel().close();
> }
> if (resolvedRaftHandle != null && resolvedRaftHandle.log() != null) {
> resolvedRaftHandle.log().close();
> }
> ...
> {code}
> With the component {{raftHandle}}, two endpoints of the same cluster that
> differ in their options (for example a producer to {{jgroups-raft:orders}}
> and a consumer from {{jgroups-raft:orders?enableRoleChangeEvents=true}})
> share the handle but not the count. When the producer route stops, its
> endpoint disconnects the shared channel, so the node leaves the Raft cluster
> while the consumer route stays started. When the producer route is removed,
> its endpoint is stopped and closes the channel and the Raft log of the shared
> handle, and the other endpoints cannot use the handle again. Nothing is
> logged at WARN or ERROR.
> This is the same pattern as CAMEL-25852 (camel-jgroups, the {{channel}}
> option of the component); it was left out of that fix to keep it to one
> component.
> *Fix*: as in CAMEL-25852, the component counts the producers and consumers of
> a handle that the endpoints did not create (the component {{raftHandle}}, or
> a handle given to one endpoint with {{raftHandle=#bean}}) and disconnects its
> channel when the last of them stops; an endpoint closes only a handle it
> created itself (from {{channelProperties}} or the default), and the component
> closes the other handles when it stops. A handle an endpoint creates itself
> is unchanged. A producer or consumer disconnects the handle only when it
> connected it (a consumer whose route never started is stopped as well), and
> the component closes each handle in its own try, so a failure to close one
> does not leave the others open.
> *How it was found*: variant analysis of CAMEL-25852 during the review of its
> pull request, reading {{JGroupsRaftEndpoint}} and {{JGroupsRaftComponent}},
> then a JUnit test ({{JGroupsRaftComponentHandleEndpointsTest}}: component
> {{raftHandle}} on a single member cluster, a producer route to
> {{jgroups-raft:<cluster>}} and a consumer route from
> {{jgroups-raft:<cluster>?enableRoleChangeEvents=true}}). On main, after
> stopping the producer route the shared channel is no longer connected ({{the
> consumer route still uses the handle ==> expected: <true> but was:
> <false>}}), and after removing the producer route it is closed ({{the
> consumer route still uses the handle ==> expected: <false> but was:
> <true>}}). In review, {{JGroupsRaftNeverStartedConsumerTest}} (a consumer
> route with {{autoStartup(false)}} next to a producer route on the component
> handle) showed that stopping the never started route disconnected the handle
> ({{after stopRoute of the never started route ==> expected: <true> but was:
> <false>}}); fixed with a connected flag in the producer and the consumer.
> camel-jgroups-raft unit tests with the fix: 19 run, 0 failures.
> *Affected*: main, camel-4.23.x, camel-4.22.x, camel-4.18.x and camel-4.14.x
> (the same per-endpoint {{connectCount}} and {{close}} in {{doStop}}; read,
> not run).
> _Filed with Claude Code on behalf of allthingssecurity._
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)