qianye1001 opened a new issue, #1321:
URL: https://github.com/apache/rocketmq-clients/issues/1321

   ### Before Creating the Bug Report
   
   - [x] I found a bug, not just a question.
   - [x] I searched existing issues and discussions and did not find a 
duplicate.
   - [x] I confirmed that the behavior is in this client repository.
   
   ### Programming Language of the Client
   
   Java
   
   ### Runtime Platform Environment
   
   Linux on Kubernetes. The fault was injected by an external h2c proxy between 
the Java client and RocketMQ Proxy; the client-to-proxy TCP connection and 
other HTTP/2 streams remained alive.
   
   ### RocketMQ Version of the Client/Server
   
   - Java client: current `master` at `9abb7f39ce9f74b41873a4f5253ab82af052d7a7`
   - Server: RocketMQ 5.x gRPC Proxy/Broker deployment
   
   ### Run or Compiler Version
   
   OpenJDK 11
   
   ### Describe the Bug
   
   `ProcessQueueImpl` can replace the attempt ID before a receive request has 
actually returned messages to the client:
   
   1. On a receive RPC failure, the current implementation preserves the 
request attempt ID only for `DEADLINE_EXCEEDED`. Other transport failures clear 
it, so the retry uses a new attempt ID.
   2. After a successful but empty receive response, the next receive also uses 
a new attempt ID.
   
   This is observable with FIFO consumption when the server has completed the 
receive/POP operation but the corresponding HTTP/2 response is lost. The 
previous attempt may still own the server-side FIFO order state. Retrying with 
a different attempt ID cannot recover that result and can be blocked by the 
existing order lock.
   
   An attempt ID should identify consecutive receive retries until a response 
actually contains messages, rather than identify every client-side RPC 
invocation.
   
   ### Steps to Reproduce
   
   1. Create a new FIFO topic and FIFO consumer group.
   2. Start a Java `PushConsumer` and send one FIFO message.
   3. Put an external HTTP/2-aware proxy in front of RocketMQ Proxy.
   4. After the server sends response DATA for one `ReceiveMessage` RPC, reset 
only that HTTP/2 stream. Keep the TCP connection and unrelated streams alive.
   5. Observe the receive error and the attempt IDs used by subsequent receive 
requests.
   6. Repeat the scenario several times because the timing depends on whether 
the server has completed POP before the stream is reset.
   
   In a deterministic run, the old client received `CANCELLED: RST_STREAM`, 
discarded the request attempt ID, generated new IDs for subsequent receives, 
returned only empty results, and did not invoke the message callback within 180 
seconds.
   
   For comparison, a response blackhole that ends as `DEADLINE_EXCEEDED` does 
not reproduce the same behavior because the old implementation already 
preserves the attempt ID for that status.
   
   ### What Did You Expect to See?
   
   - Reuse the request attempt ID after any failed receive RPC.
   - Reuse it after a successful response that contains no messages.
   - Generate a new attempt ID only after the raw receive response contains at 
least one message.
   - Preserve the existing acknowledgement and redelivery semantics.
   
   ### What Did You See Instead?
   
   After a non-deadline stream failure, the next request used a new attempt ID. 
In the FIFO scenario above, the new attempt was unable to recover the message 
associated with the previous attempt and remained blocked behind the existing 
FIFO order state.
   
   ### Additional Context
   
   With the proposed behavior, the retry after the same injected stream reset 
reused the previous attempt ID, received the original FIFO message in about one 
second with `deliveryAttempt=1`, and acknowledged it successfully.
   
   The decision to rotate must be based on messages in the raw receive 
response, before client-side filtering. If an interceptor filters every 
returned message, the server still returned messages for that attempt and the 
next receive should use a new ID.
   
   `SimpleConsumer` does not set an attempt ID in its receive request, so its 
behavior is outside the scope of this bug. This change does not provide 
exactly-once delivery and does not alter ACK behavior.
   


-- 
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]

Reply via email to