-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[improve][txn][PIP-298] Consumer supports specifying consumption isolation level #21246
base: master
Are you sure you want to change the base?
Changes from 3 commits
e13370d
05a5c46
7eee90c
4712979
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,14 +18,37 @@ | |
*/ | ||
package org.apache.pulsar.broker.service; | ||
|
||
import org.apache.pulsar.common.api.proto.CommandSubscribe.IsolationLevel; | ||
|
||
import java.util.Map; | ||
import java.util.Optional; | ||
import java.util.concurrent.atomic.LongAdder; | ||
import java.util.function.ToLongFunction; | ||
|
||
public abstract class AbstractSubscription implements Subscription { | ||
protected static final String SUBSCRIPTION_ISOLATION_LEVEL_PROPERTY = "pulsar.subscription.isolation.level"; | ||
protected final LongAdder bytesOutFromRemovedConsumers = new LongAdder(); | ||
protected final LongAdder msgOutFromRemovedConsumer = new LongAdder(); | ||
|
||
public static void wrapIsolationLevelToProperties(Map<String, String> properties, IsolationLevel isolationLevel) { | ||
if (properties != null) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the argument |
||
properties.put(SUBSCRIPTION_ISOLATION_LEVEL_PROPERTY, String.valueOf(isolationLevel.getValue())); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Once the subscription was created, the prop If yes, we should prevent modifying it by the API There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, why do we need to persist the isolation level to properties? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
For example:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I agree that the subscription use the isolation type of the first consumer provided. But the isolation level should not be changed. Just like schema. |
||
} | ||
} | ||
|
||
public IsolationLevel fetchIsolationLevelFromProperties(Map<String, String> properties) { | ||
if (properties == null) { | ||
return IsolationLevel.READ_COMMITTED; | ||
} | ||
|
||
if (properties.containsKey(SUBSCRIPTION_ISOLATION_LEVEL_PROPERTY)) { | ||
IsolationLevel isolationLevel = IsolationLevel.valueOf(Integer.parseInt(properties.get(SUBSCRIPTION_ISOLATION_LEVEL_PROPERTY))); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we catch the |
||
return isolationLevel != null ? isolationLevel : IsolationLevel.READ_COMMITTED; | ||
} else { | ||
return IsolationLevel.READ_COMMITTED; | ||
} | ||
} | ||
|
||
public long getMsgOutCounter() { | ||
return msgOutFromRemovedConsumer.longValue() + sumConsumers(Consumer::getMsgOutCounter); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -45,6 +45,7 @@ public class SubscriptionOption { | |
private Map<String, String> metadata; | ||
private boolean readCompacted; | ||
private CommandSubscribe.InitialPosition initialPosition; | ||
private CommandSubscribe.IsolationLevel isolationLevel; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you modify this variable with |
||
private long startMessageRollbackDurationSec; | ||
private boolean replicatedSubscriptionStateArg; | ||
private KeySharedMeta keySharedMeta; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,6 +41,7 @@ | |
import org.apache.pulsar.broker.service.Subscription; | ||
import org.apache.pulsar.broker.service.Topic; | ||
import org.apache.pulsar.common.api.proto.CommandAck.AckType; | ||
import org.apache.pulsar.common.api.proto.CommandSubscribe.IsolationLevel; | ||
import org.apache.pulsar.common.api.proto.CommandSubscribe.SubType; | ||
import org.apache.pulsar.common.api.proto.KeySharedMeta; | ||
import org.apache.pulsar.common.api.proto.KeySharedMode; | ||
|
@@ -70,6 +71,8 @@ public class NonPersistentSubscription extends AbstractSubscription implements S | |
|
||
private KeySharedMode keySharedMode = null; | ||
|
||
private final IsolationLevel isolationLevel; | ||
|
||
public NonPersistentSubscription(NonPersistentTopic topic, String subscriptionName, | ||
Map<String, String> properties) { | ||
this.topic = topic; | ||
|
@@ -79,6 +82,7 @@ public NonPersistentSubscription(NonPersistentTopic topic, String subscriptionNa | |
IS_FENCED_UPDATER.set(this, FALSE); | ||
this.subscriptionProperties = properties != null | ||
? Collections.unmodifiableMap(properties) : Collections.emptyMap(); | ||
this.isolationLevel = fetchIsolationLevelFromProperties(properties); | ||
} | ||
|
||
@Override | ||
|
@@ -236,6 +240,11 @@ public String getTypeString() { | |
return "Null"; | ||
} | ||
|
||
@Override | ||
public IsolationLevel getIsolationLevel() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe use |
||
return this.isolationLevel; | ||
} | ||
|
||
@Override | ||
public CompletableFuture<Void> clearBacklog() { | ||
// No-op | ||
|
@@ -463,6 +472,7 @@ public NonPersistentSubscriptionStatsImpl getStats() { | |
|
||
subStats.type = getTypeString(); | ||
subStats.msgDropRate = dispatcher.getMessageDropRate().getValueRate(); | ||
subStats.subscriptionIsolationLevel = this.isolationLevel.toString(); | ||
|
||
KeySharedMode keySharedMode = this.keySharedMode; | ||
if (getType() == SubType.Key_Shared && keySharedMode != null) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -77,6 +77,7 @@ | |
import org.apache.pulsar.client.api.Range; | ||
import org.apache.pulsar.client.api.transaction.TxnID; | ||
import org.apache.pulsar.common.api.proto.CommandAck.AckType; | ||
import org.apache.pulsar.common.api.proto.CommandSubscribe.IsolationLevel; | ||
import org.apache.pulsar.common.api.proto.CommandSubscribe.SubType; | ||
import org.apache.pulsar.common.api.proto.KeySharedMeta; | ||
import org.apache.pulsar.common.api.proto.MessageMetadata; | ||
|
@@ -127,6 +128,7 @@ public class PersistentSubscription extends AbstractSubscription implements Subs | |
private volatile ReplicatedSubscriptionSnapshotCache replicatedSubscriptionSnapshotCache; | ||
private final PendingAckHandle pendingAckHandle; | ||
private volatile Map<String, String> subscriptionProperties; | ||
private final IsolationLevel isolationLevel; | ||
private volatile CompletableFuture<Void> fenceFuture; | ||
|
||
static Map<String, Long> getBaseCursorProperties(boolean isReplicated) { | ||
|
@@ -160,6 +162,7 @@ public PersistentSubscription(PersistentTopic topic, String subscriptionName, Ma | |
this.pendingAckHandle = new PendingAckHandleDisabled(); | ||
} | ||
IS_FENCED_UPDATER.set(this, FALSE); | ||
this.isolationLevel = fetchIsolationLevelFromProperties(subscriptionProperties); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we support users using a message that is read from a subscription typed
And please add a test for this case. |
||
} | ||
|
||
public void updateLastMarkDeleteAdvancedTimestamp() { | ||
|
@@ -506,6 +509,11 @@ public String getTypeString() { | |
return "Null"; | ||
} | ||
|
||
@Override | ||
public IsolationLevel getIsolationLevel() { | ||
return isolationLevel; | ||
} | ||
|
||
@Override | ||
public CompletableFuture<AnalyzeBacklogResult> analyzeBacklog(Optional<Position> position) { | ||
|
||
|
@@ -1187,6 +1195,7 @@ public SubscriptionStatsImpl getStats(Boolean getPreciseBacklog, boolean subscri | |
subStats.isReplicated = isReplicated(); | ||
subStats.subscriptionProperties = subscriptionProperties; | ||
subStats.isDurable = cursor.isDurable(); | ||
subStats.subscriptionIsolationLevel = this.isolationLevel.toString(); | ||
if (getType() == SubType.Key_Shared && dispatcher instanceof PersistentStickyKeyDispatcherMultipleConsumers) { | ||
PersistentStickyKeyDispatcherMultipleConsumers keySharedDispatcher = | ||
(PersistentStickyKeyDispatcherMultipleConsumers) dispatcher; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since it is a prop for Transaction, we should make this prop name contain the keyword
transaction
, right?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And for all the system properties, please add
__
as a prefix.