Merge remote-tracking branch 'apache/5.0.0-beta' into 5.0.0-beta-tmp

# Conflicts:
#	broker/src/main/java/org/apache/rocketmq/broker/processor/PopMessageProcessor.java
This commit is contained in:
RongtongJin
2022-03-19 09:41:42 +08:00
34 changed files with 1636 additions and 8 deletions
+39
View File
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>rocketmq-all</artifactId>
<groupId>org.apache.rocketmq</groupId>
<version>5.0.0-BETA-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<artifactId>rocketmq-apis</artifactId>
<name>rocketmq-apis ${project.version}</name>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,61 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis;
import static com.google.common.base.Preconditions.checkNotNull;
import java.time.Duration;
/**
* Common client configuration.
*/
public class ClientConfiguration {
private final String endpoints;
private final SessionCredentialsProvider sessionCredentialsProvider;
private final Duration requestTimeout;
private final boolean enableTracing;
public static ClientConfigurationBuilder newBuilder() {
return new ClientConfigurationBuilder();
}
public ClientConfiguration(String endpoints, SessionCredentialsProvider sessionCredentialsProvider,
Duration requestTimeout, boolean enableTracing) {
this.endpoints = checkNotNull(endpoints, "endpoints should not be null");
this.sessionCredentialsProvider = checkNotNull(sessionCredentialsProvider, "credentialsProvider should not be"
+ " null");
this.requestTimeout = checkNotNull(requestTimeout, "requestTimeout should be not null");
this.enableTracing = enableTracing;
}
public String getEndpoints() {
return endpoints;
}
public SessionCredentialsProvider getCredentialsProvider() {
return sessionCredentialsProvider;
}
public Duration getRequestTimeout() {
return requestTimeout;
}
public boolean isEnableTracing() {
return enableTracing;
}
}
@@ -0,0 +1,72 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis;
import static com.google.common.base.Preconditions.checkNotNull;
import java.time.Duration;
/**
* Builder to set {@link ClientConfiguration}.
*/
public class ClientConfigurationBuilder {
private String endpoints;
private SessionCredentialsProvider sessionCredentialsProvider;
private Duration requestTimeout;
private boolean enableTracing;
/**
* Configure the endpoints with which the SDK should communicate.
*
* <p>Endpoints here means address of service, complying with the following scheme(part square brackets is
* optional).
* <p>1. DNS scheme(default): dns:host[:port], host is the host to resolve via DNS, port is the port to return
* for each address. If not specified, 443 is used.
* <p>2. ipv4 scheme: ipv4:address:port[,address:port,...]
* <p>3. ipv6 scheme: ipv6:address:port[,address:port,...]
* <p>4. http/https scheme: http|https://host[:port], similar to DNS scheme, if port not specified, 443 is used.
*
* @param endpoints address of service.
* @return the client configuration builder instance.
*/
public ClientConfigurationBuilder setEndpoints(String endpoints) {
checkNotNull(endpoints, "endpoints should not be not null");
this.endpoints = endpoints;
return this;
}
public ClientConfigurationBuilder setCredentialProvider(SessionCredentialsProvider sessionCredentialsProvider) {
this.sessionCredentialsProvider = checkNotNull(sessionCredentialsProvider, "credentialsProvider should not be "
+ "null");
return this;
}
public ClientConfigurationBuilder setRequestTimeout(Duration requestTimeout) {
this.requestTimeout = checkNotNull(requestTimeout, "requestTimeout should not be not null");
return this;
}
public ClientConfigurationBuilder enableTracing(boolean enableTracing) {
this.enableTracing = enableTracing;
return this;
}
public ClientConfiguration build() {
return new ClientConfiguration(endpoints, sessionCredentialsProvider, requestTimeout, enableTracing);
}
}
@@ -0,0 +1,52 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis;
import java.util.Iterator;
import java.util.ServiceLoader;
import org.apache.rocketmq.apis.message.MessageBuilder;
import org.apache.rocketmq.apis.producer.ProducerBuilder;
/**
* Service provider to seek client, which load client according to
* <a href="https://en.wikipedia.org/wiki/Service_provider_interface">Java SPI mechanism</a>.
*/
public interface ClientServiceProvider {
static ClientServiceProvider loadService() {
final ServiceLoader<ClientServiceProvider> loaders = ServiceLoader.load(ClientServiceProvider.class);
final Iterator<ClientServiceProvider> iterators = loaders.iterator();
if (iterators.hasNext()) {
return iterators.next();
}
throw new UnsupportedOperationException("Client service provider not found");
}
/**
* Get the producer builder by current provider.
*
* @return the producer builder instance.
*/
ProducerBuilder newProducerBuilder();
/**
* Get the message builder by current provider.
*
* @return the message builder instance.
*/
MessageBuilder newMessageBuilder();
}
@@ -0,0 +1,24 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis;
public interface MessageQueue {
String getTopic();
String getId();
}
@@ -0,0 +1,58 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Optional;
/**
* Session credentials used in service authentications.
*/
public class SessionCredentials {
private final String accessKey;
private final String accessSecret;
private final String securityToken;
public SessionCredentials(String accessKey, String accessSecret, String securityToken) {
this.accessKey = checkNotNull(accessKey, "accessKey should not be null");
this.accessSecret = checkNotNull(accessSecret, "accessSecret should not be null");
this.securityToken = checkNotNull(securityToken, "securityToken should not be null");
}
public SessionCredentials(String accessKey, String accessSecret) {
this.accessKey = checkNotNull(accessKey, "accessKey should not be null");
this.accessSecret = checkNotNull(accessSecret, "accessSecret should not be null");
this.securityToken = null;
}
public String getAccessKey() {
return accessKey;
}
public String getAccessSecret() {
return accessSecret;
}
public Optional<String> getSecurityToken() {
if (null == securityToken) {
return Optional.empty();
}
return Optional.of(securityToken);
}
}
@@ -0,0 +1,30 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis;
/**
* Abstract provider to provide {@link SessionCredentials}.
*/
public interface SessionCredentialsProvider {
/**
* Get the provided credentials.
*
* @return provided credentials.
*/
SessionCredentials getCredentials();
}
@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis;
public class StaticSessionCredentialsProvider implements SessionCredentialsProvider {
private final SessionCredentials credentials;
public StaticSessionCredentialsProvider(String accessKey, String accessSecret) {
this.credentials = new SessionCredentials(accessKey, accessSecret);
}
public StaticSessionCredentialsProvider(String accessKey, String accessSecret, String securityToken) {
this.credentials = new SessionCredentials(accessKey, accessSecret, securityToken);
}
@Override
public SessionCredentials getCredentials() {
return credentials;
}
}
@@ -0,0 +1,31 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis.exception;
/**
* The difference between {@link AuthorisationException} and {@link AuthenticationException} is that
* {@link AuthenticationException} here means current user's identity could not be recognized.
*
* <p>For example, {@link AuthenticationException} will be thrown if access key is invalid.
*/
public class AuthenticationException extends ClientException {
public AuthenticationException(ErrorCode code, String message, String requestId) {
super(code, message);
putMetadata(REQUEST_ID_KEY, requestId);
}
}
@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis.exception;
import org.apache.rocketmq.apis.message.Message;
import org.apache.rocketmq.apis.producer.Producer;
/**
* The difference between {@link AuthenticationException} and {@link AuthorisationException} is that
* {@link AuthorisationException} here means current users don't have permission to do current operation.
*
* <p>For example, current user is forbidden to send message to this topic, {@link AuthorisationException} will be
* thrown in {@link Producer#send(Message)}.
*/
public class AuthorisationException extends ClientException {
public AuthorisationException(ErrorCode code, String message, String requestId) {
super(code, message);
putMetadata(REQUEST_ID_KEY, requestId);
}
}
@@ -0,0 +1,72 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis.exception;
import com.google.common.base.MoreObjects;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
/**
* Base exception for all exception raised in client, each exception should derive from current class.
* It should throw exception which is derived from {@link ClientException} rather than {@link ClientException} itself.
*/
public abstract class ClientException extends Exception {
/**
* For those {@link ClientException} along with a remote procedure call, request id could be used to track the
* request.
*/
protected static final String REQUEST_ID_KEY = "request-id";
private final ErrorCode errorCode;
private final Map<String, String> context;
ClientException(ErrorCode errorCode, String message, Throwable cause) {
super(message, cause);
this.errorCode = errorCode;
this.context = new HashMap<>();
}
ClientException(ErrorCode errorCode, String message) {
super(message);
this.errorCode = errorCode;
this.context = new HashMap<>();
}
@SuppressWarnings("SameParameterValue")
protected void putMetadata(String key, String value) {
context.put(key, value);
}
public Optional<String> getRequestId() {
final String requestId = context.get(REQUEST_ID_KEY);
return null == requestId ? Optional.empty() : Optional.of(requestId);
}
public ErrorCode getErrorCode() {
return errorCode;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(super.toString())
.add("errorCode", errorCode)
.add("context", context)
.toString();
}
}
@@ -0,0 +1,84 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis.exception;
/**
* Indicates the reason why the exception is thrown, it can be easily divided into the following categories.
*
* <blockquote>
*
* <table>
* <caption>Error Categories and Exceptions</caption>
* <tr>
* <th>Category
* <th>Exception
* <th>Code range
* <tr>
* <td>Illegal client argument
* <td>{@link RemoteIllegalArgumentException}
* <p>{@link IllegalArgumentException}
* <td>{@code [101..199]}
* <tr>
* <td>Authorisation failure
* <td>{@link AuthorisationException}
* <td>{@code [201..299]}
* <tr>
* <td>Resource not found
* <td>{@link ResourceNotFoundException}
* <td>{@code [301..399]}
* </table>
*
* </blockquote>
*/
public enum ErrorCode {
/**
* Format of topic is illegal.
*/
INVALID_TOPIC(101),
/**
* Format of consumer group is illegal.
*/
INVALID_CONSUMER_GROUP(102),
/**
* Message is forbidden to publish.
*/
MESSAGE_PUBLISH_FORBIDDEN(201),
/**
* Topic does not exist.
*/
TOPIC_DOES_NOT_EXIST(301),
/**
* Consumer group does not exist.
*/
CONSUMER_GROUP_DOES_NOT_EXIST(302);
private final int code;
ErrorCode(int code) {
this.code = code;
}
public int getCode() {
return code;
}
@Override
public String toString() {
return String.valueOf(code);
}
}
@@ -0,0 +1,25 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis.exception;
public class FlowControlException extends ClientException {
public FlowControlException(ErrorCode code, String message, String requestId) {
super(code, message);
putMetadata(REQUEST_ID_KEY, requestId);
}
}
@@ -0,0 +1,28 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis.exception;
public class NetworkException extends ClientException {
public NetworkException(ErrorCode code, String message, Throwable cause) {
super(code, message, cause);
}
public NetworkException(ErrorCode code, String message) {
super(code, message);
}
}
@@ -0,0 +1,25 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis.exception;
public class RemoteIllegalArgumentException extends ClientException {
public RemoteIllegalArgumentException(ErrorCode code, String message, String requestId) {
super(code, message);
putMetadata(REQUEST_ID_KEY, requestId);
}
}
@@ -0,0 +1,25 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis.exception;
public class ResourceNotFoundException extends ClientException {
public ResourceNotFoundException(ErrorCode code, String message, String requestId) {
super(code, message);
putMetadata(REQUEST_ID_KEY, requestId);
}
}
@@ -0,0 +1,24 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis.exception;
public class ResourceNotMatchException extends ClientException {
public ResourceNotMatchException(ErrorCode code, String message) {
super(code, message);
}
}
@@ -0,0 +1,28 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis.exception;
public class TimeoutException extends ClientException {
public TimeoutException(ErrorCode code, String message, Throwable cause) {
super(code, message, cause);
}
public TimeoutException(ErrorCode code, String message) {
super(code, message);
}
}
@@ -0,0 +1,77 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis.message;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import org.apache.rocketmq.apis.producer.Producer;
/**
* Abstract message only used for {@link Producer}.
*/
public interface Message {
/**
* Get the topic of message, which is the first classifier for message.
*
* @return topic of message.
*/
String getTopic();
/**
* Get the <strong>deep copy</strong> of message body.
*
* @return the <strong>deep copy</strong> of message body.
*/
byte[] getBody();
/**
* Get the <strong>deep copy</strong> of message properties.
*
* @return the <strong>deep copy</strong> of message properties.
*/
Map<String, String> getProperties();
/**
* Get the tag of message, which is the second classifier besides topic.
*
* @return the tag of message.
*/
Optional<String> getTag();
/**
* Get the key collection of message.
*
* @return <strong>the key collection</strong> of message.
*/
Collection<String> getKeys();
/**
* Get the message group, which make sense only when topic type is fifo.
*
* @return message group, which is optional.
*/
Optional<String> getMessageGroup();
/**
* Get the expected delivery timestamp, which make sense only when topic type is delay.
*
* @return message expected delivery timestamp, which is optional.
*/
Optional<Long> getDeliveryTimestamp();
}
@@ -0,0 +1,91 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis.message;
import java.util.Collection;
/**
* Builder to config {@link Message}.
*/
public interface MessageBuilder {
/**
* Set the topic for message.
*
* @param topic topic for the message.
* @return the message builder instance.
*/
MessageBuilder setTopic(String topic);
/**
* Set the body for message.
*
* @param body body for the message.
* @return the message builder instance.
*/
MessageBuilder setBody(byte[] body);
/**
* Set the tag for message.
*
* @param tag tag for the message.
* @return the message builder instance.
*/
MessageBuilder setTag(String tag);
/**
* Set the key for message.
*
* @param key key for the message.
* @return the message builder instance.
*/
MessageBuilder setKey(String key);
/**
* Set the key collection for message.
*
* @param keys key collection for the message.
* @return the message builder instance.
*/
MessageBuilder setKeys(Collection<String> keys);
/**
* Set the group for message.
*
* @param messageGroup group for the message.
* @return the message builder instance.
*/
MessageBuilder setMessageGroup(String messageGroup);
/**
* Add user property for message.
*
* @param key single property key.
* @param value single property value.
* @return the message builder instance.
*/
MessageBuilder addProperty(String key, String value);
/**
* Finalize the build of the {@link Message} instance.
*
* <p>Unique {@link MessageId} is generated after message building.</p>
*
* @return the message instance.
*/
Message build();
}
@@ -0,0 +1,38 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis.message;
/**
* Abstract message id, the implement must override {@link Object#toString()}, which indicates the message id using
* string form.
*/
public interface MessageId {
/**
* Get the version of message id.
*
* @return the version of message id.
*/
MessageIdVersion getVersion();
/**
* The implementation <strong>must</strong> override this method, which indicates the message id using string form.
*
* @return string-formed string id.
*/
String toString();
}
@@ -0,0 +1,29 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis.message;
public enum MessageIdVersion {
/**
* V0 version, whose length is 32.
*/
V0,
/**
* V1 version, whose length is 34 and begins with "01".
*/
V1
}
@@ -0,0 +1,121 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis.message;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import org.apache.rocketmq.apis.MessageQueue;
/**
* {@link MessageView} provides a read-only view for message, that's why setters do not exist here. In addition,
* it only makes sense when {@link Message} is sent successfully, or it could be considered as a return receipt
* for producer/consumer.
*/
public interface MessageView {
/**
* Get the unique id of message.
*
* @return unique id.
*/
MessageId getMessageId();
/**
* Get the topic of message.
*
* @return topic of message.
*/
String getTopic();
/**
* Get the <strong>deep copy</strong> of message body, which makes the modification of return value does not
* affect the message itself.
*
* @return the <strong>deep copy</strong> of message body.
*/
byte[] getBody();
/**
* Get the <strong>deep copy</strong> of message properties, which makes the modification of return value does
* not affect the message itself.
*
* @return the <strong>deep copy</strong> of message properties.
*/
Map<String, String> getProperties();
/**
* Get the tag of message, which is optional.
*
* @return the tag of message, which is optional.
*/
Optional<String> getTag();
/**
* Get the key collection of message.
*
* @return <strong>the key collection</strong> of message.
*/
Collection<String> getKeys();
/**
* Get the message group, which is optional and only make sense only when topic type is fifo.
*
* @return message group, which is optional.
*/
Optional<String> getMessageGroup();
/**
* Get the expected delivery timestamp, which make sense only when topic type is delay.
*
* @return message expected delivery timestamp, which is optional.
*/
Optional<Long> getDeliveryTimestamp();
/**
* Get the born host of message.
*
* @return born host of message.
*/
String getBornHost();
/**
* Get the born timestamp of message.
*
* @return born timestamp of message.
*/
long getBornTimestamp();
/**
* Get the delivery attempt for message.
*
* @return delivery attempt.
*/
int getDeliveryAttempt();
/**
* Get the {@link MessageQueue} of message.
*
* @return message queue.
*/
MessageQueue getMessageQueue();
/**
* Get the position of message in {@link MessageQueue}.
*/
long getOffset();
}
@@ -0,0 +1,100 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis.producer;
import java.io.Closeable;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import org.apache.rocketmq.apis.exception.ClientException;
import org.apache.rocketmq.apis.message.Message;
/**
* Producer is a thread-safe rocketmq client which is used to publish messages.
*
* <p>On account of network timeout or other reasons, rocketmq producer only promised the at-least-once semantics.
* For producer, at-least-once semantics means potentially attempts are made at sending it, messages may be
* duplicated but not lost.
*/
public interface Producer extends Closeable {
/**
* Sends a message synchronously.
*
* <p>This method does not return until it gets the definitive result.
*
* @param message message to send.
*/
SendReceipt send(Message message) throws ClientException;
/**
* Sends a transactional message synchronously.
*
* @param message message to send.
* @param transaction transaction to bind.
* @return the message id assigned to the appointed message.
*/
SendReceipt send(Message message, Transaction transaction) throws ClientException;
/**
* Sends a message asynchronously.
*
* <p>This method returns immediately, the result is included in the {@link CompletableFuture};
*
* @param message message to send.
* @return a future that indicates the result.
*/
CompletableFuture<SendReceipt> sendAsync(Message message);
/**
* Sends batch messages synchronously.
*
* <p>This method does not return until it gets the definitive result.
*
* <p>All messages to send should have the same topic.
*
* @param messages batch messages to send.
* @return collection indicates the message id assigned to the appointed message, which keep the same order
* messages collection.
*/
List<SendReceipt> send(List<Message> messages) throws ClientException;
/**
* Begins a transaction.
*
* <p>For example:
*
* <pre>{@code
* Transaction transaction = producer.beginTransaction();
* SendReceipt receipt1 = producer.send(message1, transaction);
* SendReceipt receipt2 = producer.send(message2, transaction);
* transaction.commit();
* }</pre>
*
* @return a transaction entity to execute commit/rollback operation.
*/
Transaction beginTransaction() throws ClientException;
/**
* Close the producer and release all related resources.
*
* <p>This method does not return until all related resource is released. Once producer is closed, <strong>it could
* not be started once again.</strong> we maintained an FSM (finite-state machine) to record the different states
* for each producer.
*/
@Override
void close();
}
@@ -0,0 +1,82 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis.producer;
import org.apache.rocketmq.apis.ClientConfiguration;
import org.apache.rocketmq.apis.exception.ClientException;
import org.apache.rocketmq.apis.message.Message;
import org.apache.rocketmq.apis.retry.BackoffRetryPolicy;
/**
* Builder to config and start {@link Producer}.
*/
public interface ProducerBuilder {
/**
* Set the client configuration for producer.
*
* @param clientConfiguration client's configuration.
* @return the producer builder instance.
*/
ProducerBuilder setClientConfiguration(ClientConfiguration clientConfiguration);
/**
* Declare topics ahead of message sending/preparation.
*
* <p>Even though the declaration is not essential, we <strong>highly recommend</strong> to declare the topics in
* advance, which could help to discover potential mistakes.
*
* @param topics topics to send/prepare.
* @return the producer builder instance.
*/
ProducerBuilder setTopics(String... topics);
/**
* Set the threads count for {@link Producer#sendAsync(Message)}.
*
* @return the producer builder instance.
*/
ProducerBuilder setAsyncThreadCount(int count);
/**
* Set the retry policy to send message.
*
* @param retryPolicy policy to re-send message when failure encountered.
* @return the producer builder instance.
*/
ProducerBuilder setRetryPolicy(BackoffRetryPolicy retryPolicy);
/**
* Set the transaction checker for producer.
*
* @param checker transaction checker.
* @return the produce builder instance.
*/
ProducerBuilder setTransactionChecker(TransactionChecker checker);
/**
* Finalize the build of {@link Producer} instance and start.
*
* <p>The producer does a series of preparatory work during startup, which could help to identify more unexpected
* error earlier.
*
* <p>Especially, if this method is invoked more than once, different producer will be created and started.
*
* @return the producer instance.
*/
Producer build() throws ClientException;
}
@@ -0,0 +1,29 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis.producer;
import org.apache.rocketmq.apis.MessageQueue;
import org.apache.rocketmq.apis.message.MessageId;
public interface SendReceipt {
MessageId getMessageId();
MessageQueue getMessageQueue();
long getOffset();
}
@@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis.producer;
import org.apache.rocketmq.apis.exception.ClientException;
/**
* An entity to describe an independent transaction.
*
* <p>Once request of commit of roll-back reached server, subsequent arrived commit or roll-back request in
* {@link Transaction} would be ignored by server.
*
* <p>If transaction is not commit/roll-back in time, it is suspended until it is solved by {@link TransactionChecker}
* or reach the end of life.
*/
public interface Transaction {
/**
* Try to commit the transaction, which would expose the message before the transaction is closed if no exception
* thrown.
*
* <p>What you should pay more attention is that commit may be successful even exception thrown.
*/
void commit() throws ClientException;
/**
* Try to roll back the transaction, which would expose the message before the transaction is closed if no exception
* thrown.
*
* <p>What you should pay more attention is that roll-back may be successful even exception thrown.
*/
void rollback() throws ClientException;
}
@@ -0,0 +1,41 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis.producer;
import org.apache.rocketmq.apis.message.MessageView;
/**
* Used to determine {@link TransactionResolution} when {@link Transaction} is not committed or roll-backed in time.
* {@link Transaction#commit()} and {@link Transaction#rollback()} does not promise that it would be applied
* successfully, so that checker here is necessary.
*
* <p>If {@link TransactionChecker#check(MessageView)} returns {@link TransactionResolution#UNKNOWN} or exception
* raised during the invocation of {@link TransactionChecker#check(MessageView)}, the examination from server will be
* performed periodically.
*/
public interface TransactionChecker {
/**
* Server will solve the suspended transactional message by this method.
*
* <p>If exception was thrown in this method, which equals {@link TransactionResolution#UNKNOWN} is returned.
*
* @param messageView message to determine {@link TransactionResolution}.
* @return the transaction resolution.
*/
TransactionResolution check(MessageView messageView);
}
@@ -0,0 +1,34 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis.producer;
public enum TransactionResolution {
/**
* Notify server that current transaction should be committed.
*/
COMMIT,
/**
* Notify server that current transaction should be roll-backed.
*/
ROLLBACK,
/**
* Notify server that the state of this transaction is not sure. You should be cautions before return unknown
* because the examination from server will be performed periodically.
*/
UNKNOWN;
}
@@ -0,0 +1,59 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis.retry;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.time.Duration;
public class BackOffRetryPolicyBuilder {
private int maxAttempts = 3;
private Duration initialBackoff = Duration.ofMillis(100);
private Duration maxBackoff = Duration.ofSeconds(1);
private int backoffMultiplier = 2;
public BackOffRetryPolicyBuilder() {
}
BackOffRetryPolicyBuilder setMaxAttempts(int maxAttempts) {
checkArgument(maxAttempts > 0, "maxAttempts must be positive");
this.maxAttempts = maxAttempts;
return this;
}
BackOffRetryPolicyBuilder setInitialBackoff(Duration initialBackoff) {
this.initialBackoff = checkNotNull(initialBackoff, "initialBackoff should not be null");
return this;
}
BackOffRetryPolicyBuilder setMaxBackoff(Duration maxBackoff) {
this.maxBackoff = checkNotNull(maxBackoff, "maxBackoff should not be null");
return this;
}
BackOffRetryPolicyBuilder setBackoffMultiplier(int backoffMultiplier) {
checkArgument(backoffMultiplier > 0, "backoffMultiplier must be positive");
this.backoffMultiplier = backoffMultiplier;
return this;
}
BackoffRetryPolicy build() {
return new BackoffRetryPolicy(maxAttempts, initialBackoff, maxBackoff, backoffMultiplier);
}
}
@@ -0,0 +1,86 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis.retry;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.MoreObjects;
import java.time.Duration;
import java.util.Random;
/**
* The {@link BackoffRetryPolicy} defines a policy to do more attempts when failure is encountered, mainly refer to
* <a href="https://github.com/grpc/proposal/blob/master/A6-client-retries.md">gRPC Retry Design</a>.
*/
public class BackoffRetryPolicy implements RetryPolicy {
public static BackOffRetryPolicyBuilder newBuilder() {
return new BackOffRetryPolicyBuilder();
}
private final Random random;
private final int maxAttempts;
private final Duration initialBackoff;
private final Duration maxBackoff;
private final int backoffMultiplier;
public BackoffRetryPolicy(int maxAttempts, Duration initialBackoff, Duration maxBackoff, int backoffMultiplier) {
checkArgument(maxBackoff.compareTo(initialBackoff) <= 0, "initialBackoff should not be minor than maxBackoff");
checkArgument(maxAttempts > 0, "maxAttempts must be positive");
this.random = new Random();
this.maxAttempts = maxAttempts;
this.initialBackoff = checkNotNull(initialBackoff, "initialBackoff should not be null");
this.maxBackoff = maxBackoff;
this.backoffMultiplier = backoffMultiplier;
}
@Override
public int getMaxAttempts() {
return maxAttempts;
}
@Override
public Duration getNextAttemptDelay(int attempt) {
checkArgument(attempt > 0, "attempt must be positive");
int randomNumberBound = Math.min(initialBackoff.getNano() * (backoffMultiplier ^ (attempt - 1)),
maxBackoff.getNano());
return Duration.ofNanos(random.nextInt(randomNumberBound));
}
public Duration getInitialBackoff() {
return initialBackoff;
}
public Duration getMaxBackoff() {
return maxBackoff;
}
public int getBackoffMultiplier() {
return backoffMultiplier;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("maxAttempts", maxAttempts)
.add("initialBackoff", initialBackoff)
.add("maxBackoff", maxBackoff)
.add("backoffMultiplier", backoffMultiplier)
.toString();
}
}
@@ -0,0 +1,40 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.rocketmq.apis.retry;
import java.time.Duration;
/**
* Internal interface for retry policy.
*/
interface RetryPolicy {
/**
* Get the max attempt times for retry.
*
* @return max attempt times.
*/
int getMaxAttempts();
/**
* Get await time after current attempts, the attempt index starts at 1.
*
* @param attempt current attempt.
* @return await time.
*/
Duration getNextAttemptDelay(int attempt);
}
@@ -497,19 +497,21 @@ public class PopMessageProcessor implements NettyRequestProcessor {
return restNum;
}
getMessageTmpResult = this.brokerController.getMessageStore().getMessage(requestHeader.getConsumerGroup()
, topic, queueId, offset,
requestHeader.getMaxMsgNums() - getMessageResult.getMessageMapedList().size(), messageFilter);
, topic, queueId, offset,
requestHeader.getMaxMsgNums() - getMessageResult.getMessageMapedList().size(), messageFilter);
if (getMessageTmpResult == null) {
return this.brokerController.getMessageStore().getMaxOffsetInQueue(topic, queueId) - offset + restNum;
}
// maybe store offset is not correct.
if (getMessageTmpResult == null
|| GetMessageStatus.OFFSET_TOO_SMALL.equals(getMessageTmpResult.getStatus())
|| GetMessageStatus.OFFSET_OVERFLOW_BADLY.equals(getMessageTmpResult.getStatus())
|| GetMessageStatus.OFFSET_FOUND_NULL.equals(getMessageTmpResult.getStatus())) {
if (GetMessageStatus.OFFSET_TOO_SMALL.equals(getMessageTmpResult.getStatus())
|| GetMessageStatus.OFFSET_OVERFLOW_BADLY.equals(getMessageTmpResult.getStatus())
|| GetMessageStatus.OFFSET_FOUND_NULL.equals(getMessageTmpResult.getStatus())) {
// commit offset, because the offset is not correct
// If offset in store is greater than cq offset, it will cause duplicate messages,
// because offset in PopBuffer is not committed.
POP_LOGGER.warn("Pop initial offset, because store is no correct, {}, {}->{}",
lockKey, offset, getMessageTmpResult != null ? getMessageTmpResult.getNextBeginOffset() : "null");
offset = getMessageTmpResult != null ? getMessageTmpResult.getNextBeginOffset() : 0;
lockKey, offset, getMessageTmpResult.getNextBeginOffset());
offset = getMessageTmpResult.getNextBeginOffset();
this.brokerController.getConsumerOffsetManager().commitOffset(channel.remoteAddress().toString(), requestHeader.getConsumerGroup(), topic,
queueId, offset);
getMessageTmpResult =
+4
View File
@@ -106,6 +106,7 @@
</properties>
<modules>
<module>apis</module>
<module>client</module>
<module>common</module>
<module>broker</module>
@@ -278,6 +279,9 @@
<goal>prepare-agent-integration</goal>
</goals>
<configuration>
<excludes>
<exclude>**/apache/rocketmq/apis/*</exclude>
</excludes>
<destFile>${project.build.directory}/jacoco-it.exec</destFile>
<propertyName>failsafeArgLine</propertyName>
</configuration>