36
36
import java .util .stream .Collectors ;
37
37
import java .util .stream .Stream ;
38
38
import javax .ws .rs .DELETE ;
39
+ import javax .ws .rs .DefaultValue ;
39
40
import javax .ws .rs .GET ;
40
41
import javax .ws .rs .POST ;
41
42
import javax .ws .rs .PUT ;
55
56
import org .apache .pulsar .broker .admin .AdminResource ;
56
57
import org .apache .pulsar .broker .web .RestException ;
57
58
import org .apache .pulsar .client .admin .PulsarAdmin ;
59
+ import org .apache .pulsar .client .admin .PulsarAdminException ;
58
60
import org .apache .pulsar .common .naming .Constants ;
59
61
import org .apache .pulsar .common .naming .NamedEntity ;
60
62
import org .apache .pulsar .common .policies .data .BrokerNamespaceIsolationData ;
@@ -705,7 +707,9 @@ public void setNamespaceIsolationPolicy(
705
707
@ ApiParam (value = "The namespace isolation policy name" , required = true )
706
708
@ PathParam ("policyName" ) String policyName ,
707
709
@ ApiParam (value = "The namespace isolation policy data" , required = true )
708
- NamespaceIsolationDataImpl policyData
710
+ NamespaceIsolationDataImpl policyData ,
711
+ @ DefaultValue ("true" )
712
+ @ QueryParam ("unloadBundles" ) boolean unload
709
713
) {
710
714
validateSuperUserAccessAsync ()
711
715
.thenCompose (__ -> validatePoliciesReadOnlyAccessAsync ())
@@ -723,7 +727,13 @@ public void setNamespaceIsolationPolicy(
723
727
nsIsolationPolicies .setPolicy (policyName , policyData );
724
728
return namespaceIsolationPolicies ()
725
729
.setIsolationDataAsync (cluster , old -> nsIsolationPolicies .getPolicies ());
726
- }).thenCompose (__ -> filterAndUnloadMatchedNamespaceAsync (policyData ))
730
+ }).thenCompose (__ -> {
731
+ if (unload ) {
732
+ return filterAndUnloadMatchedNamespaceAsync (cluster , policyData );
733
+ } else {
734
+ return CompletableFuture .completedFuture (null );
735
+ }
736
+ })
727
737
.thenAccept (__ -> {
728
738
log .info ("[{}] Successful to update clusters/{}/namespaceIsolationPolicies/{}." ,
729
739
clientAppId (), cluster , policyName );
@@ -757,7 +767,8 @@ public void setNamespaceIsolationPolicy(
757
767
/**
758
768
* Get matched namespaces; call unload for each namespaces.
759
769
*/
760
- private CompletableFuture <Void > filterAndUnloadMatchedNamespaceAsync (NamespaceIsolationDataImpl policyData ) {
770
+ private CompletableFuture <Void > filterAndUnloadMatchedNamespaceAsync (String cluster ,
771
+ NamespaceIsolationDataImpl policyData ) {
761
772
PulsarAdmin adminClient ;
762
773
try {
763
774
adminClient = pulsar ().getAdminClient ();
@@ -770,8 +781,13 @@ private CompletableFuture<Void> filterAndUnloadMatchedNamespaceAsync(NamespaceIs
770
781
.map (tenant -> adminClient .namespaces ().getNamespacesAsync (tenant ));
771
782
return FutureUtil .waitForAll (completableFutureStream )
772
783
.thenApply (namespaces -> {
773
- // if namespace match any policy regex, add it to ns list to be unload.
784
+ // Filter namespaces that have current cluster in their replication_clusters
785
+ // if namespace match any policy regex, add it to ns list to be unloaded.
774
786
return namespaces .stream ()
787
+ .filter (namespaceName -> adminClient .namespaces ()
788
+ .getPoliciesAsync (namespaceName )
789
+ .thenApply (policies -> policies .replication_clusters .contains (cluster ))
790
+ .join ())
775
791
.filter (namespaceName ->
776
792
policyData .getNamespaces ().stream ().anyMatch (namespaceName ::matches ))
777
793
.collect (Collectors .toList ());
@@ -781,7 +797,33 @@ private CompletableFuture<Void> filterAndUnloadMatchedNamespaceAsync(NamespaceIs
781
797
return CompletableFuture .completedFuture (null );
782
798
}
783
799
List <CompletableFuture <Void >> futures = shouldUnloadNamespaces .stream ()
784
- .map (namespaceName -> adminClient .namespaces ().unloadAsync (namespaceName ))
800
+ .map (namespaceName -> {
801
+ try {
802
+ return adminClient .namespaces ()
803
+ .getPolicies (namespaceName );
804
+ } catch (PulsarAdminException e ) {
805
+ log .warn ("[{}] Failed to get policy for {} namespace." , clientAppId (),
806
+ namespaceName , e );
807
+ throw new RuntimeException (e );
808
+ }
809
+ })
810
+ .map (policies -> {
811
+ final List <CompletableFuture <Void >> unloadFutures = new ArrayList <>();
812
+ List <String > boundaries = policies .bundles .getBoundaries ();
813
+ for (int i = 0 ; i < boundaries .size () - 1 ; i ++) {
814
+ String bundle = String .format ("%s_%s" , boundaries .get (i ), boundaries .get (i + 1 ));
815
+ try {
816
+ unloadFutures .add (
817
+ pulsar ().getAdminClient ().namespaces ().unloadNamespaceBundleAsync (
818
+ namespaceName .toString (), bundle ));
819
+ } catch (PulsarServerException e ) {
820
+ log .error ("[{}] Failed to unload namespace {}" , clientAppId (), namespaceName ,
821
+ e );
822
+ throw new RestException (e );
823
+ }
824
+ }
825
+ return FutureUtil .waitForAll (unloadFutures );
826
+ })
785
827
.collect (Collectors .toList ());
786
828
return FutureUtil .waitForAll (futures )
787
829
.thenAccept (__ -> {
0 commit comments