You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pulsar.apache.org by lh...@apache.org on 2026/10/22 08:31:56 UTC

(pulsar) 01/12: [fix][broker] Ignore replicated subscription updates for the compaction subscription (#27032)

This is an automated email from the ASF dual-hosted git repository.

lhotari pushed a commit to branch branch-5.0
in repository https://gitbox.apache.org/repos/asf/pulsar.git

commit 650885b36a22734ac12ba0de318c3b42a1ef1743
Author: kaminski-dev <39...@users.noreply.github.com>
AuthorDate: Thu Oct 22 00:38:22 2026 +0200

    [fix][broker] Ignore replicated subscription updates for the compaction subscription (#27032)
    
    (cherry picked from commit 5511b5a441adfe38e5c64a1726e39a10ba42cf35)
---
 .../ReplicatedSubscriptionsController.java         |  8 ++++++
 .../ReplicatedSubscriptionsControllerTest.java     | 32 +++++++++++++++++++++-
 2 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/persistent/ReplicatedSubscriptionsController.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/persistent/ReplicatedSubscriptionsController.java
index bf3a6513146a..03c43da88c0d 100644
--- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/persistent/ReplicatedSubscriptionsController.java
+++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/persistent/ReplicatedSubscriptionsController.java
@@ -198,6 +198,14 @@ public class ReplicatedSubscriptionsController implements AutoCloseable, Topic.P
     }
 
     private void receiveSubscriptionUpdated(ReplicatedSubscriptionsUpdate update) {
+        if (PersistentTopic.isCompactionSubscription(update.getSubscriptionName())) {
+            // The compactor owns this cursor: it may only move together with the compacted ledger
+            log.debug()
+                    .attr("subscriptionName", update.getSubscriptionName())
+                    .log("Ignoring replicated subscription update for the compaction subscription");
+            return;
+        }
+
         MarkersMessageIdData updatedMessageId = null;
         for (int i = 0, size = update.getClustersCount(); i < size; i++) {
             ClusterMessageId cmid = update.getClusterAt(i);
diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/persistent/ReplicatedSubscriptionsControllerTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/persistent/ReplicatedSubscriptionsControllerTest.java
index 09b86418b253..320bf11177fe 100644
--- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/persistent/ReplicatedSubscriptionsControllerTest.java
+++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/persistent/ReplicatedSubscriptionsControllerTest.java
@@ -20,6 +20,7 @@ package org.apache.pulsar.broker.service.persistent;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
@@ -68,6 +69,7 @@ import org.apache.pulsar.common.policies.data.BacklogQuota;
 import org.apache.pulsar.common.policies.data.impl.BacklogQuotaImpl;
 import org.apache.pulsar.common.protocol.Commands;
 import org.apache.pulsar.common.protocol.Markers;
+import org.apache.pulsar.compaction.Compactor;
 import org.apache.pulsar.utils.TestLogAppender;
 import org.mockito.Mockito;
 import org.testng.Assert;
@@ -155,9 +157,37 @@ public class ReplicatedSubscriptionsControllerTest {
         return subscription;
     }
 
+    @Test
+    public void testReplicatedSubscriptionUpdateForCompactionSubscriptionIsIgnored() {
+        PersistentTopic topic = mockTopicForUpdates();
+        PulsarCompactorSubscription compactorSubscription = mock(PulsarCompactorSubscription.class);
+        // PulsarCompactorSubscription rejects acks without the compacted ledger property synchronously
+        when(compactorSubscription.acknowledgeMessageAsync(any(), any(), any()))
+                .thenThrow(new IllegalArgumentException());
+        when(topic.getSubscription(Compactor.COMPACTION_SUBSCRIPTION)).thenReturn(compactorSubscription);
+
+        receiveUpdate(topic, Compactor.COMPACTION_SUBSCRIPTION, 1, 2);
+
+        verify(compactorSubscription, never()).acknowledgeMessageAsync(any(), any(), any());
+    }
+
+    @Test
+    public void testReplicatedSubscriptionUpdateDoesNotCreateCompactionSubscription() {
+        PersistentTopic topic = mockTopicForUpdates();
+        when(topic.getSubscription(Compactor.COMPACTION_SUBSCRIPTION)).thenReturn(null);
+
+        receiveUpdate(topic, Compactor.COMPACTION_SUBSCRIPTION, 1, 2);
+
+        verify(topic, never()).createSubscription(any(), any(), anyBoolean(), any());
+    }
+
     private static void receiveUpdate(PersistentTopic topic, long ledgerId, long entryId) {
+        receiveUpdate(topic, "sub", ledgerId, entryId);
+    }
+
+    private static void receiveUpdate(PersistentTopic topic, String subscriptionName, long ledgerId, long entryId) {
         ReplicatedSubscriptionsController controller = new ReplicatedSubscriptionsController(topic, "local");
-        ByteBuf marker = Markers.newReplicatedSubscriptionsUpdate("sub",
+        ByteBuf marker = Markers.newReplicatedSubscriptionsUpdate(subscriptionName,
                 Map.of("local", new MarkersMessageIdData().setLedgerId(ledgerId).setEntryId(entryId)));
         try {
             Commands.skipMessageMetadata(marker);