Skip to content

Commit bfb3d17

Browse files
authored
[ISSUE #8974] Support recalling of delay message (#8975)
1 parent 4571a85 commit bfb3d17

File tree

54 files changed

+2253
-4
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+2253
-4
lines changed

acl/src/main/java/org/apache/rocketmq/acl/plain/PlainAccessResource.java

+7
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import apache.rocketmq.v2.NotifyClientTerminationRequest;
2727
import apache.rocketmq.v2.QueryAssignmentRequest;
2828
import apache.rocketmq.v2.QueryRouteRequest;
29+
import apache.rocketmq.v2.RecallMessageRequest;
2930
import apache.rocketmq.v2.ReceiveMessageRequest;
3031
import apache.rocketmq.v2.Resource;
3132
import apache.rocketmq.v2.SendMessageRequest;
@@ -128,6 +129,9 @@ public static PlainAccessResource parse(RemotingCommand request, String remoteAd
128129
final String topicV2 = request.getExtFields().get("b");
129130
accessResource.addResourceAndPerm(topicV2, PlainAccessResource.isRetryTopic(topicV2) ? Permission.SUB : Permission.PUB);
130131
break;
132+
case RequestCode.RECALL_MESSAGE:
133+
accessResource.addResourceAndPerm(request.getExtFields().get("topic"), Permission.PUB);
134+
break;
131135
case RequestCode.CONSUMER_SEND_MSG_BACK:
132136
accessResource.addResourceAndPerm(getRetryTopic(request.getExtFields().get("group")), Permission.SUB);
133137
break;
@@ -232,6 +236,9 @@ public static PlainAccessResource parse(GeneratedMessageV3 messageV3, Authentica
232236
}
233237
}
234238
accessResource.addResourceAndPerm(topic, Permission.PUB);
239+
} else if (RecallMessageRequest.getDescriptor().getFullName().equals(rpcFullName)) {
240+
RecallMessageRequest request = (RecallMessageRequest) messageV3;
241+
accessResource.addResourceAndPerm(request.getTopic(), Permission.PUB);
235242
} else if (ReceiveMessageRequest.getDescriptor().getFullName().equals(rpcFullName)) {
236243
ReceiveMessageRequest request = (ReceiveMessageRequest) messageV3;
237244
accessResource.addGroupResourceAndPerm(request.getGroup(), Permission.SUB);

acl/src/test/java/org/apache/rocketmq/acl/plain/PlainAccessResourceTest.java

+37
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,15 @@
1919

2020
import java.util.HashMap;
2121
import java.util.Map;
22+
import apache.rocketmq.v2.RecallMessageRequest;
23+
import apache.rocketmq.v2.Resource;
24+
import com.google.protobuf.GeneratedMessageV3;
25+
import org.apache.rocketmq.acl.common.AuthenticationHeader;
2226
import org.apache.rocketmq.acl.common.Permission;
2327
import org.apache.rocketmq.common.MixAll;
2428
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
2529
import org.apache.rocketmq.remoting.protocol.RequestCode;
30+
import org.apache.rocketmq.remoting.protocol.header.RecallMessageRequestHeader;
2631
import org.apache.rocketmq.remoting.protocol.header.SendMessageRequestHeader;
2732
import org.apache.rocketmq.remoting.protocol.header.SendMessageRequestHeaderV2;
2833
import org.junit.Assert;
@@ -33,6 +38,8 @@ public class PlainAccessResourceTest {
3338
public static final String DEFAULT_PRODUCER_GROUP = "PID_acl";
3439
public static final String DEFAULT_CONSUMER_GROUP = "GID_acl";
3540
public static final String DEFAULT_REMOTE_ADDR = "192.128.1.1";
41+
public static final String AUTH_HEADER =
42+
"Signature Credential=1234567890/test, SignedHeaders=host, Signature=1234567890";
3643

3744
@Test
3845
public void testParseSendNormal() {
@@ -93,4 +100,34 @@ public void testParseSendRetryV2() {
93100

94101
Assert.assertEquals(permMap, accessResource.getResourcePermMap());
95102
}
103+
104+
@Test
105+
public void testParseRecallMessage() {
106+
// remoting
107+
RecallMessageRequestHeader requestHeader = new RecallMessageRequestHeader();
108+
requestHeader.setTopic(DEFAULT_TOPIC);
109+
requestHeader.setProducerGroup(DEFAULT_PRODUCER_GROUP);
110+
requestHeader.setRecallHandle("handle");
111+
RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.RECALL_MESSAGE, requestHeader);
112+
request.makeCustomHeaderToNet();
113+
114+
PlainAccessResource accessResource = PlainAccessResource.parse(request, DEFAULT_REMOTE_ADDR);
115+
Assert.assertTrue(Permission.PUB == accessResource.getResourcePermMap().get(DEFAULT_TOPIC));
116+
117+
// grpc
118+
GeneratedMessageV3 grpcRequest = RecallMessageRequest.newBuilder()
119+
.setTopic(Resource.newBuilder().setName(DEFAULT_TOPIC).build())
120+
.setRecallHandle("handle")
121+
.build();
122+
accessResource = PlainAccessResource.parse(grpcRequest, mockAuthenticationHeader());
123+
Assert.assertTrue(Permission.PUB == accessResource.getResourcePermMap().get(DEFAULT_TOPIC));
124+
}
125+
126+
private AuthenticationHeader mockAuthenticationHeader() {
127+
return AuthenticationHeader.builder()
128+
.remoteAddress(DEFAULT_REMOTE_ADDR)
129+
.authorization(AUTH_HEADER)
130+
.datetime("datetime")
131+
.build();
132+
}
96133
}

auth/src/main/java/org/apache/rocketmq/auth/authorization/builder/DefaultAuthorizationContextBuilder.java

+9
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import apache.rocketmq.v2.NotifyClientTerminationRequest;
2626
import apache.rocketmq.v2.QueryAssignmentRequest;
2727
import apache.rocketmq.v2.QueryRouteRequest;
28+
import apache.rocketmq.v2.RecallMessageRequest;
2829
import apache.rocketmq.v2.ReceiveMessageRequest;
2930
import apache.rocketmq.v2.SendMessageRequest;
3031
import apache.rocketmq.v2.Subscription;
@@ -101,6 +102,10 @@ public List<DefaultAuthorizationContext> build(Metadata metadata, GeneratedMessa
101102
}
102103
result = newPubContext(metadata, request.getMessages(0).getTopic());
103104
}
105+
if (message instanceof RecallMessageRequest) {
106+
RecallMessageRequest request = (RecallMessageRequest) message;
107+
result = newPubContext(metadata, request.getTopic());
108+
}
104109
if (message instanceof EndTransactionRequest) {
105110
EndTransactionRequest request = (EndTransactionRequest) message;
106111
result = newPubContext(metadata, request.getTopic());
@@ -207,6 +212,10 @@ public List<DefaultAuthorizationContext> build(ChannelHandlerContext context, Re
207212
result.add(DefaultAuthorizationContext.of(subject, topic, Action.PUB, sourceIp));
208213
}
209214
break;
215+
case RequestCode.RECALL_MESSAGE:
216+
topic = Resource.ofTopic(fields.get(TOPIC));
217+
result.add(DefaultAuthorizationContext.of(subject, topic, Action.PUB, sourceIp));
218+
break;
210219
case RequestCode.END_TRANSACTION:
211220
if (StringUtils.isNotBlank(fields.get(TOPIC))) {
212221
topic = Resource.ofTopic(fields.get(TOPIC));

auth/src/test/java/org/apache/rocketmq/auth/authorization/builder/DefaultAuthorizationContextBuilderTest.java

+31
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import apache.rocketmq.v2.Publishing;
2929
import apache.rocketmq.v2.QueryAssignmentRequest;
3030
import apache.rocketmq.v2.QueryRouteRequest;
31+
import apache.rocketmq.v2.RecallMessageRequest;
3132
import apache.rocketmq.v2.ReceiveMessageRequest;
3233
import apache.rocketmq.v2.Resource;
3334
import apache.rocketmq.v2.SendMessageRequest;
@@ -65,6 +66,7 @@
6566
import org.apache.rocketmq.remoting.protocol.header.PullMessageRequestHeader;
6667
import org.apache.rocketmq.remoting.protocol.header.QueryConsumerOffsetRequestHeader;
6768
import org.apache.rocketmq.remoting.protocol.header.QueryMessageRequestHeader;
69+
import org.apache.rocketmq.remoting.protocol.header.RecallMessageRequestHeader;
6870
import org.apache.rocketmq.remoting.protocol.header.SendMessageRequestHeader;
6971
import org.apache.rocketmq.remoting.protocol.header.SendMessageRequestHeaderV2;
7072
import org.apache.rocketmq.remoting.protocol.header.UnregisterClientRequestHeader;
@@ -122,6 +124,19 @@ public void buildGrpc() {
122124
Assert.assertEquals(result.get(0).getChannelId(), "channel-id");
123125
Assert.assertEquals(result.get(0).getRpcCode(), SendMessageRequest.getDescriptor().getFullName());
124126

127+
request = RecallMessageRequest.newBuilder()
128+
.setTopic(Resource.newBuilder().setName("topic").build())
129+
.setRecallHandle("handle")
130+
.build();
131+
result = builder.build(metadata, request);
132+
Assert.assertEquals(1, result.size());
133+
Assert.assertEquals(result.get(0).getSubject().getSubjectKey(), "User:rocketmq");
134+
Assert.assertEquals(result.get(0).getResource().getResourceKey(), "Topic:topic");
135+
Assert.assertTrue(result.get(0).getActions().containsAll(Arrays.asList(Action.PUB)));
136+
Assert.assertEquals(result.get(0).getSourceIp(), "192.168.0.1");
137+
Assert.assertEquals(result.get(0).getChannelId(), "channel-id");
138+
Assert.assertEquals(result.get(0).getRpcCode(), RecallMessageRequest.getDescriptor().getFullName());
139+
125140
request = EndTransactionRequest.newBuilder()
126141
.setTopic(Resource.newBuilder().setName("topic").build())
127142
.build();
@@ -315,6 +330,22 @@ public void buildRemoting() {
315330
Assert.assertEquals("Group:group", result.get(0).getResource().getResourceKey());
316331
Assert.assertTrue(result.get(0).getActions().containsAll(Arrays.asList(Action.SUB)));
317332

333+
RecallMessageRequestHeader recallMessageRequestHeader = new RecallMessageRequestHeader();
334+
recallMessageRequestHeader.setTopic("topic");
335+
recallMessageRequestHeader.setRecallHandle("handle");
336+
request = RemotingCommand.createRequestCommand(RequestCode.RECALL_MESSAGE, recallMessageRequestHeader);
337+
request.setVersion(441);
338+
request.addExtField("AccessKey", "rocketmq");
339+
request.makeCustomHeaderToNet();
340+
result = builder.build(channelHandlerContext, request);
341+
Assert.assertEquals(1, result.size());
342+
Assert.assertEquals("User:rocketmq", result.get(0).getSubject().getSubjectKey());
343+
Assert.assertEquals("Topic:topic", result.get(0).getResource().getResourceKey());
344+
Assert.assertTrue(result.get(0).getActions().containsAll(Arrays.asList(Action.PUB)));
345+
Assert.assertEquals("192.168.0.1", result.get(0).getSourceIp());
346+
Assert.assertEquals("channel-id", result.get(0).getChannelId());
347+
Assert.assertEquals(RequestCode.RECALL_MESSAGE + "", result.get(0).getRpcCode());
348+
318349
EndTransactionRequestHeader endTransactionRequestHeader = new EndTransactionRequestHeader();
319350
endTransactionRequestHeader.setTopic("topic");
320351
request = RemotingCommand.createRequestCommand(RequestCode.END_TRANSACTION, endTransactionRequestHeader);

broker/src/main/java/org/apache/rocketmq/broker/BrokerController.java

+9
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
import org.apache.rocketmq.broker.processor.PullMessageProcessor;
9494
import org.apache.rocketmq.broker.processor.QueryAssignmentProcessor;
9595
import org.apache.rocketmq.broker.processor.QueryMessageProcessor;
96+
import org.apache.rocketmq.broker.processor.RecallMessageProcessor;
9697
import org.apache.rocketmq.broker.processor.ReplyMessageProcessor;
9798
import org.apache.rocketmq.broker.processor.SendMessageProcessor;
9899
import org.apache.rocketmq.broker.schedule.ScheduleMessageService;
@@ -210,6 +211,7 @@ public class BrokerController {
210211
protected final QueryAssignmentProcessor queryAssignmentProcessor;
211212
protected final ClientManageProcessor clientManageProcessor;
212213
protected final SendMessageProcessor sendMessageProcessor;
214+
protected final RecallMessageProcessor recallMessageProcessor;
213215
protected final ReplyMessageProcessor replyMessageProcessor;
214216
protected final PullRequestHoldService pullRequestHoldService;
215217
protected final MessageArrivingListener messageArrivingListener;
@@ -369,6 +371,7 @@ public BrokerController(
369371
this.ackMessageProcessor = new AckMessageProcessor(this);
370372
this.changeInvisibleTimeProcessor = new ChangeInvisibleTimeProcessor(this);
371373
this.sendMessageProcessor = new SendMessageProcessor(this);
374+
this.recallMessageProcessor = new RecallMessageProcessor(this);
372375
this.replyMessageProcessor = new ReplyMessageProcessor(this);
373376
this.messageArrivingListener = new NotifyMessageArrivingListener(this.pullRequestHoldService, this.popMessageProcessor, this.notificationProcessor);
374377
this.consumerIdsChangeListener = new DefaultConsumerIdsChangeListener(this);
@@ -1096,10 +1099,12 @@ public void registerProcessor() {
10961099
this.remotingServer.registerProcessor(RequestCode.SEND_MESSAGE_V2, sendMessageProcessor, this.sendMessageExecutor);
10971100
this.remotingServer.registerProcessor(RequestCode.SEND_BATCH_MESSAGE, sendMessageProcessor, this.sendMessageExecutor);
10981101
this.remotingServer.registerProcessor(RequestCode.CONSUMER_SEND_MSG_BACK, sendMessageProcessor, this.sendMessageExecutor);
1102+
this.remotingServer.registerProcessor(RequestCode.RECALL_MESSAGE, recallMessageProcessor, this.sendMessageExecutor);
10991103
this.fastRemotingServer.registerProcessor(RequestCode.SEND_MESSAGE, sendMessageProcessor, this.sendMessageExecutor);
11001104
this.fastRemotingServer.registerProcessor(RequestCode.SEND_MESSAGE_V2, sendMessageProcessor, this.sendMessageExecutor);
11011105
this.fastRemotingServer.registerProcessor(RequestCode.SEND_BATCH_MESSAGE, sendMessageProcessor, this.sendMessageExecutor);
11021106
this.fastRemotingServer.registerProcessor(RequestCode.CONSUMER_SEND_MSG_BACK, sendMessageProcessor, this.sendMessageExecutor);
1107+
this.fastRemotingServer.registerProcessor(RequestCode.RECALL_MESSAGE, recallMessageProcessor, this.sendMessageExecutor);
11031108
/**
11041109
* PullMessageProcessor
11051110
*/
@@ -2424,6 +2429,10 @@ public SendMessageProcessor getSendMessageProcessor() {
24242429
return sendMessageProcessor;
24252430
}
24262431

2432+
public RecallMessageProcessor getRecallMessageProcessor() {
2433+
return recallMessageProcessor;
2434+
}
2435+
24272436
public QueryAssignmentProcessor getQueryAssignmentProcessor() {
24282437
return queryAssignmentProcessor;
24292438
}

0 commit comments

Comments
 (0)