Search in sources :

Example 1 with SubscriptionInvalidCursorPosition

use of com.yahoo.pulsar.broker.service.BrokerServiceException.SubscriptionInvalidCursorPosition in project pulsar by yahoo.

the class PersistentTopics method resetCursor.

@POST
@Path("/{property}/{cluster}/{namespace}/{destination}/subscription/{subName}/resetcursor/{timestamp}")
@ApiOperation(value = "Reset subscription to message position closest to absolute timestamp (in ms).", notes = "There should not be any active consumers on the subscription.")
@ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), @ApiResponse(code = 404, message = "Topic does not exist"), @ApiResponse(code = 405, message = "Not supported for global topics"), @ApiResponse(code = 412, message = "Subscription has active consumers") })
public void resetCursor(@PathParam("property") String property, @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, @PathParam("destination") @Encoded String destination, @PathParam("subName") String subName, @PathParam("timestamp") long timestamp, @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) {
    destination = decode(destination);
    DestinationName dn = DestinationName.get(domain(), property, cluster, namespace, destination);
    PartitionedTopicMetadata partitionMetadata = getPartitionedTopicMetadata(property, cluster, namespace, destination, authoritative);
    if (partitionMetadata.partitions > 0) {
        int numParts = partitionMetadata.partitions;
        int numPartException = 0;
        Exception partitionException = null;
        try {
            for (int i = 0; i < numParts; i++) {
                pulsar().getAdminClient().persistentTopics().resetCursor(dn.getPartition(i).toString(), subName, timestamp);
            }
        } catch (PreconditionFailedException pfe) {
            // throw the last exception if all partitions get this error
            // any other exception on partition is reported back to user
            ++numPartException;
            partitionException = pfe;
        } catch (Exception e) {
            log.warn("[{}] [{}] Failed to reset cursor on subscription {} to time {}", clientAppId(), dn, subName, timestamp, e);
            throw new RestException(e);
        }
        // report an error to user if unable to reset for all partitions
        if (numPartException == numParts) {
            log.warn("[{}] [{}] Failed to reset cursor on subscription {} to time {}", clientAppId(), dn, subName, timestamp, partitionException);
            throw new RestException(Status.PRECONDITION_FAILED, partitionException.getMessage());
        } else if (numPartException > 0 && log.isDebugEnabled()) {
            log.debug("[{}][{}] partial errors for reset cursor on subscription {} to time {} - ", clientAppId(), destination, subName, timestamp, partitionException);
        }
    } else {
        validateAdminOperationOnDestination(dn, authoritative);
        log.info("[{}][{}] received reset cursor on subscription {} to time {}", clientAppId(), destination, subName, timestamp);
        PersistentTopic topic = getTopicReference(dn);
        try {
            PersistentSubscription sub = topic.getPersistentSubscription(subName);
            checkNotNull(sub);
            sub.resetCursor(timestamp).get();
            log.info("[{}][{}] reset cursor on subscription {} to time {}", clientAppId(), dn, subName, timestamp);
        } catch (Exception e) {
            Throwable t = e.getCause();
            log.warn("[{}] [{}] Failed to reset cursor on subscription {} to time {}", clientAppId(), dn, subName, timestamp, e);
            if (e instanceof NullPointerException) {
                throw new RestException(Status.NOT_FOUND, "Subscription not found");
            } else if (e instanceof NotAllowedException) {
                throw new RestException(Status.METHOD_NOT_ALLOWED, e.getMessage());
            } else if (t instanceof SubscriptionBusyException) {
                throw new RestException(Status.PRECONDITION_FAILED, "Subscription has active connected consumers");
            } else if (t instanceof SubscriptionInvalidCursorPosition) {
                throw new RestException(Status.PRECONDITION_FAILED, "Unable to find position for timestamp specified -" + t.getMessage());
            } else {
                throw new RestException(e);
            }
        }
    }
}
Also used : NotAllowedException(com.yahoo.pulsar.broker.service.BrokerServiceException.NotAllowedException) RestException(com.yahoo.pulsar.broker.web.RestException) PersistentSubscription(com.yahoo.pulsar.broker.service.persistent.PersistentSubscription) RestException(com.yahoo.pulsar.broker.web.RestException) TopicBusyException(com.yahoo.pulsar.broker.service.BrokerServiceException.TopicBusyException) WebApplicationException(javax.ws.rs.WebApplicationException) PulsarClientException(com.yahoo.pulsar.client.api.PulsarClientException) PreconditionFailedException(com.yahoo.pulsar.client.admin.PulsarAdminException.PreconditionFailedException) SubscriptionBusyException(com.yahoo.pulsar.broker.service.BrokerServiceException.SubscriptionBusyException) NotFoundException(com.yahoo.pulsar.client.admin.PulsarAdminException.NotFoundException) NotAllowedException(com.yahoo.pulsar.broker.service.BrokerServiceException.NotAllowedException) KeeperException(org.apache.zookeeper.KeeperException) IOException(java.io.IOException) SubscriptionInvalidCursorPosition(com.yahoo.pulsar.broker.service.BrokerServiceException.SubscriptionInvalidCursorPosition) PersistentTopic(com.yahoo.pulsar.broker.service.persistent.PersistentTopic) DestinationName(com.yahoo.pulsar.common.naming.DestinationName) PreconditionFailedException(com.yahoo.pulsar.client.admin.PulsarAdminException.PreconditionFailedException) SubscriptionBusyException(com.yahoo.pulsar.broker.service.BrokerServiceException.SubscriptionBusyException) PartitionedTopicMetadata(com.yahoo.pulsar.common.partition.PartitionedTopicMetadata) Path(javax.ws.rs.Path) POST(javax.ws.rs.POST) ApiOperation(io.swagger.annotations.ApiOperation) ApiResponses(io.swagger.annotations.ApiResponses)

Example 2 with SubscriptionInvalidCursorPosition

use of com.yahoo.pulsar.broker.service.BrokerServiceException.SubscriptionInvalidCursorPosition in project pulsar by yahoo.

the class PersistentSubscription method resetCursor.

@Override
public CompletableFuture<Void> resetCursor(long timestamp) {
    CompletableFuture<Void> future = new CompletableFuture<>();
    PersistentMessageFinder persistentMessageFinder = new PersistentMessageFinder(topicName, cursor);
    if (log.isDebugEnabled()) {
        log.debug("[{}][{}] Resetting subscription to timestamp {}", topicName, subName, timestamp);
    }
    persistentMessageFinder.findMessages(timestamp, new AsyncCallbacks.FindEntryCallback() {

        @Override
        public void findEntryComplete(Position position, Object ctx) {
            final Position finalPosition;
            if (position == null) {
                // this should not happen ideally unless a reset is requested for a time
                // that spans beyond the retention limits (time/size)
                finalPosition = cursor.getFirstPosition();
                if (finalPosition == null) {
                    log.warn("[{}][{}] Unable to find position for timestamp {}. Unable to reset cursor to first position", topicName, subName, timestamp);
                    future.completeExceptionally(new SubscriptionInvalidCursorPosition("Unable to find position for specified timestamp"));
                    return;
                }
                log.info("[{}][{}] Unable to find position for timestamp {}. Resetting cursor to first position {} in ledger", topicName, subName, timestamp, finalPosition);
            } else {
                finalPosition = position;
            }
            if (!IS_FENCED_UPDATER.compareAndSet(PersistentSubscription.this, FALSE, TRUE)) {
                future.completeExceptionally(new SubscriptionBusyException("Failed to fence subscription"));
                return;
            }
            final CompletableFuture<Void> disconnectFuture;
            if (dispatcher != null && dispatcher.isConsumerConnected()) {
                disconnectFuture = dispatcher.disconnectAllConsumers();
            } else {
                disconnectFuture = CompletableFuture.completedFuture(null);
            }
            disconnectFuture.whenComplete((aVoid, throwable) -> {
                if (throwable != null) {
                    log.error("[{}][{}] Failed to disconnect consumer from subscription", topicName, subName, throwable);
                    IS_FENCED_UPDATER.set(PersistentSubscription.this, FALSE);
                    future.completeExceptionally(new SubscriptionBusyException("Failed to disconnect consumers from subscription"));
                    return;
                }
                log.info("[{}][{}] Successfully disconnected consumers from subscription, proceeding with cursor reset", topicName, subName);
                try {
                    cursor.asyncResetCursor(finalPosition, new AsyncCallbacks.ResetCursorCallback() {

                        @Override
                        public void resetComplete(Object ctx) {
                            if (log.isDebugEnabled()) {
                                log.debug("[{}][{}] Successfully reset subscription to timestamp {}", topicName, subName, timestamp);
                            }
                            IS_FENCED_UPDATER.set(PersistentSubscription.this, FALSE);
                            future.complete(null);
                        }

                        @Override
                        public void resetFailed(ManagedLedgerException exception, Object ctx) {
                            log.error("[{}][{}] Failed to reset subscription to timestamp {}", topicName, subName, timestamp, exception);
                            IS_FENCED_UPDATER.set(PersistentSubscription.this, FALSE);
                            // or should we just ask user to retry one more time?
                            if (exception instanceof InvalidCursorPositionException) {
                                future.completeExceptionally(new SubscriptionInvalidCursorPosition(exception.getMessage()));
                            } else if (exception instanceof ConcurrentFindCursorPositionException) {
                                future.completeExceptionally(new SubscriptionBusyException(exception.getMessage()));
                            } else {
                                future.completeExceptionally(new BrokerServiceException(exception));
                            }
                        }
                    });
                } catch (Exception e) {
                    log.error("[{}][{}] Error while resetting cursor", topicName, subName, e);
                    IS_FENCED_UPDATER.set(PersistentSubscription.this, FALSE);
                    future.completeExceptionally(new BrokerServiceException(e));
                }
            });
        }

        @Override
        public void findEntryFailed(ManagedLedgerException exception, Object ctx) {
            // todo - what can go wrong here that needs to be retried?
            if (exception instanceof ConcurrentFindCursorPositionException) {
                future.completeExceptionally(new SubscriptionBusyException(exception.getMessage()));
            } else {
                future.completeExceptionally(new BrokerServiceException(exception));
            }
        }
    });
    return future;
}
Also used : SubType(com.yahoo.pulsar.common.api.proto.PulsarApi.CommandSubscribe.SubType) PersistentSubscriptionStats(com.yahoo.pulsar.common.policies.data.PersistentSubscriptionStats) AtomicIntegerFieldUpdater(java.util.concurrent.atomic.AtomicIntegerFieldUpdater) ConsumerStats(com.yahoo.pulsar.common.policies.data.ConsumerStats) CloseCallback(org.apache.bookkeeper.mledger.AsyncCallbacks.CloseCallback) Entry(org.apache.bookkeeper.mledger.Entry) LoggerFactory(org.slf4j.LoggerFactory) CompletableFuture(java.util.concurrent.CompletableFuture) ReadEntryCallback(org.apache.bookkeeper.mledger.AsyncCallbacks.ReadEntryCallback) SubscriptionBusyException(com.yahoo.pulsar.broker.service.BrokerServiceException.SubscriptionBusyException) DeleteCallback(org.apache.bookkeeper.mledger.AsyncCallbacks.DeleteCallback) SubscriptionFencedException(com.yahoo.pulsar.broker.service.BrokerServiceException.SubscriptionFencedException) Dispatcher(com.yahoo.pulsar.broker.service.Dispatcher) ClearBacklogCallback(org.apache.bookkeeper.mledger.AsyncCallbacks.ClearBacklogCallback) ManagedCursor(org.apache.bookkeeper.mledger.ManagedCursor) Codec(com.yahoo.pulsar.common.util.Codec) Objects(com.google.common.base.Objects) PositionImpl(org.apache.bookkeeper.mledger.impl.PositionImpl) DestinationName(com.yahoo.pulsar.common.naming.DestinationName) Logger(org.slf4j.Logger) BrokerServiceException(com.yahoo.pulsar.broker.service.BrokerServiceException) PersistenceException(com.yahoo.pulsar.broker.service.BrokerServiceException.PersistenceException) ServerMetadataException(com.yahoo.pulsar.broker.service.BrokerServiceException.ServerMetadataException) CopyOnWriteArrayList(com.yahoo.pulsar.utils.CopyOnWriteArrayList) ConcurrentFindCursorPositionException(org.apache.bookkeeper.mledger.ManagedLedgerException.ConcurrentFindCursorPositionException) Position(org.apache.bookkeeper.mledger.Position) IndividualDeletedEntries(org.apache.bookkeeper.mledger.ManagedCursor.IndividualDeletedEntries) ManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException) SubscriptionInvalidCursorPosition(com.yahoo.pulsar.broker.service.BrokerServiceException.SubscriptionInvalidCursorPosition) Consumer(com.yahoo.pulsar.broker.service.Consumer) List(java.util.List) AckType(com.yahoo.pulsar.common.api.proto.PulsarApi.CommandAck.AckType) MarkDeleteCallback(org.apache.bookkeeper.mledger.AsyncCallbacks.MarkDeleteCallback) InvalidCursorPositionException(org.apache.bookkeeper.mledger.ManagedLedgerException.InvalidCursorPositionException) Subscription(com.yahoo.pulsar.broker.service.Subscription) AsyncCallbacks(org.apache.bookkeeper.mledger.AsyncCallbacks) Position(org.apache.bookkeeper.mledger.Position) SubscriptionInvalidCursorPosition(com.yahoo.pulsar.broker.service.BrokerServiceException.SubscriptionInvalidCursorPosition) BrokerServiceException(com.yahoo.pulsar.broker.service.BrokerServiceException) InvalidCursorPositionException(org.apache.bookkeeper.mledger.ManagedLedgerException.InvalidCursorPositionException) ConcurrentFindCursorPositionException(org.apache.bookkeeper.mledger.ManagedLedgerException.ConcurrentFindCursorPositionException) SubscriptionBusyException(com.yahoo.pulsar.broker.service.BrokerServiceException.SubscriptionBusyException) SubscriptionFencedException(com.yahoo.pulsar.broker.service.BrokerServiceException.SubscriptionFencedException) BrokerServiceException(com.yahoo.pulsar.broker.service.BrokerServiceException) PersistenceException(com.yahoo.pulsar.broker.service.BrokerServiceException.PersistenceException) ServerMetadataException(com.yahoo.pulsar.broker.service.BrokerServiceException.ServerMetadataException) ConcurrentFindCursorPositionException(org.apache.bookkeeper.mledger.ManagedLedgerException.ConcurrentFindCursorPositionException) ManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException) InvalidCursorPositionException(org.apache.bookkeeper.mledger.ManagedLedgerException.InvalidCursorPositionException) SubscriptionInvalidCursorPosition(com.yahoo.pulsar.broker.service.BrokerServiceException.SubscriptionInvalidCursorPosition) CompletableFuture(java.util.concurrent.CompletableFuture) ManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException) AsyncCallbacks(org.apache.bookkeeper.mledger.AsyncCallbacks) SubscriptionBusyException(com.yahoo.pulsar.broker.service.BrokerServiceException.SubscriptionBusyException)

Aggregations

SubscriptionBusyException (com.yahoo.pulsar.broker.service.BrokerServiceException.SubscriptionBusyException)2 SubscriptionInvalidCursorPosition (com.yahoo.pulsar.broker.service.BrokerServiceException.SubscriptionInvalidCursorPosition)2 DestinationName (com.yahoo.pulsar.common.naming.DestinationName)2 Objects (com.google.common.base.Objects)1 BrokerServiceException (com.yahoo.pulsar.broker.service.BrokerServiceException)1 NotAllowedException (com.yahoo.pulsar.broker.service.BrokerServiceException.NotAllowedException)1 PersistenceException (com.yahoo.pulsar.broker.service.BrokerServiceException.PersistenceException)1 ServerMetadataException (com.yahoo.pulsar.broker.service.BrokerServiceException.ServerMetadataException)1 SubscriptionFencedException (com.yahoo.pulsar.broker.service.BrokerServiceException.SubscriptionFencedException)1 TopicBusyException (com.yahoo.pulsar.broker.service.BrokerServiceException.TopicBusyException)1 Consumer (com.yahoo.pulsar.broker.service.Consumer)1 Dispatcher (com.yahoo.pulsar.broker.service.Dispatcher)1 Subscription (com.yahoo.pulsar.broker.service.Subscription)1 PersistentSubscription (com.yahoo.pulsar.broker.service.persistent.PersistentSubscription)1 PersistentTopic (com.yahoo.pulsar.broker.service.persistent.PersistentTopic)1 RestException (com.yahoo.pulsar.broker.web.RestException)1 NotFoundException (com.yahoo.pulsar.client.admin.PulsarAdminException.NotFoundException)1 PreconditionFailedException (com.yahoo.pulsar.client.admin.PulsarAdminException.PreconditionFailedException)1 PulsarClientException (com.yahoo.pulsar.client.api.PulsarClientException)1 AckType (com.yahoo.pulsar.common.api.proto.PulsarApi.CommandAck.AckType)1