use of org.apache.pulsar.common.policies.data.RetentionPolicies in project incubator-pulsar by apache.
the class PersistentTopicE2ETest method testGcAndRetentionPolicy.
/**
* A topic that has retention policy set to non-0, should not be GCed until it has been inactive for at least the
* retention time.
*/
@Test
public void testGcAndRetentionPolicy() throws Exception {
// Retain data for at-least 10min
admin.namespaces().setRetention("prop/use/ns-abc", new RetentionPolicies(10, 10));
// 1. Simple successful GC
String topicName = "persistent://prop/use/ns-abc/topic-10";
Producer<byte[]> producer = pulsarClient.newProducer().topic(topicName).create();
producer.close();
assertNotNull(pulsar.getBrokerService().getTopicReference(topicName));
runGC();
// Should not have been deleted, since we have retention
assertNotNull(pulsar.getBrokerService().getTopicReference(topicName));
// Remove retention
admin.namespaces().setRetention("prop/use/ns-abc", new RetentionPolicies(0, 10));
Thread.sleep(300);
// 2. Topic is not GCed with live connection
String subName = "sub1";
Consumer<byte[]> consumer = pulsarClient.newConsumer().topic(topicName).subscriptionName(subName).subscribe();
runGC();
assertNotNull(pulsar.getBrokerService().getTopicReference(topicName));
// 3. Topic with subscription is not GCed even with no connections
consumer.close();
runGC();
assertNotNull(pulsar.getBrokerService().getTopicReference(topicName));
// 4. Topic can be GCed after unsubscribe
admin.persistentTopics().deleteSubscription(topicName, subName);
runGC();
assertNull(pulsar.getBrokerService().getTopicReference(topicName));
}
use of org.apache.pulsar.common.policies.data.RetentionPolicies in project incubator-pulsar by apache.
the class BrokerClientIntegrationTest method testResetCursor.
@Test(timeOut = 10000, dataProvider = "subType")
public void testResetCursor(SubscriptionType subType) throws Exception {
final RetentionPolicies policy = new RetentionPolicies(60, 52 * 1024);
final TopicName topicName = TopicName.get("persistent://my-property/use/my-ns/unacked-topic");
final int warmup = 20;
final int testSize = 150;
final List<Message<byte[]>> received = new ArrayList<>();
final String subsId = "sub";
final NavigableMap<Long, TimestampEntryCount> publishTimeIdMap = new ConcurrentSkipListMap<>();
// set delay time to start dispatching messages to active consumer in order to avoid message duplication
conf.setActiveConsumerFailoverDelayTimeMillis(500);
restartBroker();
admin.namespaces().setRetention(topicName.getNamespace(), policy);
ConsumerBuilder<byte[]> consumerBuilder = pulsarClient.newConsumer().topic(topicName.toString()).subscriptionName(subsId).subscriptionType(subType).messageListener((consumer, msg) -> {
try {
synchronized (received) {
received.add(msg);
}
consumer.acknowledge(msg);
long publishTime = ((MessageImpl<?>) msg).getPublishTime();
log.info(" publish time is " + publishTime + "," + msg.getMessageId());
TimestampEntryCount timestampEntryCount = publishTimeIdMap.computeIfAbsent(publishTime, (k) -> new TimestampEntryCount(publishTime));
timestampEntryCount.incrementAndGet();
} catch (final PulsarClientException e) {
log.warn("Failed to ack!");
}
});
Consumer<byte[]> consumer1 = consumerBuilder.subscribe();
Consumer<byte[]> consumer2 = consumerBuilder.subscribe();
final Producer<byte[]> producer = pulsarClient.newProducer().topic(topicName.toString()).create();
log.info("warm up started for " + topicName.toString());
// send warmup msgs
byte[] msgBytes = new byte[1000];
for (Integer i = 0; i < warmup; i++) {
producer.send(msgBytes);
}
log.info("warm up finished.");
// sleep to ensure receiving of msgs
for (int n = 0; n < 10 && received.size() < warmup; n++) {
Thread.sleep(200);
}
// validate received msgs
Assert.assertEquals(received.size(), warmup);
received.clear();
// publish testSize num of msgs
log.info("Sending more messages.");
for (Integer n = 0; n < testSize; n++) {
producer.send(msgBytes);
Thread.sleep(1);
}
log.info("Sending more messages done.");
Thread.sleep(3000);
long begints = publishTimeIdMap.firstEntry().getKey();
long endts = publishTimeIdMap.lastEntry().getKey();
// find reset timestamp
long timestamp = (endts - begints) / 2 + begints;
timestamp = publishTimeIdMap.floorKey(timestamp);
NavigableMap<Long, TimestampEntryCount> expectedMessages = new ConcurrentSkipListMap<>();
expectedMessages.putAll(publishTimeIdMap.tailMap(timestamp, true));
received.clear();
log.info("reset cursor to " + timestamp + " for topic " + topicName.toString() + " for subs " + subsId);
log.info("issuing admin operation on " + admin.getServiceUrl().toString());
List<String> subList = admin.persistentTopics().getSubscriptions(topicName.toString());
for (String subs : subList) {
log.info("got sub " + subs);
}
publishTimeIdMap.clear();
// reset the cursor to this timestamp
Assert.assertTrue(subList.contains(subsId));
admin.persistentTopics().resetCursor(topicName.toString(), subsId, timestamp);
Thread.sleep(3000);
int totalExpected = 0;
for (TimestampEntryCount tec : expectedMessages.values()) {
totalExpected += tec.numMessages;
}
// validate that replay happens after the timestamp
Assert.assertTrue(publishTimeIdMap.firstEntry().getKey() >= timestamp);
consumer1.close();
consumer2.close();
producer.close();
// validate that expected and received counts match
int totalReceived = 0;
for (TimestampEntryCount tec : publishTimeIdMap.values()) {
totalReceived += tec.numMessages;
}
Assert.assertEquals(totalReceived, totalExpected, "did not receive all messages on replay after reset");
resetConfig();
restartBroker();
}
use of org.apache.pulsar.common.policies.data.RetentionPolicies in project incubator-pulsar by apache.
the class BrokerService method getManagedLedgerConfig.
public CompletableFuture<ManagedLedgerConfig> getManagedLedgerConfig(TopicName topicName) {
CompletableFuture<ManagedLedgerConfig> future = new CompletableFuture<>();
// Execute in background thread, since getting the policies might block if the z-node wasn't already cached
pulsar.getOrderedExecutor().submitOrdered(topicName, safeRun(() -> {
NamespaceName namespace = topicName.getNamespaceObject();
ServiceConfiguration serviceConfig = pulsar.getConfiguration();
// Get persistence policy for this topic
Optional<Policies> policies = Optional.empty();
try {
policies = pulsar.getConfigurationCache().policiesCache().get(AdminResource.path(POLICIES, namespace.toString()));
} catch (Throwable t) {
// Ignoring since if we don't have policies, we fallback on the default
log.warn("Got exception when reading persistence policy for {}: {}", topicName, t.getMessage(), t);
future.completeExceptionally(t);
return;
}
PersistencePolicies persistencePolicies = policies.map(p -> p.persistence).orElseGet(() -> new PersistencePolicies(serviceConfig.getManagedLedgerDefaultEnsembleSize(), serviceConfig.getManagedLedgerDefaultWriteQuorum(), serviceConfig.getManagedLedgerDefaultAckQuorum(), serviceConfig.getManagedLedgerDefaultMarkDeleteRateLimit()));
RetentionPolicies retentionPolicies = policies.map(p -> p.retention_policies).orElseGet(() -> new RetentionPolicies(serviceConfig.getDefaultRetentionTimeInMinutes(), serviceConfig.getDefaultRetentionSizeInMB()));
ManagedLedgerConfig managedLedgerConfig = new ManagedLedgerConfig();
managedLedgerConfig.setEnsembleSize(persistencePolicies.getBookkeeperEnsemble());
managedLedgerConfig.setWriteQuorumSize(persistencePolicies.getBookkeeperWriteQuorum());
managedLedgerConfig.setAckQuorumSize(persistencePolicies.getBookkeeperAckQuorum());
managedLedgerConfig.setThrottleMarkDelete(persistencePolicies.getManagedLedgerMaxMarkDeleteRate());
managedLedgerConfig.setDigestType(serviceConfig.getManagedLedgerDigestType());
managedLedgerConfig.setMaxUnackedRangesToPersist(serviceConfig.getManagedLedgerMaxUnackedRangesToPersist());
managedLedgerConfig.setMaxUnackedRangesToPersistInZk(serviceConfig.getManagedLedgerMaxUnackedRangesToPersistInZooKeeper());
managedLedgerConfig.setMaxEntriesPerLedger(serviceConfig.getManagedLedgerMaxEntriesPerLedger());
managedLedgerConfig.setMinimumRolloverTime(serviceConfig.getManagedLedgerMinLedgerRolloverTimeMinutes(), TimeUnit.MINUTES);
managedLedgerConfig.setMaximumRolloverTime(serviceConfig.getManagedLedgerMaxLedgerRolloverTimeMinutes(), TimeUnit.MINUTES);
managedLedgerConfig.setMaxSizePerLedgerMb(2048);
managedLedgerConfig.setMetadataEnsembleSize(serviceConfig.getManagedLedgerDefaultEnsembleSize());
managedLedgerConfig.setMetadataWriteQuorumSize(serviceConfig.getManagedLedgerDefaultWriteQuorum());
managedLedgerConfig.setMetadataAckQuorumSize(serviceConfig.getManagedLedgerDefaultAckQuorum());
managedLedgerConfig.setMetadataMaxEntriesPerLedger(serviceConfig.getManagedLedgerCursorMaxEntriesPerLedger());
managedLedgerConfig.setLedgerRolloverTimeout(serviceConfig.getManagedLedgerCursorRolloverTimeInSeconds());
managedLedgerConfig.setRetentionTime(retentionPolicies.getRetentionTimeInMinutes(), TimeUnit.MINUTES);
managedLedgerConfig.setRetentionSizeInMB(retentionPolicies.getRetentionSizeInMB());
future.complete(managedLedgerConfig);
}, (exception) -> future.completeExceptionally(exception)));
return future;
}
use of org.apache.pulsar.common.policies.data.RetentionPolicies in project incubator-pulsar by apache.
the class AdminApiTest method partitionedTopicsCursorReset.
@Test(dataProvider = "topicName")
public void partitionedTopicsCursorReset(String topicName) throws Exception {
admin.namespaces().setRetention("prop-xyz/use/ns1", new RetentionPolicies(10, 10));
topicName = "persistent://prop-xyz/use/ns1/" + topicName;
admin.persistentTopics().createPartitionedTopic(topicName, 4);
// create consumer and subscription
Consumer<byte[]> consumer = pulsarClient.newConsumer().topic(topicName).subscriptionName("my-sub").subscriptionType(SubscriptionType.Exclusive).subscribe();
List<String> topics = admin.persistentTopics().getList("prop-xyz/use/ns1");
assertEquals(topics.size(), 4);
assertEquals(admin.persistentTopics().getSubscriptions(topicName), Lists.newArrayList("my-sub"));
publishMessagesOnPersistentTopic(topicName, 5, 0);
Thread.sleep(1);
long timestamp = System.currentTimeMillis();
publishMessagesOnPersistentTopic(topicName, 5, 5);
for (int i = 0; i < 10; i++) {
Message<byte[]> message = consumer.receive();
consumer.acknowledge(message);
}
// messages should still be available due to retention
admin.persistentTopics().resetCursor(topicName, "my-sub", timestamp);
Set<String> expectedMessages = Sets.newHashSet();
Set<String> receivedMessages = Sets.newHashSet();
for (int i = 4; i < 10; i++) {
Message<byte[]> message = consumer.receive();
consumer.acknowledge(message);
expectedMessages.add("message-" + i);
receivedMessages.add(new String(message.getData()));
}
receivedMessages.removeAll(expectedMessages);
assertEquals(receivedMessages.size(), 0);
consumer.close();
admin.persistentTopics().deleteSubscription(topicName, "my-sub");
admin.persistentTopics().deletePartitionedTopic(topicName);
}
use of org.apache.pulsar.common.policies.data.RetentionPolicies in project incubator-pulsar by apache.
the class AdminApiTest method persistentTopicsInvalidCursorReset.
@Test
public void persistentTopicsInvalidCursorReset() throws Exception {
admin.namespaces().setRetention("prop-xyz/use/ns1", new RetentionPolicies(10, 10));
assertEquals(admin.persistentTopics().getList("prop-xyz/use/ns1"), Lists.newArrayList());
String topicName = "persistent://prop-xyz/use/ns1/invalidcursorreset";
// Force to create a topic
publishMessagesOnPersistentTopic(topicName, 0);
assertEquals(admin.persistentTopics().getList("prop-xyz/use/ns1"), Lists.newArrayList(topicName));
// create consumer and subscription
URL pulsarUrl = new URL("http://127.0.0.1" + ":" + BROKER_WEBSERVICE_PORT);
PulsarClient client = PulsarClient.builder().serviceUrl(pulsarUrl.toString()).statsInterval(0, TimeUnit.SECONDS).build();
Consumer<byte[]> consumer = client.newConsumer().topic(topicName).subscriptionName("my-sub").subscriptionType(SubscriptionType.Exclusive).subscribe();
assertEquals(admin.persistentTopics().getSubscriptions(topicName), Lists.newArrayList("my-sub"));
publishMessagesOnPersistentTopic(topicName, 10);
List<Message<byte[]>> messages = admin.persistentTopics().peekMessages(topicName, "my-sub", 10);
assertEquals(messages.size(), 10);
for (int i = 0; i < 10; i++) {
Message<byte[]> message = consumer.receive();
consumer.acknowledge(message);
}
// use invalid timestamp
try {
admin.persistentTopics().resetCursor(topicName, "my-sub", System.currentTimeMillis() - 190000);
} catch (Exception e) {
// fail the test
throw e;
}
admin.persistentTopics().resetCursor(topicName, "my-sub", System.currentTimeMillis() + 90000);
consumer = client.newConsumer().topic(topicName).subscriptionName("my-sub").subscribe();
consumer.close();
client.close();
admin.persistentTopics().deleteSubscription(topicName, "my-sub");
assertEquals(admin.persistentTopics().getSubscriptions(topicName), Lists.newArrayList());
admin.persistentTopics().delete(topicName);
}
Aggregations