Skip to content

Commit b6086b2

Browse files
committed
Subscription: add topic owner epoch fencing
1 parent 05a816d commit b6086b2

25 files changed

Lines changed: 796 additions & 2 deletions

File tree

‎iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,11 @@ public enum TSStatusCode {
316316
SHOW_SUBSCRIPTION_ERROR(1910),
317317
SUBSCRIPTION_PIPE_TIMEOUT_ERROR(1911),
318318
SUBSCRIPTION_NOT_ENABLED_ERROR(1912),
319+
SUBSCRIPTION_OWNER_FENCED(1913),
320+
SUBSCRIPTION_OWNER_REQUIRED(1914),
321+
SUBSCRIPTION_OWNER_EPOCH_REQUIRED(1915),
322+
SUBSCRIPTION_OWNER_LEASE_EXPIRED(1916),
323+
SUBSCRIPTION_OWNER_EPOCH_CONFLICT(1917),
319324

320325
// Topic
321326
CREATE_TOPIC_ERROR(2000),

‎iotdb-client/subscription/src/main/java/org/apache/iotdb/rpc/subscription/config/ConsumerConfig.java‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,16 @@ public String getConsumerGroupId() {
6868
return getString(ConsumerConstant.CONSUMER_GROUP_ID_KEY);
6969
}
7070

71+
public String getOwnerId() {
72+
return getString(ConsumerConstant.OWNER_ID_KEY);
73+
}
74+
75+
public Long getOwnerEpoch() {
76+
return hasAttribute(ConsumerConstant.OWNER_EPOCH_KEY)
77+
? getLong(ConsumerConstant.OWNER_EPOCH_KEY)
78+
: null;
79+
}
80+
7181
public String getUsername() {
7282
return getString(ConsumerConstant.USERNAME_KEY);
7383
}

‎iotdb-client/subscription/src/main/java/org/apache/iotdb/rpc/subscription/config/ConsumerConstant.java‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ public class ConsumerConstant {
4040

4141
public static final String CONSUMER_ID_KEY = "consumer-id";
4242
public static final String CONSUMER_GROUP_ID_KEY = "group-id";
43+
public static final String OWNER_ID_KEY = "owner-id";
44+
public static final String OWNER_EPOCH_KEY = "owner-epoch";
4345

4446
public static final String HEARTBEAT_INTERVAL_MS_KEY = "heartbeat-interval-ms";
4547
public static final long HEARTBEAT_INTERVAL_MS_DEFAULT_VALUE = 30_000L;

‎iotdb-client/subscription/src/main/java/org/apache/iotdb/rpc/subscription/config/TopicConstant.java‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ public class TopicConstant {
6161
public static final String STRICT_KEY = "strict";
6262
public static final String STRICT_DEFAULT_VALUE = "true";
6363

64+
public static final String OWNER_ID_KEY = "owner-id";
65+
public static final String OWNER_EPOCH_KEY = "owner-epoch";
66+
public static final String OWNER_LEASE_EXPIRE_TIME_MS_KEY = "owner-lease-expire-time-ms";
67+
6468
private TopicConstant() {
6569
throw new IllegalStateException(SubscriptionMessages.UTILITY_CLASS);
6670
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.iotdb.rpc.subscription.exception;
21+
22+
import java.util.Objects;
23+
24+
public class SubscriptionOwnerFencedException extends SubscriptionRuntimeNonCriticalException {
25+
26+
public SubscriptionOwnerFencedException(final String message) {
27+
super(message);
28+
}
29+
30+
public SubscriptionOwnerFencedException(final String message, final Throwable cause) {
31+
super(message, cause);
32+
}
33+
34+
@Override
35+
public boolean equals(final Object obj) {
36+
return obj instanceof SubscriptionOwnerFencedException
37+
&& Objects.equals(getMessage(), ((SubscriptionOwnerFencedException) obj).getMessage())
38+
&& Objects.equals(getTimeStamp(), ((SubscriptionOwnerFencedException) obj).getTimeStamp());
39+
}
40+
41+
@Override
42+
public int hashCode() {
43+
return super.hashCode();
44+
}
45+
}

‎iotdb-client/subscription/src/main/java/org/apache/iotdb/session/subscription/consumer/base/AbstractSubscriptionConsumer.java‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ abstract class AbstractSubscriptionConsumer implements AutoCloseable {
105105

106106
protected String consumerId;
107107
protected String consumerGroupId;
108+
protected String ownerId;
109+
protected Long ownerEpoch;
108110

109111
private final long heartbeatIntervalMs;
110112
private final long endpointsSyncIntervalMs;
@@ -154,6 +156,14 @@ public String getConsumerGroupId() {
154156
return consumerGroupId;
155157
}
156158

159+
public String getOwnerId() {
160+
return ownerId;
161+
}
162+
163+
public Long getOwnerEpoch() {
164+
return ownerEpoch;
165+
}
166+
157167
/////////////////////////////// ctor ///////////////////////////////
158168

159169
protected AbstractSubscriptionConsumer(final AbstractSubscriptionConsumerBuilder builder) {
@@ -183,6 +193,8 @@ protected AbstractSubscriptionConsumer(final AbstractSubscriptionConsumerBuilder
183193

184194
this.consumerId = builder.consumerId;
185195
this.consumerGroupId = builder.consumerGroupId;
196+
this.ownerId = builder.ownerId;
197+
this.ownerEpoch = builder.ownerEpoch;
186198

187199
this.heartbeatIntervalMs = builder.heartbeatIntervalMs;
188200
this.endpointsSyncIntervalMs = builder.endpointsSyncIntervalMs;
@@ -213,6 +225,8 @@ protected AbstractSubscriptionConsumer(
213225
.encryptedPassword((String) properties.get(ConsumerConstant.ENCRYPTED_PASSWORD_KEY))
214226
.consumerId((String) properties.get(ConsumerConstant.CONSUMER_ID_KEY))
215227
.consumerGroupId((String) properties.get(ConsumerConstant.CONSUMER_GROUP_ID_KEY))
228+
.ownerId((String) properties.get(ConsumerConstant.OWNER_ID_KEY))
229+
.ownerEpoch((Long) properties.get(ConsumerConstant.OWNER_EPOCH_KEY))
216230
.heartbeatIntervalMs(
217231
(Long)
218232
properties.getOrDefault(
@@ -394,6 +408,8 @@ protected abstract AbstractSubscriptionProvider constructSubscriptionProvider(
394408
final String encryptedPassword,
395409
final String consumerId,
396410
final String consumerGroupId,
411+
final String ownerId,
412+
final Long ownerEpoch,
397413
final int thriftMaxFrameSize,
398414
final long heartbeatIntervalMs,
399415
final int connectionTimeoutInMs);
@@ -408,6 +424,8 @@ AbstractSubscriptionProvider constructProviderAndHandshake(final TEndPoint endPo
408424
this.encryptedPassword,
409425
this.consumerId,
410426
this.consumerGroupId,
427+
this.ownerId,
428+
this.ownerEpoch,
411429
this.thriftMaxFrameSize,
412430
this.heartbeatIntervalMs,
413431
this.connectionTimeoutInMs);
@@ -1429,6 +1447,8 @@ protected Map<String, String> coreReportMessage() {
14291447
final Map<String, String> result = new HashMap<>();
14301448
result.put("consumerId", consumerId);
14311449
result.put("consumerGroupId", consumerGroupId);
1450+
result.put("ownerId", ownerId);
1451+
result.put("ownerEpoch", String.valueOf(ownerEpoch));
14321452
result.put("isClosed", isClosed.toString());
14331453
result.put("fileSaveDir", fileSaveDir);
14341454
result.put(
@@ -1443,6 +1463,8 @@ protected Map<String, String> allReportMessage() {
14431463
final Map<String, String> result = new HashMap<>();
14441464
result.put("consumerId", consumerId);
14451465
result.put("consumerGroupId", consumerGroupId);
1466+
result.put("ownerId", ownerId);
1467+
result.put("ownerEpoch", String.valueOf(ownerEpoch));
14461468
result.put("heartbeatIntervalMs", String.valueOf(heartbeatIntervalMs));
14471469
result.put("endpointsSyncIntervalMs", String.valueOf(endpointsSyncIntervalMs));
14481470
result.put("providers", providers.toString());

‎iotdb-client/subscription/src/main/java/org/apache/iotdb/session/subscription/consumer/base/AbstractSubscriptionConsumerBuilder.java‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ public class AbstractSubscriptionConsumerBuilder {
4040

4141
protected String consumerId;
4242
protected String consumerGroupId;
43+
protected String ownerId;
44+
protected Long ownerEpoch;
4345

4446
protected long heartbeatIntervalMs = ConsumerConstant.HEARTBEAT_INTERVAL_MS_DEFAULT_VALUE;
4547
protected long endpointsSyncIntervalMs =
@@ -111,6 +113,27 @@ public AbstractSubscriptionConsumerBuilder consumerGroupId(
111113
return this;
112114
}
113115

116+
public AbstractSubscriptionConsumerBuilder ownerId(@Nullable final String ownerId) {
117+
if (Objects.isNull(ownerId)) {
118+
return this;
119+
}
120+
this.ownerId = ownerId;
121+
return this;
122+
}
123+
124+
public AbstractSubscriptionConsumerBuilder ownerEpoch(final long ownerEpoch) {
125+
this.ownerEpoch = ownerEpoch;
126+
return this;
127+
}
128+
129+
public AbstractSubscriptionConsumerBuilder ownerEpoch(@Nullable final Long ownerEpoch) {
130+
if (Objects.isNull(ownerEpoch)) {
131+
return this;
132+
}
133+
this.ownerEpoch = ownerEpoch;
134+
return this;
135+
}
136+
114137
public AbstractSubscriptionConsumerBuilder heartbeatIntervalMs(final long heartbeatIntervalMs) {
115138
this.heartbeatIntervalMs =
116139
Math.max(heartbeatIntervalMs, ConsumerConstant.HEARTBEAT_INTERVAL_MS_MIN_VALUE);

‎iotdb-client/subscription/src/main/java/org/apache/iotdb/session/subscription/consumer/base/AbstractSubscriptionProvider.java‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.apache.iotdb.rpc.subscription.config.TopicConfig;
2828
import org.apache.iotdb.rpc.subscription.exception.SubscriptionConnectionException;
2929
import org.apache.iotdb.rpc.subscription.exception.SubscriptionException;
30+
import org.apache.iotdb.rpc.subscription.exception.SubscriptionOwnerFencedException;
3031
import org.apache.iotdb.rpc.subscription.exception.SubscriptionPipeTimeoutException;
3132
import org.apache.iotdb.rpc.subscription.exception.SubscriptionRuntimeCriticalException;
3233
import org.apache.iotdb.rpc.subscription.exception.SubscriptionRuntimeNonCriticalException;
@@ -81,6 +82,8 @@ public abstract class AbstractSubscriptionProvider {
8182

8283
private String consumerId;
8384
private String consumerGroupId;
85+
private final String ownerId;
86+
private final Long ownerEpoch;
8487

8588
private final AtomicBoolean isClosed = new AtomicBoolean(true);
8689
private final AtomicBoolean isAvailable = new AtomicBoolean(false);
@@ -109,6 +112,8 @@ protected AbstractSubscriptionProvider(
109112
final String encryptedPassword,
110113
final String consumerId,
111114
final String consumerGroupId,
115+
final String ownerId,
116+
final Long ownerEpoch,
112117
final int thriftMaxFrameSize,
113118
final long heartbeatIntervalMs,
114119
final int connectionTimeoutInMs) {
@@ -124,6 +129,8 @@ protected AbstractSubscriptionProvider(
124129
this.endPoint = endPoint;
125130
this.consumerId = consumerId;
126131
this.consumerGroupId = consumerGroupId;
132+
this.ownerId = ownerId;
133+
this.ownerEpoch = ownerEpoch;
127134
this.username = username;
128135
this.password = password;
129136
this.encryptedPassword = encryptedPassword;
@@ -176,6 +183,12 @@ synchronized void handshake() throws SubscriptionException, IoTDBConnectionExcep
176183
final Map<String, String> consumerAttributes = new HashMap<>();
177184
consumerAttributes.put(ConsumerConstant.CONSUMER_GROUP_ID_KEY, consumerGroupId);
178185
consumerAttributes.put(ConsumerConstant.CONSUMER_ID_KEY, consumerId);
186+
if (ownerId != null) {
187+
consumerAttributes.put(ConsumerConstant.OWNER_ID_KEY, ownerId);
188+
}
189+
if (ownerEpoch != null) {
190+
consumerAttributes.put(ConsumerConstant.OWNER_EPOCH_KEY, String.valueOf(ownerEpoch));
191+
}
179192
consumerAttributes.put(ConsumerConstant.USERNAME_KEY, username);
180193
consumerAttributes.put(ConsumerConstant.PASSWORD_KEY, password);
181194
if (encryptedPassword != null) {
@@ -451,6 +464,17 @@ private static void verifyPipeSubscribeSuccess(final TSStatus status)
451464
case 1911: // SUBSCRIPTION_PIPE_TIMEOUT_ERROR
452465
throw new SubscriptionPipeTimeoutException(
453466
String.format(SUBSCRIPTION_PIPE_TIMEOUT_FORMATTER, status.code, status.message));
467+
case 1913: // SUBSCRIPTION_OWNER_FENCED
468+
case 1914: // SUBSCRIPTION_OWNER_REQUIRED
469+
case 1915: // SUBSCRIPTION_OWNER_EPOCH_REQUIRED
470+
case 1916: // SUBSCRIPTION_OWNER_LEASE_EXPIRED
471+
case 1917: // SUBSCRIPTION_OWNER_EPOCH_CONFLICT
472+
{
473+
final String errorMessage =
474+
String.format(INTERNAL_ERROR_FORMATTER, status.code, status.message);
475+
LOGGER.warn(errorMessage);
476+
throw new SubscriptionOwnerFencedException(errorMessage);
477+
}
454478
case 1900: // SUBSCRIPTION_VERSION_ERROR
455479
case 1901: // SUBSCRIPTION_TYPE_ERROR
456480
case 1909: // SUBSCRIPTION_MISSING_CUSTOMER

‎iotdb-client/subscription/src/main/java/org/apache/iotdb/session/subscription/consumer/table/SubscriptionTableProvider.java‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ final class SubscriptionTableProvider extends AbstractSubscriptionProvider {
3333
final String encryptedPassword,
3434
final String consumerId,
3535
final String consumerGroupId,
36+
final String ownerId,
37+
final Long ownerEpoch,
3638
final int thriftMaxFrameSize,
3739
final long heartbeatIntervalMs,
3840
final int connectionTimeoutInMs) {
@@ -43,6 +45,8 @@ final class SubscriptionTableProvider extends AbstractSubscriptionProvider {
4345
encryptedPassword,
4446
consumerId,
4547
consumerGroupId,
48+
ownerId,
49+
ownerEpoch,
4650
thriftMaxFrameSize,
4751
heartbeatIntervalMs,
4852
connectionTimeoutInMs);

‎iotdb-client/subscription/src/main/java/org/apache/iotdb/session/subscription/consumer/table/SubscriptionTablePullConsumer.java‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ protected AbstractSubscriptionProvider constructSubscriptionProvider(
4545
final String encryptedPassword,
4646
final String consumerId,
4747
final String consumerGroupId,
48+
final String ownerId,
49+
final Long ownerEpoch,
4850
final int thriftMaxFrameSize,
4951
final long heartbeatIntervalMs,
5052
final int connectionTimeoutInMs) {
@@ -55,6 +57,8 @@ protected AbstractSubscriptionProvider constructSubscriptionProvider(
5557
encryptedPassword,
5658
consumerId,
5759
consumerGroupId,
60+
ownerId,
61+
ownerEpoch,
5862
thriftMaxFrameSize,
5963
heartbeatIntervalMs,
6064
connectionTimeoutInMs);

0 commit comments

Comments
 (0)