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

sijie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-pulsar.git


The following commit(s) were added to refs/heads/master by this push:
     new e0fbbcc  Add compaction threshold policy (#1910)
e0fbbcc is described below

commit e0fbbcc390561805c0cf681ed7aff894cb7f2f13
Author: Ivan Kelly <[email protected]>
AuthorDate: Tue Jun 5 20:02:18 2018 +0200

    Add compaction threshold policy (#1910)
    
    Policy is number of bytes at which compaction should be triggered for
    a topic.
    
    This patch contains the policy itself, and the check. Subsequent patches
    will include the monitor and rest api.
---
 .../service/persistent/PersistentSubscription.java |  4 ++
 .../broker/service/persistent/PersistentTopic.java | 36 ++++++++++
 .../pulsar/broker/service/PersistentTopicTest.java | 83 ++++++++++++++++++++++
 .../pulsar/common/policies/data/Policies.java      |  8 ++-
 4 files changed, 129 insertions(+), 2 deletions(-)

diff --git 
a/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/persistent/PersistentSubscription.java
 
b/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/persistent/PersistentSubscription.java
index bdace55..54ac65f 100644
--- 
a/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/persistent/PersistentSubscription.java
+++ 
b/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/persistent/PersistentSubscription.java
@@ -630,6 +630,10 @@ public class PersistentSubscription implements 
Subscription {
         return expiryMonitor.getMessageExpiryRate();
     }
 
+    public long estimateBacklogSize() {
+        return cursor.getEstimatedSizeSinceMarkDeletePosition();
+    }
+
     public SubscriptionStats getStats() {
         SubscriptionStats subStats = new SubscriptionStats();
 
diff --git 
a/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/persistent/PersistentTopic.java
 
b/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/persistent/PersistentTopic.java
index 3cfddb0..4768fa8 100644
--- 
a/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/persistent/PersistentTopic.java
+++ 
b/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/persistent/PersistentTopic.java
@@ -970,6 +970,42 @@ public class PersistentTopic implements Topic, 
AddEntryCallback {
         messageDeduplication.purgeInactiveProducers();
     }
 
+    public void checkCompaction() {
+        TopicName name = TopicName.get(topic);
+        try {
+            Policies policies = 
brokerService.pulsar().getConfigurationCache().policiesCache()
+                .get(AdminResource.path(POLICIES, name.getNamespace()))
+                .orElseThrow(() -> new KeeperException.NoNodeException());
+
+
+            if (policies.compaction_threshold != 0
+                && currentCompaction.isDone()) {
+
+                long backlogEstimate = 0;
+
+                PersistentSubscription compactionSub = 
subscriptions.get(Compactor.COMPACTION_SUBSCRIPTION);
+                if (compactionSub != null) {
+                    backlogEstimate = compactionSub.estimateBacklogSize();
+                } else {
+                    // compaction has never run, so take full backlog size
+                    backlogEstimate = ledger.getEstimatedBacklogSize();
+                }
+
+                if (backlogEstimate > policies.compaction_threshold) {
+                    try {
+                        triggerCompaction();
+                    } catch (AlreadyRunningException are) {
+                        log.debug("[{}] Compaction already running, so don't 
trigger again, "
+                                  + "even though backlog({}) is over 
threshold({})",
+                                  name, backlogEstimate, 
policies.compaction_threshold);
+                    }
+                }
+            }
+        } catch (Exception e) {
+            log.debug("[{}] Error getting policies", topic);
+        }
+    }
+
     CompletableFuture<Void> startReplicator(String remoteCluster) {
         log.info("[{}] Starting replicator to remote: {}", topic, 
remoteCluster);
         final CompletableFuture<Void> future = new CompletableFuture<>();
diff --git 
a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PersistentTopicTest.java
 
b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PersistentTopicTest.java
index 17d282e..db35e74 100644
--- 
a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PersistentTopicTest.java
+++ 
b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PersistentTopicTest.java
@@ -31,6 +31,7 @@ import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 import static org.testng.Assert.assertEquals;
@@ -79,6 +80,7 @@ import org.apache.pulsar.broker.admin.AdminResource;
 import org.apache.pulsar.broker.cache.ConfigurationCacheService;
 import org.apache.pulsar.broker.cache.LocalZooKeeperCacheService;
 import org.apache.pulsar.broker.namespace.NamespaceService;
+import org.apache.pulsar.broker.service.Topic.PublishContext;
 import org.apache.pulsar.broker.service.nonpersistent.NonPersistentReplicator;
 import org.apache.pulsar.broker.service.persistent.CompactorSubscription;
 import 
org.apache.pulsar.broker.service.persistent.PersistentDispatcherMultipleConsumers;
@@ -115,6 +117,7 @@ import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
@@ -143,6 +146,7 @@ public class PersistentTopicTest {
         ServiceConfiguration svcConfig = spy(new ServiceConfiguration());
         pulsar = spy(new PulsarService(svcConfig));
         doReturn(svcConfig).when(pulsar).getConfiguration();
+        doReturn(mock(Compactor.class)).when(pulsar).getCompactor();
 
         mlFactoryMock = mock(ManagedLedgerFactory.class);
         doReturn(mlFactoryMock).when(pulsar).getManagedLedgerFactory();
@@ -1264,4 +1268,83 @@ public class PersistentTopicTest {
         new CompactorSubscription(topic, compactedTopic, 
Compactor.COMPACTION_SUBSCRIPTION, cursorMock);
         verify(compactedTopic, Mockito.times(1)).newCompactedLedger(position, 
ledgerId);
     }
+
+    @Test
+    public void testCompactionTriggeredAfterThresholdFirstInvocation() throws 
Exception {
+        CompletableFuture<Long> compactPromise = new CompletableFuture<>();
+        Compactor compactor = pulsar.getCompactor();
+        doReturn(compactPromise).when(compactor).compact(anyString());
+
+        Policies policies = new Policies();
+        policies.compaction_threshold = 1;
+        when(pulsar.getConfigurationCache().policiesCache()
+                .get(AdminResource.path(POLICIES, 
TopicName.get(successTopicName).getNamespace())))
+                .thenReturn(Optional.of(policies));
+
+        PersistentTopic topic = new PersistentTopic(successTopicName, 
ledgerMock, brokerService);
+
+        topic.checkCompaction();
+
+        verify(compactor, times(0)).compact(anyString());
+
+        doReturn(10L).when(ledgerMock).getEstimatedBacklogSize();
+
+        topic.checkCompaction();
+        verify(compactor, times(1)).compact(anyString());
+
+        // run a second time, shouldn't run again because already running
+        topic.checkCompaction();
+        verify(compactor, times(1)).compact(anyString());
+    }
+
+    @Test
+    public void testCompactionTriggeredAfterThresholdSecondInvocation() throws 
Exception {
+        CompletableFuture<Long> compactPromise = new CompletableFuture<>();
+        Compactor compactor = pulsar.getCompactor();
+        doReturn(compactPromise).when(compactor).compact(anyString());
+
+        ManagedCursor subCursor = mock(ManagedCursor.class);
+        doReturn(Lists.newArrayList(subCursor)).when(ledgerMock).getCursors();
+        doReturn(Compactor.COMPACTION_SUBSCRIPTION).when(subCursor).getName();
+
+        Policies policies = new Policies();
+        policies.compaction_threshold = 1;
+        when(pulsar.getConfigurationCache().policiesCache()
+                .get(AdminResource.path(POLICIES, 
TopicName.get(successTopicName).getNamespace())))
+                .thenReturn(Optional.of(policies));
+
+        PersistentTopic topic = new PersistentTopic(successTopicName, 
ledgerMock, brokerService);
+
+        topic.checkCompaction();
+
+        verify(compactor, times(0)).compact(anyString());
+
+        
doReturn(10L).when(subCursor).getEstimatedSizeSinceMarkDeletePosition();
+
+        topic.checkCompaction();
+        verify(compactor, times(1)).compact(anyString());
+
+        // run a second time, shouldn't run again because already running
+        topic.checkCompaction();
+        verify(compactor, times(1)).compact(anyString());
+    }
+
+    @Test
+    public void testCompactionDisabledWithZeroThreshold() throws Exception {
+        CompletableFuture<Long> compactPromise = new CompletableFuture<>();
+        Compactor compactor = pulsar.getCompactor();
+        doReturn(compactPromise).when(compactor).compact(anyString());
+
+        Policies policies = new Policies();
+        policies.compaction_threshold = 0;
+        when(pulsar.getConfigurationCache().policiesCache()
+                .get(AdminResource.path(POLICIES, 
TopicName.get(successTopicName).getNamespace())))
+                .thenReturn(Optional.of(policies));
+
+        doReturn(1000L).when(ledgerMock).getEstimatedBacklogSize();
+
+        PersistentTopic topic = new PersistentTopic(successTopicName, 
ledgerMock, brokerService);
+        topic.checkCompaction();
+        verify(compactor, times(0)).compact(anyString());
+    }
 }
diff --git 
a/pulsar-common/src/main/java/org/apache/pulsar/common/policies/data/Policies.java
 
b/pulsar-common/src/main/java/org/apache/pulsar/common/policies/data/Policies.java
index 59c1b3a..a33119e 100644
--- 
a/pulsar-common/src/main/java/org/apache/pulsar/common/policies/data/Policies.java
+++ 
b/pulsar-common/src/main/java/org/apache/pulsar/common/policies/data/Policies.java
@@ -57,6 +57,8 @@ public class Policies {
     public int max_consumers_per_topic = 0;
     public int max_consumers_per_subscription = 0;
 
+    public long compaction_threshold = 0;
+
     @Override
     public boolean equals(Object obj) {
         if (obj instanceof Policies) {
@@ -75,7 +77,8 @@ public class Policies {
                     && Objects.equals(antiAffinityGroup, 
other.antiAffinityGroup)
                     && max_producers_per_topic == other.max_producers_per_topic
                     && max_consumers_per_topic == other.max_consumers_per_topic
-                    && max_consumers_per_subscription == 
other.max_consumers_per_subscription;
+                    && max_consumers_per_subscription == 
other.max_consumers_per_subscription
+                    && compaction_threshold == other.compaction_threshold;
         }
 
         return false;
@@ -105,6 +108,7 @@ public class Policies {
                 .add("subscription_auth_mode", subscription_auth_mode)
                 .add("max_producers_per_topic", max_producers_per_topic)
                 .add("max_consumers_per_topic", max_consumers_per_topic)
-                .add("max_consumers_per_subscription", 
max_consumers_per_topic).toString();
+                .add("max_consumers_per_subscription", max_consumers_per_topic)
+                .add("compaction_threshold", compaction_threshold).toString();
     }
 }

-- 
To stop receiving notification emails like this one, please contact
[email protected].

Reply via email to