public String getEncodedLocalName() { return Codec.encode(localName); }
public PersistentMessageFinder(String topicName, ManagedCursor cursor) { this.topicName = topicName; this.cursor = cursor; this.subName = Codec.decode(cursor.getName()); }
@DELETE @Path("/{property}/{cluster}/{namespace}/{topic}/subscription/{subName}") @ApiOperation(hidden = true, value = "Delete a subscription.", 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 = 412, message = "Subscription has active consumers") }) public void deleteSubscription(@PathParam("property") String property, @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, @PathParam("topic") @Encoded String encodedTopic, @PathParam("subName") String encodedSubName, @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { validateTopicName(property, cluster, namespace, encodedTopic); internalDeleteSubscription(decode(encodedSubName), authoritative); }
public String getEncodedLocalName() { return Codec.encode(localName); }
@DELETE @Path("/{tenant}/{namespace}/{topic}/subscription/{subName}") @ApiOperation(value = "Delete a subscription.", 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 = 412, message = "Subscription has active consumers") }) public void deleteSubscription(@PathParam("tenant") String tenant, @PathParam("namespace") String namespace, @PathParam("topic") @Encoded String encodedTopic, @PathParam("subName") String encodedSubName, @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { validateTopicName(tenant, namespace, encodedTopic); internalDeleteSubscription(decode(encodedSubName), authoritative); }
private CompletableFuture<Subscription> getDurableSubscription(String subscriptionName, InitialPosition initialPosition) { CompletableFuture<Subscription> subscriptionFuture = new CompletableFuture<>(); ledger.asyncOpenCursor(Codec.encode(subscriptionName), initialPosition, new OpenCursorCallback() { @Override 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; }
@POST @Path("/{tenant}/{namespace}/{topic}/subscription/{subName}/expireMessages/{expireTimeInSeconds}") @ApiOperation(value = "Expire messages on a topic subscription.") @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), @ApiResponse(code = 404, message = "Topic or subscription does not exist") }) public void expireTopicMessages(@PathParam("tenant") String tenant, @PathParam("namespace") String namespace, @PathParam("topic") @Encoded String encodedTopic, @PathParam("subName") String encodedSubName, @PathParam("expireTimeInSeconds") int expireTimeInSeconds, @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { validateTopicName(tenant, namespace, encodedTopic); internalExpireMessages(decode(encodedSubName), expireTimeInSeconds, authoritative); }
CompletableFuture<Void> unsubscribeFuture = new CompletableFuture<>(); ledger.asyncDeleteCursor(Codec.encode(subscriptionName), new DeleteCursorCallback() { @Override public void deleteCursorComplete(Object ctx) {
@POST @Path("/{tenant}/{namespace}/{topic}/subscription/{subName}/resetcursor/{timestamp}") @ApiOperation(value = "Reset subscription to message position closest to absolute timestamp (in ms).", notes = "It fence cursor and disconnects all active consumers before reseting cursor.") @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), @ApiResponse(code = 404, message = "Topic/Subscription does not exist") }) public void resetCursor(@PathParam("tenant") String tenant, @PathParam("namespace") String namespace, @PathParam("topic") @Encoded String encodedTopic, @PathParam("subName") String encodedSubName, @PathParam("timestamp") long timestamp, @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { validateTopicName(tenant, namespace, encodedTopic); internalResetCursor(decode(encodedSubName), timestamp, authoritative); }
@Override public CompletableFuture<Void> expireMessagesAsync(String topic, String subName, long expireTimeInSeconds) { TopicName tn = validateTopic(topic); String encodedSubName = Codec.encode(subName); WebTarget path = topicPath(tn, "subscription", encodedSubName, "expireMessages", String.valueOf(expireTimeInSeconds)); return asyncPostRequest(path, Entity.entity("", MediaType.APPLICATION_JSON)); }
@GET @Path("/{property}/{cluster}/{namespace}/{topic}/subscription/{subName}/position/{messagePosition}") @ApiOperation(hidden = true, value = "Peek nth message on a topic subscription.") @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), @ApiResponse(code = 404, message = "Topic, subscription or the message position does not exist") }) public Response peekNthMessage(@PathParam("property") String property, @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, @PathParam("topic") @Encoded String encodedTopic, @PathParam("subName") String encodedSubName, @PathParam("messagePosition") int messagePosition, @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { validateTopicName(property, cluster, namespace, encodedTopic); return internalPeekNthMessage(decode(encodedSubName), messagePosition, authoritative); }
@Override public CompletableFuture<Void> resetCursorAsync(String topic, String subName, long timestamp) { TopicName tn = validateTopic(topic); String encodedSubName = Codec.encode(subName); WebTarget path = topicPath(tn, "subscription", encodedSubName, "resetcursor", String.valueOf(timestamp)); return asyncPostRequest(path, Entity.entity("", MediaType.APPLICATION_JSON)); }
@PUT @Path("/{tenant}/{namespace}/{topic}/subscription/{subscriptionName}") @ApiOperation(value = "Reset subscription to message position closest to given position.", notes = "Creates a subscription on the topic at the specified message id") @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), @ApiResponse(code = 404, message = "Topic/Subscription does not exist"), @ApiResponse(code = 405, message = "Not supported for partitioned topics") }) public void createSubscription(@PathParam("tenant") String tenant, @PathParam("namespace") String namespace, @PathParam("topic") @Encoded String topic, @PathParam("subscriptionName") String encodedSubName, @QueryParam("authoritative") @DefaultValue("false") boolean authoritative, MessageIdImpl messageId) { validateTopicName(tenant, namespace, topic); internalCreateSubscription(decode(encodedSubName), messageId, authoritative); }
@Override public CompletableFuture<Void> skipMessagesAsync(String topic, String subName, long numMessages) { TopicName tn = validateTopic(topic); String encodedSubName = Codec.encode(subName); WebTarget path = topicPath(tn, "subscription", encodedSubName, "skip", String.valueOf(numMessages)); return asyncPostRequest(path, Entity.entity("", MediaType.APPLICATION_JSON)); }
@POST @Path("/{tenant}/{namespace}/{topic}/subscription/{subName}/skip/{numMessages}") @ApiOperation(value = "Skip messages on a topic subscription.") @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), @ApiResponse(code = 404, message = "Topic or subscription does not exist") }) public void skipMessages(@PathParam("tenant") String tenant, @PathParam("namespace") String namespace, @PathParam("topic") @Encoded String encodedTopic, @PathParam("subName") String encodedSubName, @PathParam("numMessages") int numMessages, @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { validateTopicName(tenant, namespace, encodedTopic); internalSkipMessages(decode(encodedSubName), numMessages, authoritative); }
@Override public CompletableFuture<Void> skipAllMessagesAsync(String topic, String subName) { TopicName tn = validateTopic(topic); String encodedSubName = Codec.encode(subName); WebTarget path = topicPath(tn, "subscription", encodedSubName, "skip_all"); return asyncPostRequest(path, Entity.entity("", MediaType.APPLICATION_JSON)); }
@GET @Path("/{tenant}/{namespace}/{topic}/subscription/{subName}/position/{messagePosition}") @ApiOperation(value = "Peek nth message on a topic subscription.") @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), @ApiResponse(code = 404, message = "Topic, subscription or the message position does not exist") }) public Response peekNthMessage(@PathParam("tenant") String tenant, @PathParam("namespace") String namespace, @PathParam("topic") @Encoded String encodedTopic, @PathParam("subName") String encodedSubName, @PathParam("messagePosition") int messagePosition, @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { validateTopicName(tenant, namespace, encodedTopic); return internalPeekNthMessage(decode(encodedSubName), messagePosition, authoritative); }
@Override public CompletableFuture<Void> resetCursorAsync(String topic, String subName, MessageId messageId) { TopicName tn = validateTopic(topic); String encodedSubName = Codec.encode(subName); final WebTarget path = topicPath(tn, "subscription", encodedSubName, "resetcursor"); return asyncPostRequest(path, Entity.entity(messageId, MediaType.APPLICATION_JSON)); }
@POST @Path("/{property}/{cluster}/{namespace}/{topic}/subscription/{subName}/skip/{numMessages}") @ApiOperation(hidden = true, value = "Skip messages on a topic subscription.") @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), @ApiResponse(code = 404, message = "Topic or subscription does not exist") }) public void skipMessages(@PathParam("property") String property, @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, @PathParam("topic") @Encoded String encodedTopic, @PathParam("subName") String encodedSubName, @PathParam("numMessages") int numMessages, @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { validateTopicName(property, cluster, namespace, encodedTopic); internalSkipMessages(decode(encodedSubName), numMessages, authoritative); }
@Override public void resetCursor(String topic, String subName, long timestamp) throws PulsarAdminException { try { TopicName tn = validateTopic(topic); String encodedSubName = Codec.encode(subName); WebTarget path = topicPath(tn, "subscription", encodedSubName, "resetcursor", String.valueOf(timestamp)); request(path).post(Entity.entity("", MediaType.APPLICATION_JSON), ErrorData.class); } catch (Exception e) { throw getApiException(e); } }