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/06/22 20:16:17 UTC
(pulsar) branch master updated: [fix][broker] Fix geo-replication stuck after a failed publish to the remote cluster (#26002)
This is an automated email from the ASF dual-hosted git repository.
lhotari pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar.git
The following commit(s) were added to refs/heads/master by this push:
new 9b9e67a9d710 [fix][broker] Fix geo-replication stuck after a failed publish to the remote cluster (#26002)
9b9e67a9d710 is described below
commit 9b9e67a9d710f6e4cc4d0665a6cd8dab24c45973
Author: void-ptr974 <vo...@protonmail.com>
AuthorDate: Tue Jun 23 04:16:10 2026 +0800
[fix][broker] Fix geo-replication stuck after a failed publish to the remote cluster (#26002)
---
.../service/persistent/PersistentReplicator.java | 3 ++
.../PersistentReplicatorInflightTaskTest.java | 32 ++++++++++++++++++++++
2 files changed, 35 insertions(+)
diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/persistent/PersistentReplicator.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/persistent/PersistentReplicator.java
index 8433d9b9c7ba..c599920f727b 100644
--- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/persistent/PersistentReplicator.java
+++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/persistent/PersistentReplicator.java
@@ -408,6 +408,9 @@ public abstract class PersistentReplicator extends AbstractReplicator
// cursor should be rewound since it was incremented when readMoreEntries
replicator.beforeTerminateOrCursorRewinding(ReasonOfWaitForCursorRewinding.Failed_Publishing);
replicator.doRewindCursor(false);
+ // The failed send has completed from the producer queue perspective. The cursor rewind
+ // makes the entry readable again, so this in-flight task must release its permit.
+ inFlightTask.incCompletedEntries();
} else {
replicator.log.debug()
.exception(exception)
diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/persistent/PersistentReplicatorInflightTaskTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/persistent/PersistentReplicatorInflightTaskTest.java
index 478437ffde01..6295f14022dd 100644
--- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/persistent/PersistentReplicatorInflightTaskTest.java
+++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/persistent/PersistentReplicatorInflightTaskTest.java
@@ -19,6 +19,7 @@
package org.apache.pulsar.broker.service.persistent;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.testng.Assert.assertEquals;
@@ -43,8 +44,11 @@ import org.apache.pulsar.broker.service.AbstractReplicator;
import org.apache.pulsar.broker.service.BrokerServiceInternalMethodInvoker;
import org.apache.pulsar.broker.service.OneWayReplicatorTestBase;
import org.apache.pulsar.broker.service.persistent.PersistentReplicator.InFlightTask;
+import org.apache.pulsar.broker.service.persistent.PersistentReplicator.ProducerSendCallback;
+import org.apache.pulsar.broker.service.persistent.PersistentReplicator.ReasonOfWaitForCursorRewinding;
import org.apache.pulsar.client.api.MessageId;
import org.apache.pulsar.client.api.Producer;
+import org.apache.pulsar.client.api.PulsarClientException;
import org.apache.pulsar.client.api.Schema;
import org.awaitility.Awaitility;
import org.mockito.invocation.InvocationOnMock;
@@ -167,6 +171,34 @@ public class PersistentReplicatorInflightTaskTest extends OneWayReplicatorTestBa
}
}
+ @Test
+ public void testFailedPublishCompletesInFlightTask() throws Exception {
+ PersistentReplicator replicator = spy(getReplicator(topicName));
+ doNothing().when(replicator).beforeTerminateOrCursorRewinding(ReasonOfWaitForCursorRewinding.Failed_Publishing);
+ doNothing().when(replicator).doRewindCursor(false);
+ doNothing().when(replicator).readMoreEntries();
+
+ LinkedList<InFlightTask> inFlightTasks = replicator.inFlightTasks;
+ List<InFlightTask> originalTasks = new ArrayList<>(inFlightTasks);
+ inFlightTasks.clear();
+
+ try {
+ InFlightTask task = new InFlightTask(PositionFactory.create(1, 1), 1, replicator.getReplicatorId());
+ task.setEntries(Collections.singletonList(mock(Entry.class)));
+ inFlightTasks.add(task);
+ assertEquals(replicator.getPermitsIfNoPendingRead(), 999);
+
+ ProducerSendCallback callback = ProducerSendCallback.create(replicator, mock(Entry.class), null, task);
+ callback.sendComplete(new PulsarClientException.ProducerBlockedQuotaExceededException("mocked"), null);
+
+ assertTrue(task.isDone());
+ assertEquals(replicator.getPermitsIfNoPendingRead(), 1000);
+ } finally {
+ inFlightTasks.clear();
+ inFlightTasks.addAll(originalTasks);
+ }
+ }
+
@Test
public void testCreateOrRecycleInFlightTaskIntoQueue() throws Exception {
log.info("Starting testCreateOrRecycleInFlightTaskIntoQueue");