-
Notifications
You must be signed in to change notification settings - Fork 3.7k
[fix][broker]The partitions of the topic was wrongly created even though this cluster was not allowed to access it #25443
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
base: master
Are you sure you want to change the base?
Changes from all commits
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 |
|---|---|---|
|
|
@@ -94,11 +94,14 @@ | |
| import org.apache.bookkeeper.mledger.ManagedLedgerFactory; | ||
| import org.apache.bookkeeper.mledger.impl.NonAppendableLedgerOffloader; | ||
| import org.apache.bookkeeper.mledger.util.Futures; | ||
| import org.apache.commons.collections4.CollectionUtils; | ||
| import org.apache.commons.collections4.MapUtils; | ||
| import org.apache.commons.lang3.StringUtils; | ||
| import org.apache.commons.lang3.mutable.MutableBoolean; | ||
| import org.apache.commons.lang3.tuple.ImmutablePair; | ||
| import org.apache.commons.lang3.tuple.ImmutableTriple; | ||
| import org.apache.commons.lang3.tuple.Pair; | ||
| import org.apache.commons.lang3.tuple.Triple; | ||
| import org.apache.pulsar.bookie.rackawareness.IsolatedBookieEnsemblePlacementPolicy; | ||
| import org.apache.pulsar.broker.PulsarServerException; | ||
| import org.apache.pulsar.broker.PulsarService; | ||
|
|
@@ -2076,29 +2079,43 @@ private CompletableFuture<Void> checkTopicAlreadyMigrated(TopicName topicName) { | |
| return result; | ||
| } | ||
|
|
||
| public CompletableFuture<ManagedLedgerConfig> getManagedLedgerConfig(@NonNull TopicName topicName) { | ||
| /** | ||
| * @return Triple [namespace policies, global topic policies, topic policies]. | ||
| */ | ||
| public CompletableFuture<Triple<Optional<Policies>, Optional<TopicPolicies>, Optional<TopicPolicies>>> | ||
| getCombinedTopicPolicies(@NonNull TopicName topicName) { | ||
| if (topicName == null) { | ||
| return FutureUtil.failedFuture(new NullPointerException("topicName")); | ||
| } | ||
| NamespaceName namespace = topicName.getNamespaceObject(); | ||
| ServiceConfiguration serviceConfig = pulsar.getConfiguration(); | ||
|
|
||
| NamespaceResources nsr = pulsar.getPulsarResources().getNamespaceResources(); | ||
| LocalPoliciesResources lpr = pulsar.getPulsarResources().getLocalPolicies(); | ||
| final CompletableFuture<Optional<TopicPolicies>> topicPoliciesFuture = | ||
| getTopicPoliciesBypassSystemTopic(topicName, TopicPoliciesService.GetType.LOCAL_ONLY); | ||
| final CompletableFuture<Optional<TopicPolicies>> globalTopicPoliciesFuture = | ||
| getTopicPoliciesBypassSystemTopic(topicName, TopicPoliciesService.GetType.GLOBAL_ONLY); | ||
| final CompletableFuture<Optional<Policies>> nsPolicies = nsr.getPoliciesAsync(namespace); | ||
| final CompletableFuture<Optional<LocalPolicies>> lcPolicies = lpr.getLocalPoliciesAsync(namespace); | ||
| return topicPoliciesFuture.thenCombine(globalTopicPoliciesFuture, (topicP, globalTopicP) -> { | ||
| return new ImmutablePair<>(topicP, globalTopicP); | ||
| }).thenCombine(nsPolicies, (topicPoliciesPair, np) -> { | ||
| return new ImmutablePair<>(topicPoliciesPair, np); | ||
| }).thenCombine(lcPolicies, (combined, localPolicies) -> { | ||
| Optional<TopicPolicies> topicP = combined.getLeft().getLeft(); | ||
| Optional<TopicPolicies> globalTopicP = combined.getLeft().getRight(); | ||
| Optional<Policies> policies = combined.getRight(); | ||
| Optional<TopicPolicies> topicP = topicPoliciesPair.getLeft(); | ||
| Optional<TopicPolicies> globalTopicP = topicPoliciesPair.getRight(); | ||
| return new ImmutableTriple<>(np, globalTopicP, topicP); | ||
| }); | ||
| } | ||
|
|
||
| public CompletableFuture<ManagedLedgerConfig> getManagedLedgerConfig(@NonNull TopicName topicName) { | ||
| if (topicName == null) { | ||
| return FutureUtil.failedFuture(new NullPointerException("topicName")); | ||
| } | ||
| NamespaceName namespace = topicName.getNamespaceObject(); | ||
| ServiceConfiguration serviceConfig = pulsar.getConfiguration(); | ||
|
|
||
| LocalPoliciesResources lpr = pulsar.getPulsarResources().getLocalPolicies(); | ||
| final CompletableFuture<Optional<LocalPolicies>> lcPolicies = lpr.getLocalPoliciesAsync(namespace); | ||
| return getCombinedTopicPolicies(topicName).thenCombine(lcPolicies, (combined, localPolicies) -> { | ||
| Optional<Policies> policies = combined.getLeft(); | ||
| Optional<TopicPolicies> globalTopicP = combined.getMiddle(); | ||
| Optional<TopicPolicies> topicP = combined.getRight(); | ||
|
|
||
| PersistencePolicies persistencePolicies = null; | ||
| RetentionPolicies retentionPolicies = null; | ||
|
|
@@ -4136,6 +4153,38 @@ public void setPulsarChannelInitializerFactory(PulsarChannelInitializer.Factory | |
| this.pulsarChannelInitFactory = factory; | ||
| } | ||
|
|
||
| /** | ||
| * @return CompletableFuture<Triple<Optional<Policies>, whether the current cluster is allowed to access the topic. | ||
| */ | ||
| public CompletableFuture<Boolean> isCurrentClusterAllowed(@NonNull TopicName topicName) { | ||
| final String cluster = getPulsar().getConfig().getClusterName(); | ||
| return getCombinedTopicPolicies(topicName).thenApply(triple -> { | ||
| Optional<TopicPolicies> topicP = triple.getRight(); | ||
| Optional<TopicPolicies> globalTopicP = triple.getMiddle(); | ||
| Optional<Policies> nsPolicies = triple.getLeft(); | ||
| // Disabled a cluster for a namespace manually. | ||
| if (nsPolicies.isPresent() && !isCurrentClusterAllowed(topicName.getNamespaceObject(), nsPolicies.get())) { | ||
|
Contributor
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. Possible regression: Suggest only short-circuiting on the
Contributor
Author
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.
This situation does not exist. Let's review all possible use cases:
|
||
| return false; | ||
| } | ||
| // Manually enabled topic-level replication, which can skip to set a namespace-level replication. | ||
| if (topicP.isPresent() && CollectionUtils.isNotEmpty(topicP.get().getReplicationClusters())) { | ||
| if (topicP.get().getReplicationClusters().contains(cluster)) { | ||
| return true; | ||
| } else { | ||
| return false; | ||
| } | ||
| } | ||
| if (globalTopicP.isPresent() && CollectionUtils.isNotEmpty(globalTopicP.get().getReplicationClusters())) { | ||
| if (globalTopicP.get().getReplicationClusters().contains(cluster)) { | ||
| return true; | ||
| } else { | ||
| return false; | ||
| } | ||
| } | ||
| return true; | ||
| }); | ||
| } | ||
|
|
||
| /*** | ||
| * After PIP-321 Introduce allowed-cluster at the namespace level, the condition that whether the cluster is | ||
| * allowed to access by the current cluster was defined by two fields: | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.