ai-yang opened a new issue, #10739:
URL: https://github.com/apache/rocketmq/issues/10739
## RocketMQ version
`develop` at `00e45b8a6db23efbe756d0306f10716156cfd4dd`
## Describe the bug
`FutureUtils.appendNextFuture` ignores the dependent stage returned by
`whenCompleteAsync`. If the supplied executor rejects the completion task,
that
dependent stage completes exceptionally but the manually created `nextFuture`
is never completed.
The production executors used by `ProducerProcessor` and `ConsumerProcessor`
add a second failure mode. They are created through the default
`ThreadPoolMonitor.createAndMonitor` overload, whose rejection handler is
`DiscardOldestPolicy`. After shutdown it silently discards the completion
task;
under saturation it can silently discard an older queued completion task.
Neither case gives `FutureUtils` a rejection that it can propagate, so a
proxy
request future can remain pending indefinitely.
## Deterministic reproduction
Two synchronous regression tests reproduce the complete failure chain on JDK
8.
### 1. Rejection is not propagated by `FutureUtils`
1. Create a single-thread executor and shut it down.
2. Call `FutureUtils.addExecutor(CompletableFuture.completedFuture("value"),
executor)`.
3. Inspect the returned future.
Expected: the returned future is completed exceptionally with the scheduling
failure.
Actual: the stage returned by `whenCompleteAsync` is exceptional, but the
stage
is ignored and the returned `nextFuture` remains pending.
The controlled test
`FutureUtilsTest#testAddExecutorCompletesExceptionallyWhenExecutorRejectsTask`
failed at the expected `result.isDone()` assertion in 5/5 runs.
### 2. The actual Proxy processor executor silently drops the task
1. Construct `DefaultMessagingProcessor` with its real producer and consumer
processor executors.
2. Shut down the producer processor executor.
3. Pass that executor to `FutureUtils.addExecutor` with an already completed
source future.
4. Inspect the returned future.
Expected: rejection is observable and the returned future is completed
exceptionally.
Actual: `DiscardOldestPolicy` silently discards the task after shutdown and
the
returned future remains pending.
The controlled test
`DefaultMessagingProcessorTest#testProcessorFutureCompletesWhenExecutorIsShutDown`
failed at the expected `result.isDone()` assertion in 5/5 runs. It uses the
actual processor pool, no sleeps, randomized scheduling, network access, or
external service.
## Impact
`FutureUtils.addExecutor` is used by the Proxy `ProducerProcessor` and
`ConsumerProcessor` request paths. During processor-pool shutdown, or when
the
bounded pool rejects completion work, callers may receive a future that never
reaches a terminal state. This can leave gRPC/remoting requests waiting
until an
outer timeout or connection teardown instead of receiving an immediate
failure.
## Suggested fix
Both parts are needed; either one alone leaves a pending-future path:
- Retain the stage returned by `whenCompleteAsync` and propagate a scheduling
failure into `nextFuture`.
- Create the producer and consumer processor executors with an explicit
throwing rejection policy (for example `AbortPolicy`) instead of the
default
silent `DiscardOldestPolicy`, so `FutureUtils` can observe both shutdown
and
overload rejection.
- Add regression coverage for both a throwing executor and the actual Proxy
processor executor after shutdown.
This changes only internal completion/rejection behavior and does not change
a
public protocol.
## Related work checked
- #8900 contains a `FutureUtils` stack frame but reports client cancellation
and
message redelivery, not executor rejection or a pending returned future.
- #9253 concerns receipt-handle renewal after client disconnection, not
completion-task rejection.
- #5575 introduced the Proxy remoting implementation and is not a fix for
this
behavior.
- #10711 concerns unsupported metadata futures and does not modify
`FutureUtils` or the processor executor policies.
Searches across open and closed issues and pull requests for `FutureUtils`,
`addExecutor`, `DefaultMessagingProcessor`, `DiscardOldestPolicy`, executor
shutdown/rejection, and pending Proxy futures found no equivalent report or
claimed fix.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]