shashank created CAMEL-25844:
--------------------------------

             Summary: camel-dapr - the configuration consumer never subscribes 
again after its stream to the sidecar ends, and receives no further 
configuration change
                 Key: CAMEL-25844
                 URL: https://issues.apache.org/jira/browse/CAMEL-25844
             Project: Camel
          Issue Type: Bug
          Components: camel-dapr
            Reporter: shashank
            Assignee: shashank


{{DaprConfigurationConsumer}} (main 20cdb309f7d0, {{doStart}}) subscribes once 
to the {{Flux}} returned by {{DaprClient.subscribeConfiguration}}:

{code:java}
Flux<SubscribeConfigurationResponse> responses = 
client.subscribeConfiguration(configRequest);
subscription = responses.subscribe((response) -> { ... });
{code}

The {{Flux}} is one server-streaming gRPC call to the Dapr sidecar. It ends 
with an error when that call fails (the sidecar restarts, which is routine in 
Kubernetes, or the connection to it drops), or completes when the sidecar ends 
the call. The Dapr Java SDK does not open the call again: 
{{DaprClientImpl.createFlux}} applies the client's {{RetryPolicy}}, and 
{{dapr.api.maxRetries}} is 0 by default (SDK 1.18.1, read with javap). The 
consumer passes no error or completion handler, so Reactor logs the error once 
as dropped ({{onErrorDropped}}), and a completion is not logged at all. From 
then on the consumer stays started, the route reports as started, and no 
further configuration change is delivered until the route is restarted. The 
pub/sub consumer of the same component does not have this problem: the SDK's 
{{Subscription}} opens its stream again after an error.

*Fix*: the consumer subscribes again when the stream fails or completes, after 
one second and then with a growing delay of up to 30 seconds while the sidecar 
cannot be reached (Reactor 
{{retryWhen(Retry.backoff(...).transientErrors(true))}} and {{repeatWhen}} over 
a deferred {{subscribeConfiguration}}), for as long as it runs, with a WARN 
each time. Stopping the consumer still disposes the subscription and 
unsubscribes the current subscription id. The component page says that a change 
made while the consumer is not subscribed is not delivered (the first response 
of a new subscription carries no items).

*Tests*: two new tests in {{DaprConfigurationConsumerTest}} (mocked 
{{DaprClient}}, as the existing test). 
{{testConfigurationConsumerSubscribesAgainWhenTheStreamFails}}: the first 
stream sends its subscription response and then fails, the next one carries an 
update. It fails on main ({{Wanted 2 times ... But was 1 time}}: 
{{subscribeConfiguration}} is never called again) and passes with the fix, 
where the update is routed and the consumer unsubscribes the new subscription 
id when it stops. 
{{testConfigurationConsumerSubscribesAgainWhenTheStreamCompletes}}: the same 
with a stream that completes; fails on main ({{Wanted but not invoked}}: no 
exchange), passes with the fix. camel-dapr unit tests with the fix: 66 run, 0 
failures.

*How it was found*: variant analysis of CAMEL-25843 (pattern: a library 
subscription that ends on a recoverable condition while Camel never notices, so 
the consumer stays started and receives nothing), then the JUnit tests. Not run 
against a real sidecar.

*Affected*: main, camel-4.23.x, camel-4.18.x and camel-4.14.x (the same single 
subscribe without error handling; read, not run).

_Filed with Claude Code on behalf of allthingssecurity._




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

Reply via email to