Repository: apache/rocketmq (Java)
Date: 2023-01-09 04:08:30+00:00
Task type: Bug Fix

Issue:
Code.ILLEGAL_POLLING_TIME is not compatible with gRPC Client <=5.0.2
`Code.ILLEGAL_PILLING_TIME` is introduced in `rocketmq-proto` 2.0.1, which is integrated by [gRPC client 5.0.3](https://github.com/apache/rocketmq-clients/releases/tag/java-5.0.3), so it is not compatible with the older client.





Issue discussion:

Solution patch:
diff --git a/proxy/src/main/java/org/apache/rocketmq/proxy/grpc/v2/consumer/ReceiveMessageActivity.java b/proxy/src/main/java/org/apache/rocketmq/proxy/grpc/v2/consumer/ReceiveMessageActivity.java
--- a/proxy/src/main/java/org/apache/rocketmq/proxy/grpc/v2/consumer/ReceiveMessageActivity.java
+++ b/proxy/src/main/java/org/apache/rocketmq/proxy/grpc/v2/consumer/ReceiveMessageActivity.java
@@ -49,6 +49,7 @@
 
 public class ReceiveMessageActivity extends AbstractMessingActivity {
     protected ReceiptHandleProcessor receiptHandleProcessor;
+    private static final String ILLEGAL_POLLING_TIME_INTRODUCED_CLIENT_VERSION = "5.0.3";
 
     public ReceiveMessageActivity(MessagingProcessor messagingProcessor, ReceiptHandleProcessor receiptHandleProcessor,
         GrpcClientSettingsManager grpcClientSettingsManager, GrpcChannelManager grpcChannelManager) {
@@ -85,7 +86,11 @@ public void receiveMessage(ProxyContext ctx, ReceiveMessageRequest request,
                 if (timeRemaining >= config.getGrpcClientConsumerMinLongPollingTimeoutMillis()) {
                     pollingTime = timeRemaining;
                 } else {
-                    writer.writeAndComplete(ctx, Code.ILLEGAL_POLLING_TIME, "The deadline time remaining is not enough" +
+                    final String clientVersion = ctx.getClientVersion();
+                    Code code =
+                        null == clientVersion || ILLEGAL_POLLING_TIME_INTRODUCED_CLIENT_VERSION.compareTo(clientVersion) > 0 ?
+                        Code.BAD_REQUEST : Code.ILLEGAL_POLLING_TIME;
+                    writer.writeAndComplete(ctx, code, "The deadline time remaining is not enough" +
                         " for polling, please check network condition");
                     return;
                 }


Test patch:
diff --git a/proxy/src/test/java/org/apache/rocketmq/proxy/grpc/v2/consumer/ReceiveMessageActivityTest.java b/proxy/src/test/java/org/apache/rocketmq/proxy/grpc/v2/consumer/ReceiveMessageActivityTest.java
--- a/proxy/src/test/java/org/apache/rocketmq/proxy/grpc/v2/consumer/ReceiveMessageActivityTest.java
+++ b/proxy/src/test/java/org/apache/rocketmq/proxy/grpc/v2/consumer/ReceiveMessageActivityTest.java
@@ -25,6 +25,7 @@
 import apache.rocketmq.v2.ReceiveMessageResponse;
 import apache.rocketmq.v2.Resource;
 import apache.rocketmq.v2.Settings;
+import com.google.protobuf.Duration;
 import com.google.protobuf.util.Durations;
 import io.grpc.stub.ServerCallStreamObserver;
 import io.grpc.stub.StreamObserver;
@@ -112,6 +113,47 @@ public void testReceiveMessagePollingTime() {
         assertEquals(0L, pollTimeCaptor.getValue().longValue());
     }
 
+    @Test
+    public void testReceiveMessageWithIllegalPollingTime() {
+        StreamObserver<ReceiveMessageResponse> receiveStreamObserver = mock(ServerCallStreamObserver.class);
+        ArgumentCaptor<ReceiveMessageResponse> responseArgumentCaptor0 = ArgumentCaptor.forClass(ReceiveMessageResponse.class);
+        doNothing().when(receiveStreamObserver).onNext(responseArgumentCaptor0.capture());
+
+        when(this.grpcClientSettingsManager.getClientSettings(any())).thenReturn(Settings.newBuilder().getDefaultInstanceForType());
+
+        final ProxyContext context = createContext();
+        context.setClientVersion("5.0.2");
+        context.setRemainingMs(-1L);
+        final ReceiveMessageRequest request = ReceiveMessageRequest.newBuilder()
+            .setGroup(Resource.newBuilder().setName(CONSUMER_GROUP).build())
+            .setMessageQueue(MessageQueue.newBuilder().setTopic(Resource.newBuilder().setName(TOPIC).build()).build())
+            .setAutoRenew(false)
+            .setLongPollingTimeout(Duration.newBuilder().setSeconds(20).build())
+            .setFilterExpression(FilterExpression.newBuilder()
+                .setType(FilterType.TAG)
+                .setExpression("*")
+                .build())
+            .build();
+        this.receiveMessageActivity.receiveMessage(
+            context,
+            request,
+            receiveStreamObserver
+        );
+        assertEquals(Code.BAD_REQUEST, getResponseCodeFromReceiveMessageResponseList(responseArgumentCaptor0.getAllValues()));
+
+        ArgumentCaptor<ReceiveMessageResponse> responseArgumentCaptor1 =
+            ArgumentCaptor.forClass(ReceiveMessageResponse.class);
+        doNothing().when(receiveStreamObserver).onNext(responseArgumentCaptor1.capture());
+        context.setClientVersion("5.0.3");
+        this.receiveMessageActivity.receiveMessage(
+            context,
+            request,
+            receiveStreamObserver
+        );
+        assertEquals(Code.ILLEGAL_POLLING_TIME,
+            getResponseCodeFromReceiveMessageResponseList(responseArgumentCaptor1.getAllValues()));
+    }
+
     @Test
     public void testReceiveMessageIllegalFilter() {
         StreamObserver<ReceiveMessageResponse> receiveStreamObserver = mock(ServerCallStreamObserver.class);