List of usage examples for java.util.concurrent CompletableFuture completeExceptionally
public boolean completeExceptionally(Throwable ex)
From source file:org.apache.pulsar.broker.namespace.NamespaceService.java
protected CompletableFuture<LookupResult> createLookupResult(String candidateBroker) throws Exception { CompletableFuture<LookupResult> lookupFuture = new CompletableFuture<>(); try {//from w w w . j a v a 2 s.c om checkArgument(StringUtils.isNotBlank(candidateBroker), "Lookup broker can't be null " + candidateBroker); URI uri = new URI(candidateBroker); String path = String.format("%s/%s:%s", LoadManager.LOADBALANCE_BROKERS_ROOT, uri.getHost(), uri.getPort()); pulsar.getLocalZkCache().getDataAsync(path, pulsar.getLoadManager().get().getLoadReportDeserializer()) .thenAccept(reportData -> { if (reportData.isPresent()) { ServiceLookupData lookupData = reportData.get(); lookupFuture.complete(new LookupResult(lookupData.getWebServiceUrl(), lookupData.getWebServiceUrlTls(), lookupData.getPulsarServiceUrl(), lookupData.getPulsarServiceUrlTls())); } else { lookupFuture.completeExceptionally(new KeeperException.NoNodeException(path)); } }).exceptionally(ex -> { lookupFuture.completeExceptionally(ex); return null; }); } catch (Exception e) { lookupFuture.completeExceptionally(e); } return lookupFuture; }
From source file:org.apache.pulsar.broker.namespace.NamespaceService.java
/** * 1. split the given bundle into two bundles 2. assign ownership of both the bundles to current broker 3. update * policies with newly created bundles into LocalZK 4. disable original bundle and refresh the cache * * @param bundle/*from w ww . j ava 2s . c o m*/ * @return * @throws Exception */ public CompletableFuture<Void> splitAndOwnBundle(NamespaceBundle bundle) throws Exception { final CompletableFuture<Void> future = new CompletableFuture<>(); Pair<NamespaceBundles, List<NamespaceBundle>> splittedBundles = bundleFactory.splitBundles(bundle, 2 /* by default split into 2 */); if (splittedBundles != null) { checkNotNull(splittedBundles.getLeft()); checkNotNull(splittedBundles.getRight()); checkArgument(splittedBundles.getRight().size() == 2, "bundle has to be split in two bundles"); NamespaceName nsname = bundle.getNamespaceObject(); try { // take ownership of newly split bundles for (NamespaceBundle sBundle : splittedBundles.getRight()) { checkNotNull(ownershipCache.tryAcquiringOwnership(sBundle)); } updateNamespaceBundles(nsname, splittedBundles.getLeft(), (rc, path, zkCtx, stat) -> pulsar.getOrderedExecutor().submit(safeRun(() -> { if (rc == KeeperException.Code.OK.intValue()) { // disable old bundle try { ownershipCache.disableOwnership(bundle); // invalidate cache as zookeeper has new split // namespace bundle bundleFactory.invalidateBundleCache(nsname); // update bundled_topic cache for load-report-generation pulsar.getBrokerService().refreshTopicToStatsMaps(bundle); loadManager.get().setLoadReportForceUpdateFlag(); future.complete(null); } catch (Exception e) { String msg1 = format( "failed to disable bundle %s under namespace [%s] with error %s", nsname.toString(), bundle.toString(), e.getMessage()); LOG.warn(msg1, e); future.completeExceptionally(new ServiceUnitNotReadyException(msg1)); } } else { String msg2 = format("failed to update namespace [%s] policies due to %s", nsname.toString(), KeeperException.create(KeeperException.Code.get(rc)).getMessage()); LOG.warn(msg2); future.completeExceptionally(new ServiceUnitNotReadyException(msg2)); } }))); } catch (Exception e) { String msg = format("failed to aquire ownership of split bundle for namespace [%s], %s", nsname.toString(), e.getMessage()); LOG.warn(msg, e); future.completeExceptionally(new ServiceUnitNotReadyException(msg)); } } else { String msg = format("bundle %s not found under namespace", bundle.toString()); future.completeExceptionally(new ServiceUnitNotReadyException(msg)); } return future; }
From source file:org.apache.pulsar.broker.service.BrokerService.java
private void createPersistentTopic(final String topic, CompletableFuture<Topic> topicFuture) { final long topicCreateTimeMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime()); DestinationName destinationName = DestinationName.get(topic); if (!pulsar.getNamespaceService().isServiceUnitActive(destinationName)) { // namespace is being unloaded String msg = String.format("Namespace is being unloaded, cannot add topic %s", topic); log.warn(msg);/*w w w .j a v a 2s.c o m*/ pulsar.getExecutor().submit(() -> topics.remove(topic, topicFuture)); topicFuture.completeExceptionally(new ServiceUnitNotReadyException(msg)); return; } getManagedLedgerConfig(destinationName).thenAccept(config -> { // Once we have the configuration, we can proceed with the async open operation managedLedgerFactory.asyncOpen(destinationName.getPersistenceNamingEncoding(), config, new OpenLedgerCallback() { @Override public void openLedgerComplete(ManagedLedger ledger, Object ctx) { PersistentTopic persistentTopic = new PersistentTopic(topic, ledger, BrokerService.this); CompletableFuture<Void> replicationFuture = persistentTopic.checkReplication(); replicationFuture.thenRun(() -> { log.info("Created topic {}", topic); long topicLoadLatencyMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) - topicCreateTimeMs; pulsarStats.recordTopicLoadTimeValue(topic, topicLoadLatencyMs); addTopicToStatsMaps(destinationName, persistentTopic); topicFuture.complete(persistentTopic); }); replicationFuture.exceptionally((ex) -> { log.warn("Replication check failed. Removing topic from topics list {}, {}", topic, ex); persistentTopic.stopReplProducers().whenComplete((v, exception) -> { topics.remove(topic, topicFuture); topicFuture.completeExceptionally(ex); }); return null; }); } @Override public void openLedgerFailed(ManagedLedgerException exception, Object ctx) { log.warn("Failed to create topic {}", topic, exception); topics.remove(topic, topicFuture); topicFuture.completeExceptionally(new PersistenceException(exception)); } }, null); }).exceptionally((exception) -> { log.warn("[{}] Failed to get topic configuration: {}", topic, exception.getMessage(), exception); // remove topic from topics-map in different thread to avoid possible deadlock if // createPersistentTopic-thread only tries to handle this future-result pulsar.getExecutor().submit(() -> topics.remove(topic, topicFuture)); topicFuture.completeExceptionally(exception); return null; }); }
From source file:org.apache.pulsar.broker.service.BrokerService.java
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;/* ww w .j a v a 2s . c om*/ 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; }
From source file:org.apache.pulsar.broker.service.persistent.PersistentTopic.java
@Override public CompletableFuture<Consumer> subscribe(final ServerCnx cnx, String subscriptionName, long consumerId, SubType subType, int priorityLevel, String consumerName, boolean isDurable, MessageId startMessageId, Map<String, String> metadata, boolean readCompacted, InitialPosition initialPosition) { final CompletableFuture<Consumer> future = new CompletableFuture<>(); try {/*from ww w .j a v a2s . c o m*/ brokerService.checkTopicNsOwnership(getName()); } catch (Exception e) { future.completeExceptionally(e); return future; } if (readCompacted && !(subType == SubType.Failover || subType == SubType.Exclusive)) { future.completeExceptionally( new NotAllowedException("readCompacted only allowed on failover or exclusive subscriptions")); return future; } if (isBlank(subscriptionName)) { if (log.isDebugEnabled()) { log.debug("[{}] Empty subscription name", topic); } future.completeExceptionally(new NamingException("Empty subscription name")); return future; } if (hasBatchMessagePublished && !cnx.isBatchMessageCompatibleVersion()) { if (log.isDebugEnabled()) { log.debug("[{}] Consumer doesn't support batch-message {}", topic, subscriptionName); } future.completeExceptionally(new UnsupportedVersionException("Consumer doesn't support batch-message")); return future; } if (subscriptionName.startsWith(replicatorPrefix) || subscriptionName.equals(DEDUPLICATION_CURSOR_NAME)) { log.warn("[{}] Failed to create subscription for {}", topic, subscriptionName); future.completeExceptionally( new NamingException("Subscription with reserved subscription name attempted")); return future; } if (cnx.getRemoteAddress() != null && cnx.getRemoteAddress().toString().contains(":")) { SubscribeRateLimiter.ConsumerIdentifier consumer = new SubscribeRateLimiter.ConsumerIdentifier( cnx.getRemoteAddress().toString().split(":")[0], consumerName, consumerId); if (subscribeRateLimiter.isPresent() && !subscribeRateLimiter.get().subscribeAvailable(consumer) || !subscribeRateLimiter.get().tryAcquire(consumer)) { log.warn("[{}] Failed to create subscription for {} {} limited by {}, available {}", topic, subscriptionName, consumer, subscribeRateLimiter.get().getSubscribeRate(), subscribeRateLimiter.get().getAvailableSubscribeRateLimit(consumer)); future.completeExceptionally( new NotAllowedException("Subscribe limited by subscribe rate limit per consumer.")); return future; } } lock.readLock().lock(); try { if (isFenced) { log.warn("[{}] Attempting to subscribe to a fenced topic", topic); future.completeExceptionally(new TopicFencedException("Topic is temporarily unavailable")); return future; } USAGE_COUNT_UPDATER.incrementAndGet(this); if (log.isDebugEnabled()) { log.debug("[{}] [{}] [{}] Added consumer -- count: {}", topic, subscriptionName, consumerName, USAGE_COUNT_UPDATER.get(this)); } } finally { lock.readLock().unlock(); } CompletableFuture<? extends Subscription> subscriptionFuture = isDurable ? // getDurableSubscription(subscriptionName, initialPosition) // : getNonDurableSubscription(subscriptionName, startMessageId); int maxUnackedMessages = isDurable ? brokerService.pulsar().getConfiguration().getMaxUnackedMessagesPerConsumer() : 0; subscriptionFuture.thenAccept(subscription -> { try { Consumer consumer = new Consumer(subscription, subType, topic, consumerId, priorityLevel, consumerName, maxUnackedMessages, cnx, cnx.getRole(), metadata, readCompacted, initialPosition); subscription.addConsumer(consumer); if (!cnx.isActive()) { consumer.close(); if (log.isDebugEnabled()) { log.debug("[{}] [{}] [{}] Subscribe failed -- count: {}", topic, subscriptionName, consumer.consumerName(), USAGE_COUNT_UPDATER.get(PersistentTopic.this)); } future.completeExceptionally( new BrokerServiceException("Connection was closed while the opening the cursor ")); } else { log.info("[{}][{}] Created new subscription for {}", topic, subscriptionName, consumerId); future.complete(consumer); } } catch (BrokerServiceException e) { if (e instanceof ConsumerBusyException) { log.warn("[{}][{}] Consumer {} {} already connected", topic, subscriptionName, consumerId, consumerName); } else if (e instanceof SubscriptionBusyException) { log.warn("[{}][{}] {}", topic, subscriptionName, e.getMessage()); } USAGE_COUNT_UPDATER.decrementAndGet(PersistentTopic.this); future.completeExceptionally(e); } }).exceptionally(ex -> { log.warn("[{}] Failed to create subscription for {}: ", topic, subscriptionName, ex.getMessage()); USAGE_COUNT_UPDATER.decrementAndGet(PersistentTopic.this); future.completeExceptionally(new PersistenceException(ex)); return null; }); return future; }
From source file:org.apache.pulsar.broker.service.persistent.PersistentTopic.java
private CompletableFuture<Subscription> getDurableSubscription(String subscriptionName, InitialPosition initialPosition) { CompletableFuture<Subscription> subscriptionFuture = new CompletableFuture<>(); ledger.asyncOpenCursor(Codec.encode(subscriptionName), initialPosition, new OpenCursorCallback() { @Override// ww w . j av a 2 s . c om public void openCursorComplete(ManagedCursor cursor, Object ctx) { if (log.isDebugEnabled()) { log.debug("[{}][{}] Opened cursor", topic, subscriptionName); } subscriptionFuture.complete(subscriptions.computeIfAbsent(subscriptionName, name -> createPersistentSubscription(subscriptionName, cursor))); } @Override public void openCursorFailed(ManagedLedgerException exception, Object ctx) { log.warn("[{}] Failed to create subscription for {}: {}", topic, subscriptionName, exception.getMessage()); USAGE_COUNT_UPDATER.decrementAndGet(PersistentTopic.this); subscriptionFuture.completeExceptionally(new PersistenceException(exception)); if (exception instanceof ManagedLedgerFencedException) { // If the managed ledger has been fenced, we cannot continue using it. We need to close and reopen close(); } } }, null); return subscriptionFuture; }
From source file:org.apache.pulsar.broker.service.persistent.PersistentTopic.java
private CompletableFuture<? extends Subscription> getNonDurableSubscription(String subscriptionName, MessageId startMessageId) {/*www .j a v a 2 s . c om*/ CompletableFuture<Subscription> subscriptionFuture = new CompletableFuture<>(); log.info("[{}][{}] Creating non-durable subscription at msg id {}", topic, subscriptionName, startMessageId); // Create a new non-durable cursor only for the first consumer that connects Subscription subscription = subscriptions.computeIfAbsent(subscriptionName, name -> { MessageIdImpl msgId = startMessageId != null ? (MessageIdImpl) startMessageId : (MessageIdImpl) MessageId.latest; long ledgerId = msgId.getLedgerId(); long entryId = msgId.getEntryId(); if (msgId instanceof BatchMessageIdImpl) { // When the start message is relative to a batch, we need to take one step back on the previous message, // because the "batch" might not have been consumed in its entirety. // The client will then be able to discard the first messages in the batch. if (((BatchMessageIdImpl) msgId).getBatchIndex() >= 0) { entryId = msgId.getEntryId() - 1; } } Position startPosition = new PositionImpl(ledgerId, entryId); ManagedCursor cursor = null; try { cursor = ledger.newNonDurableCursor(startPosition); } catch (ManagedLedgerException e) { subscriptionFuture.completeExceptionally(e); } return new PersistentSubscription(this, subscriptionName, cursor); }); if (!subscriptionFuture.isDone()) { subscriptionFuture.complete(subscription); } else { // failed to initialize managed-cursor: clean up created subscription subscriptions.remove(subscriptionName); } return subscriptionFuture; }
From source file:org.apache.pulsar.broker.service.persistent.PersistentTopic.java
/** * Delete the cursor ledger for a given subscription * * @param subscriptionName/* w w w . ja v a 2 s .c o m*/ * Subscription for which the cursor ledger is to be deleted * @return Completable future indicating completion of unsubscribe operation Completed exceptionally with: * ManagedLedgerException if cursor ledger delete fails */ @Override public CompletableFuture<Void> unsubscribe(String subscriptionName) { CompletableFuture<Void> unsubscribeFuture = new CompletableFuture<>(); ledger.asyncDeleteCursor(Codec.encode(subscriptionName), new DeleteCursorCallback() { @Override public void deleteCursorComplete(Object ctx) { if (log.isDebugEnabled()) { log.debug("[{}][{}] Cursor deleted successfully", topic, subscriptionName); } subscriptions.remove(subscriptionName); unsubscribeFuture.complete(null); lastActive = System.nanoTime(); } @Override public void deleteCursorFailed(ManagedLedgerException exception, Object ctx) { if (log.isDebugEnabled()) { log.debug("[{}][{}] Error deleting cursor for subscription", topic, subscriptionName, exception); } unsubscribeFuture.completeExceptionally(new PersistenceException(exception)); } }, null); return unsubscribeFuture; }
From source file:org.apache.pulsar.broker.service.persistent.PersistentTopic.java
/** * Delete the managed ledger associated with this topic * * @param failIfHasSubscriptions//from w w w.j a va2 s . c om * Flag indicating whether delete should succeed if topic still has unconnected subscriptions. Set to * false when called from admin API (it will delete the subs too), and set to true when called from GC * thread * @param closeIfClientsConnected * Flag indicate whether explicitly close connected producers/consumers/replicators before trying to delete topic. If * any client is connected to a topic and if this flag is disable then this operation fails. * * @return Completable future indicating completion of delete operation Completed exceptionally with: * IllegalStateException if topic is still active ManagedLedgerException if ledger delete operation fails */ private CompletableFuture<Void> delete(boolean failIfHasSubscriptions, boolean closeIfClientsConnected) { CompletableFuture<Void> deleteFuture = new CompletableFuture<>(); lock.writeLock().lock(); try { if (isFenced) { log.warn("[{}] Topic is already being closed or deleted", topic); deleteFuture.completeExceptionally(new TopicFencedException("Topic is already fenced")); return deleteFuture; } CompletableFuture<Void> closeClientFuture = new CompletableFuture<>(); if (closeIfClientsConnected) { List<CompletableFuture<Void>> futures = Lists.newArrayList(); replicators.forEach((cluster, replicator) -> futures.add(replicator.disconnect())); producers.forEach(producer -> futures.add(producer.disconnect())); subscriptions.forEach((s, sub) -> futures.add(sub.disconnect())); FutureUtil.waitForAll(futures).thenRun(() -> { closeClientFuture.complete(null); }).exceptionally(ex -> { log.error("[{}] Error closing clients", topic, ex); isFenced = false; closeClientFuture.completeExceptionally(ex); return null; }); } else { closeClientFuture.complete(null); } closeClientFuture.thenAccept(delete -> { if (USAGE_COUNT_UPDATER.get(this) == 0) { isFenced = true; List<CompletableFuture<Void>> futures = Lists.newArrayList(); if (failIfHasSubscriptions) { if (!subscriptions.isEmpty()) { isFenced = false; deleteFuture.completeExceptionally(new TopicBusyException("Topic has subscriptions")); return; } } else { subscriptions.forEach((s, sub) -> futures.add(sub.delete())); } FutureUtil.waitForAll(futures).whenComplete((v, ex) -> { if (ex != null) { log.error("[{}] Error deleting topic", topic, ex); isFenced = false; deleteFuture.completeExceptionally(ex); } else { ledger.asyncDelete(new AsyncCallbacks.DeleteLedgerCallback() { @Override public void deleteLedgerComplete(Object ctx) { brokerService.removeTopicFromCache(topic); log.info("[{}] Topic deleted", topic); deleteFuture.complete(null); } @Override public void deleteLedgerFailed(ManagedLedgerException exception, Object ctx) { isFenced = false; log.error("[{}] Error deleting topic", topic, exception); deleteFuture.completeExceptionally(new PersistenceException(exception)); } }, null); } }); } else { deleteFuture.completeExceptionally(new TopicBusyException( "Topic has " + USAGE_COUNT_UPDATER.get(this) + " connected producers/consumers")); } }).exceptionally(ex -> { deleteFuture.completeExceptionally( new TopicBusyException("Failed to close clients before deleting topic.")); return null; }); } finally { lock.writeLock().unlock(); } return deleteFuture; }
From source file:org.apache.pulsar.broker.service.persistent.PersistentTopic.java
/** * Close this topic - close all producers and subscriptions associated with this topic * * @return Completable future indicating completion of close operation */// ww w. j a v a 2 s . c o m @Override public CompletableFuture<Void> close() { CompletableFuture<Void> closeFuture = new CompletableFuture<>(); lock.writeLock().lock(); try { if (!isFenced) { isFenced = true; } else { log.warn("[{}] Topic is already being closed or deleted", topic); closeFuture.completeExceptionally(new TopicFencedException("Topic is already fenced")); return closeFuture; } } finally { lock.writeLock().unlock(); } List<CompletableFuture<Void>> futures = Lists.newArrayList(); replicators.forEach((cluster, replicator) -> futures.add(replicator.disconnect())); producers.forEach(producer -> futures.add(producer.disconnect())); subscriptions.forEach((s, sub) -> futures.add(sub.disconnect())); FutureUtil.waitForAll(futures).thenRun(() -> { // After having disconnected all producers/consumers, close the managed ledger ledger.asyncClose(new CloseCallback() { @Override public void closeComplete(Object ctx) { // Everything is now closed, remove the topic from map brokerService.removeTopicFromCache(topic); log.info("[{}] Topic closed", topic); closeFuture.complete(null); } @Override public void closeFailed(ManagedLedgerException exception, Object ctx) { log.error("[{}] Failed to close managed ledger, proceeding anyway.", topic, exception); brokerService.removeTopicFromCache(topic); closeFuture.complete(null); } }, null); if (dispatchRateLimiter.isPresent()) { dispatchRateLimiter.get().close(); } if (subscribeRateLimiter.isPresent()) { subscribeRateLimiter.get().close(); } }).exceptionally(exception -> { log.error("[{}] Error closing topic", topic, exception); isFenced = false; closeFuture.completeExceptionally(exception); return null; }); return closeFuture; }