shashank created CAMEL-24960:
--------------------------------

             Summary: Multicast/Split/RecipientList with parallelProcessing 
hangs forever when the thread pool rejects a sub-exchange task
                 Key: CAMEL-24960
                 URL: https://issues.apache.org/jira/browse/CAMEL-24960
             Project: Camel
          Issue Type: Bug
          Components: camel-core
            Reporter: shashank


When a parallel Multicast, Split or Recipient List runs on a thread pool that 
rejects tasks (for example {{rejectedPolicy(Abort)}} with a bounded queue), a 
rejected sub-exchange is silently dropped. The exchange then never completes: 
the caller waits forever and the exchange stays in the inflight repository.

{{MulticastProcessor.schedule(Runnable, boolean)}} catches 
{{RejectedExecutionException}} and only calls {{reject()}} when the runnable is 
{{Rejectable}}. That handles the {{MulticastTask}} itself (CAMEL-16829). The 
sub-exchange task submitted by {{completion.submit(...)}} in 
{{MulticastReactiveTask.run()}} is an {{AsyncCompletionService.Task}}, which is 
not {{Rejectable}}, so the rejection is swallowed. The sub-exchange was already 
counted in {{nbExchangeSent}}, so {{aggregate()}} never reaches {{nbAggregated 
>= nbExchangeSent}} and {{doDone}} is never called. Without a {{timeout}} 
nothing ever completes the exchange.

Reproduced against 4.23.0-SNAPSHOT with the thread pool from 
{{SplitParallelThreadPoolAbortTest}} (poolSize 1, maxPoolSize 1, maxQueueSize 
0, Abort). The task occupies the only thread, so the sub-exchange submission is 
rejected:
{noformat}
split(body()).executorService(pool)       body=[a, b] -> completed with 
RejectedExecutionException (the task's own reschedule was rejected; part a was 
dropped)
split(body()).executorService(pool)       body=[a]    -> not completed after 5 
s, inflight=1
multicast().executorService(pool).to(..)               -> not completed after 5 
s, inflight=2
recipientList(body()).executorService(pool) "mock:z"   -> not completed after 5 
s, inflight=3
{noformat}
{{SplitParallelThreadPoolAbortTest}} ("Tests that the EIP does not hang-threads 
due to thread-pools being exhausted and rejects new tasks") only passes because 
its lists have 2 elements, so the task's own re-schedule is rejected too.

Proposed fix: fail the multicast when a sub-exchange task is rejected. 
{{schedule()}} rethrows the {{RejectedExecutionException}} for a runnable that 
is not {{Rejectable}}. It propagates out of {{completion.submit(...)}} into the 
catch of {{MulticastReactiveTask.run()}}, which fails the exchange with it, the 
same way {{MulticastTask.reject()}} does for the task itself. The exception is 
the executor's own {{RejectedExecutionException}} (it names the pool), not the 
"Task rejected executing from ExecutorService" one of {{reject()}}. The 
alternative, completing the rejected sub-exchange as a failed sub-exchange so 
that {{stopOnException}} and the aggregation strategy see it, needs the task 
runner to run without an executor and is a larger change; the multicast task's 
own rejection already fails the whole exchange, so the fix does the same.

Only the parallel path is affected: {{schedule()}} only submits to the executor 
with {{parallelProcessing}}, and the other runnables it gets there (the 
multicast task itself) are {{Rejectable}}.

With a Recipient List, the producer of a recipient whose task was rejected is 
not released by this fix alone; the fix for CAMEL-24958 releases it.

A PR with the fix follows, with regression test 
{{MulticastParallelSubTaskRejectedTest}} (split with one element, multicast, 
recipient list, each on a pool with one thread, no queue and {{Abort}}). 
Without the fix every test fails with {{java.util.concurrent.TimeoutException}} 
after 5 s (the callback is never invoked); with it they complete with 
{{RejectedExecutionException}} and nothing stays inflight.

Found with a TLA+ model of the multicast task, then reproduced against 
4.23.0-SNAPSHOT.



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

Reply via email to