use of java.util.concurrent.CompletableFuture in project pulsar by yahoo.
the class MessagingServiceShutdownHook method run.
@Override
public void run() {
if (service.getConfiguration() != null) {
LOG.info("messaging service shutdown hook started, lookup port=" + service.getConfiguration().getWebServicePort() + ", broker url=" + service.getBrokerServiceUrl());
}
ExecutorService executor = Executors.newSingleThreadExecutor(new DefaultThreadFactory("shutdown-thread"));
try {
CompletableFuture<Void> future = new CompletableFuture<>();
executor.execute(() -> {
try {
service.close();
future.complete(null);
} catch (PulsarServerException e) {
future.completeExceptionally(e);
}
});
future.get(service.getConfiguration().getBrokerShutdownTimeoutMs(), TimeUnit.MILLISECONDS);
LOG.info("Completed graceful shutdown. Exiting");
} catch (TimeoutException e) {
LOG.warn("Graceful shutdown timeout expired. Closing now");
} catch (Exception e) {
LOG.error("Failed to perform graceful shutdown, Exiting anyway", e);
} finally {
immediateFlushBufferedLogs();
// always put system to halt immediately
Runtime.getRuntime().halt(0);
}
}
use of java.util.concurrent.CompletableFuture in project pulsar by yahoo.
the class BrokerService method getManagedLedgerConfig.
public CompletableFuture<ManagedLedgerConfig> getManagedLedgerConfig(DestinationName 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 destination
Policies policies;
try {
policies = pulsar.getConfigurationCache().policiesCache().get(AdminResource.path("policies", namespace.getProperty(), namespace.getCluster(), namespace.getLocalName())).orElse(null);
} 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 != null ? policies.persistence : null;
RetentionPolicies retentionPolicies = policies != null ? policies.retention_policies : null;
if (persistencePolicies == null) {
// Apply default values
persistencePolicies = new PersistencePolicies(serviceConfig.getManagedLedgerDefaultEnsembleSize(), serviceConfig.getManagedLedgerDefaultWriteQuorum(), serviceConfig.getManagedLedgerDefaultAckQuorum(), serviceConfig.getManagedLedgerDefaultMarkDeleteRateLimit());
}
if (retentionPolicies == null) {
retentionPolicies = new RetentionPolicies(serviceConfig.getDefaultRetentionTimeInMinutes(), serviceConfig.getDefaultRetentionSizeInMB());
}
ManagedLedgerConfig config = new ManagedLedgerConfig();
config.setEnsembleSize(persistencePolicies.getBookkeeperEnsemble());
config.setWriteQuorumSize(persistencePolicies.getBookkeeperWriteQuorum());
config.setAckQuorumSize(persistencePolicies.getBookkeeperAckQuorum());
config.setThrottleMarkDelete(persistencePolicies.getManagedLedgerMaxMarkDeleteRate());
config.setDigestType(DigestType.CRC32);
config.setMaxUnackedRangesToPersist(serviceConfig.getManagedLedgerMaxUnackedRangesToPersist());
config.setMaxEntriesPerLedger(serviceConfig.getManagedLedgerMaxEntriesPerLedger());
config.setMinimumRolloverTime(serviceConfig.getManagedLedgerMinLedgerRolloverTimeMinutes(), TimeUnit.MINUTES);
config.setMaximumRolloverTime(serviceConfig.getManagedLedgerMaxLedgerRolloverTimeMinutes(), TimeUnit.MINUTES);
config.setMaxSizePerLedgerMb(2048);
config.setMetadataEnsembleSize(serviceConfig.getManagedLedgerDefaultEnsembleSize());
config.setMetadataWriteQuorumSize(serviceConfig.getManagedLedgerDefaultWriteQuorum());
config.setMetadataAckQuorumSize(serviceConfig.getManagedLedgerDefaultAckQuorum());
config.setMetadataMaxEntriesPerLedger(serviceConfig.getManagedLedgerCursorMaxEntriesPerLedger());
config.setLedgerRolloverTimeout(serviceConfig.getManagedLedgerCursorRolloverTimeInSeconds());
config.setRetentionTime(retentionPolicies.getRetentionTimeInMinutes(), TimeUnit.MINUTES);
config.setRetentionSizeInMB(retentionPolicies.getRetentionSizeInMB());
future.complete(config);
}, (exception) -> future.completeExceptionally(exception)));
return future;
}
use of java.util.concurrent.CompletableFuture in project pulsar by yahoo.
the class NamespaceService method findBrokerServiceUrl.
/**
* Main internal method to lookup and setup ownership of service unit to a broker
*
* @param bundle
* @param authoritative
* @param readOnly
* @return
* @throws PulsarServerException
*/
private CompletableFuture<LookupResult> findBrokerServiceUrl(NamespaceBundle bundle, boolean authoritative, boolean readOnly) {
if (LOG.isDebugEnabled()) {
LOG.debug("findBrokerServiceUrl: {} - read-only: {}", bundle, readOnly);
}
CompletableFuture<LookupResult> future = new CompletableFuture<>();
// First check if we or someone else already owns the bundle
ownershipCache.getOwnerAsync(bundle).thenAccept(nsData -> {
if (!nsData.isPresent()) {
if (readOnly) {
future.completeExceptionally(new IllegalStateException(String.format("Can't find owner of ServiceUnit: %s", bundle)));
} else {
pulsar.getExecutor().execute(() -> {
searchForCandidateBroker(bundle, future, authoritative);
});
}
} else if (nsData.get().isDisabled()) {
future.completeExceptionally(new IllegalStateException(String.format("Namespace bundle %s is being unloaded", bundle)));
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("Namespace bundle {} already owned by {} ", bundle, nsData);
}
future.complete(new LookupResult(nsData.get()));
}
}).exceptionally(exception -> {
LOG.warn("Failed to check owner for bundle {}: {}", bundle, exception.getMessage(), exception);
future.completeExceptionally(exception);
return null;
});
return future;
}
use of java.util.concurrent.CompletableFuture in project pulsar by yahoo.
the class Namespaces method clearBacklog.
private void clearBacklog(NamespaceName nsName, String bundleRange, String subscription) {
try {
List<PersistentTopic> topicList = pulsar().getBrokerService().getAllTopicsFromNamespaceBundle(nsName.toString(), nsName.toString() + "/" + bundleRange);
List<CompletableFuture<Void>> futures = Lists.newArrayList();
if (subscription != null) {
if (subscription.startsWith(pulsar().getConfiguration().getReplicatorPrefix())) {
subscription = PersistentReplicator.getRemoteCluster(subscription);
}
for (PersistentTopic topic : topicList) {
futures.add(topic.clearBacklog(subscription));
}
} else {
for (PersistentTopic topic : topicList) {
futures.add(topic.clearBacklog());
}
}
FutureUtil.waitForAll(futures).get();
} catch (Exception e) {
log.error("[{}] Failed to clear backlog for namespace {}/{}, subscription: {}", clientAppId(), nsName.toString(), bundleRange, subscription, e);
throw new RestException(e);
}
}
use of java.util.concurrent.CompletableFuture in project pulsar by yahoo.
the class PersistentTopics method deletePartitionedTopic.
@DELETE
@Path("/{property}/{cluster}/{namespace}/{destination}/partitions")
@ApiOperation(value = "Delete a partitioned topic.", notes = "It will also delete all the partitions of the topic if it exists.")
@ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), @ApiResponse(code = 404, message = "Partitioned topic does not exist") })
public void deletePartitionedTopic(@PathParam("property") String property, @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, @PathParam("destination") @Encoded String destination, @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) {
destination = decode(destination);
DestinationName dn = DestinationName.get(domain(), property, cluster, namespace, destination);
validateAdminAccessOnProperty(dn.getProperty());
PartitionedTopicMetadata partitionMetadata = getPartitionedTopicMetadata(property, cluster, namespace, destination, authoritative);
int numPartitions = partitionMetadata.partitions;
if (numPartitions > 0) {
final CompletableFuture<Void> future = new CompletableFuture<>();
final AtomicInteger count = new AtomicInteger(numPartitions);
try {
for (int i = 0; i < numPartitions; i++) {
DestinationName dn_partition = dn.getPartition(i);
pulsar().getAdminClient().persistentTopics().deleteAsync(dn_partition.toString()).whenComplete((r, ex) -> {
if (ex != null) {
if (ex instanceof NotFoundException) {
// partition is failed to be deleted
if (log.isDebugEnabled()) {
log.debug("[{}] Partition not found: {}", clientAppId(), dn_partition);
}
} else {
future.completeExceptionally(ex);
log.error("[{}] Failed to delete partition {}", clientAppId(), dn_partition, ex);
return;
}
} else {
log.info("[{}] Deleted partition {}", clientAppId(), dn_partition);
}
if (count.decrementAndGet() == 0) {
future.complete(null);
}
});
}
future.get();
} catch (Exception e) {
Throwable t = e.getCause();
if (t instanceof PreconditionFailedException) {
throw new RestException(Status.PRECONDITION_FAILED, "Topic has active producers/subscriptions");
} else {
throw new RestException(t);
}
}
}
// Only tries to delete the znode for partitioned topic when all its partitions are successfully deleted
String path = path(PARTITIONED_TOPIC_PATH_ZNODE, property, cluster, namespace, domain(), dn.getEncodedLocalName());
try {
globalZk().delete(path, -1);
globalZkCache().invalidate(path);
// we wait for the data to be synced in all quorums and the observers
Thread.sleep(PARTITIONED_TOPIC_WAIT_SYNC_TIME_MS);
log.info("[{}] Deleted partitioned topic {}", clientAppId(), dn);
} catch (KeeperException.NoNodeException nne) {
throw new RestException(Status.NOT_FOUND, "Partitioned topic does not exist");
} catch (Exception e) {
log.error("[{}] Failed to delete partitioned topic {}", clientAppId(), dn, e);
throw new RestException(e);
}
}
Aggregations