/** * Returns the http rest path for use in the admin web service * Eg: * * * "persistent/my-tenant/my-namespace/my-topic" * * "non-persistent/my-tenant/my-namespace/my-topic" * * @return topic rest path */ public String getRestPath() { if (isV2()) { return String.format("%s/%s/%s/%s", domain, tenant, namespacePortion, getEncodedLocalName()); } else { return String.format("%s/%s/%s/%s/%s", domain, tenant, cluster, namespacePortion, getEncodedLocalName()); } }
/** * Returns the name of the persistence resource associated with the completeTopicName. * * @return the relative path to be used in persistence */ public String getPersistenceNamingEncoding() { // The convention is: domain://tenant/namespace/topic // We want to persist in the order: tenant/namespace/domain/topic // For legacy naming scheme, the convention is: domain://tenant/cluster/namespace/topic // We want to persist in the order: tenant/cluster/namespace/domain/topic if (isV2()) { return String.format("%s/%s/%s/%s", tenant, namespacePortion, domain, getEncodedLocalName()); } else { return String.format("%s/%s/%s/%s/%s", tenant, cluster, namespacePortion, domain, getEncodedLocalName()); } }
/** * Get a string suitable for completeTopicName lookup * <p> * Example: * <p> * persistent://tenant/cluster/namespace/completeTopicName -> persistent/tenant/cluster/namespace/completeTopicName * * @return */ public String getLookupName() { if (isV2()) { return String.format("%s/%s/%s/%s", domain, tenant, namespacePortion, getEncodedLocalName()); } else { return String.format("%s/%s/%s/%s/%s", domain, tenant, cluster, namespacePortion, getEncodedLocalName()); } }
public String getSchemaName() { return getTenant() + "/" + getNamespacePortion() + "/" + getEncodedLocalName(); }
/** * Get a string suitable for completeTopicName lookup * <p> * Example: * <p> * persistent://tenant/cluster/namespace/completeTopicName -> persistent/tenant/cluster/namespace/completeTopicName * * @return */ public String getLookupName() { if (isV2()) { return String.format("%s/%s/%s/%s", domain, tenant, namespacePortion, getEncodedLocalName()); } else { return String.format("%s/%s/%s/%s/%s", domain, tenant, cluster, namespacePortion, getEncodedLocalName()); } }
/** * Returns the name of the persistence resource associated with the completeTopicName. * * @return the relative path to be used in persistence */ public String getPersistenceNamingEncoding() { // The convention is: domain://tenant/namespace/topic // We want to persist in the order: tenant/namespace/domain/topic // For legacy naming scheme, the convention is: domain://tenant/cluster/namespace/topic // We want to persist in the order: tenant/cluster/namespace/domain/topic if (isV2()) { return String.format("%s/%s/%s/%s", tenant, namespacePortion, domain, getEncodedLocalName()); } else { return String.format("%s/%s/%s/%s/%s", tenant, cluster, namespacePortion, domain, getEncodedLocalName()); } }
/** * Returns the http rest path for use in the admin web service * Eg: * * * "persistent/my-tenant/my-namespace/my-topic" * * "non-persistent/my-tenant/my-namespace/my-topic" * * @return topic rest path */ public String getRestPath() { if (isV2()) { return String.format("%s/%s/%s/%s", domain, tenant, namespacePortion, getEncodedLocalName()); } else { return String.format("%s/%s/%s/%s/%s", domain, tenant, cluster, namespacePortion, getEncodedLocalName()); } }
private WebTarget schemaPath(TopicName topicName) { return target .path(topicName.getTenant()) .path(topicName.getNamespacePortion()) .path(topicName.getEncodedLocalName()) .path("schema"); } }
CompletableFuture<PartitionedTopicMetadata> getPartitionedTopicMetadata(DiscoveryService service, TopicName topicName, String role, AuthenticationDataSource authenticationData) { CompletableFuture<PartitionedTopicMetadata> metadataFuture = new CompletableFuture<>(); try { checkAuthorization(service, topicName, role, authenticationData); final String path = path(PARTITIONED_TOPIC_PATH_ZNODE, topicName.getNamespaceObject().toString(), "persistent", topicName.getEncodedLocalName()); // gets the number of partitions from the zk cache globalZkCache .getDataAsync(path, (key, content) -> getThreadLocal().readValue(content, PartitionedTopicMetadata.class)) .thenAccept(metadata -> { // if the partitioned topic is not found in zk, then the topic // is not partitioned if (metadata.isPresent()) { metadataFuture.complete(metadata.get()); } else { metadataFuture.complete(new PartitionedTopicMetadata()); } }).exceptionally(ex -> { metadataFuture.completeExceptionally(ex); return null; }); } catch (Exception e) { metadataFuture.completeExceptionally(e); } return metadataFuture; }
CompletableFuture<PartitionedTopicMetadata> getPartitionedTopicMetadata(ProxyService service, TopicName topicName, String role, AuthenticationDataSource authenticationData) { CompletableFuture<PartitionedTopicMetadata> metadataFuture = new CompletableFuture<>(); try { checkAuthorization(service, topicName, role, authenticationData); final String path = path(PARTITIONED_TOPIC_PATH_ZNODE, topicName.getNamespaceObject().toString(), "persistent", topicName.getEncodedLocalName()); // gets the number of partitions from the zk cache globalZkCache .getDataAsync(path, (key, content) -> getThreadLocal().readValue(content, PartitionedTopicMetadata.class)) .thenAccept(metadata -> { // if the partitioned topic is not found in zk, then the topic // is not partitioned if (metadata.isPresent()) { metadataFuture.complete(metadata.get()); } else { metadataFuture.complete(new PartitionedTopicMetadata()); } }).exceptionally(ex -> { metadataFuture.completeExceptionally(ex); return null; }); } catch (Exception e) { metadataFuture.completeExceptionally(e); } return metadataFuture; }
@PUT @Path("/{property}/{cluster}/{namespace}/{topic}/partitions") @ApiOperation(hidden = true, value = "Create a partitioned topic.", notes = "It needs to be called before creating a producer on a partitioned topic.") @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), @ApiResponse(code = 409, message = "Partitioned topic already exist") }) public void createPartitionedTopic(@PathParam("property") String property, @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, @PathParam("topic") @Encoded String encodedTopic, int numPartitions, @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { validateTopicName(property, cluster, namespace, encodedTopic); validateAdminAccessForTenant(topicName.getTenant()); if (numPartitions <= 1) { throw new RestException(Status.NOT_ACCEPTABLE, "Number of partitions should be more than 1"); } try { String path = path(PARTITIONED_TOPIC_PATH_ZNODE, namespaceName.toString(), domain(), topicName.getEncodedLocalName()); byte[] data = jsonMapper().writeValueAsBytes(new PartitionedTopicMetadata(numPartitions)); zkCreateOptimistic(path, data); // we wait for the data to be synced in all quorums and the observers Thread.sleep(PARTITIONED_TOPIC_WAIT_SYNC_TIME_MS); log.info("[{}] Successfully created partitioned topic {}", clientAppId(), topicName); } catch (KeeperException.NodeExistsException e) { log.warn("[{}] Failed to create already existing partitioned topic {}", clientAppId(), topicName); throw new RestException(Status.CONFLICT, "Partitioned topic already exist"); } catch (Exception e) { log.error("[{}] Failed to create partitioned topic {}", clientAppId(), topicName, e); throw new RestException(e); } }
public static String partitionedTopicPath(TopicName name) { return adminPath(PARTITIONED_TOPIC_PATH_ZNODE, name.getNamespace(), name.getDomain().value(), name.getEncodedLocalName()); }
@PUT @Path("/{tenant}/{namespace}/{topic}/partitions") @ApiOperation(value = "Create a partitioned topic.", notes = "It needs to be called before creating a producer on a partitioned topic.") @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), @ApiResponse(code = 409, message = "Partitioned topic already exists") }) public void createPartitionedTopic(@PathParam("tenant") String tenant, @PathParam("namespace") String namespace, @PathParam("topic") @Encoded String encodedTopic, int numPartitions, @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { validateTopicName(tenant, namespace, encodedTopic); validateAdminAccessForTenant(topicName.getTenant()); if (numPartitions <= 1) { throw new RestException(Status.NOT_ACCEPTABLE, "Number of partitions should be more than 1"); } try { String path = path(PARTITIONED_TOPIC_PATH_ZNODE, namespaceName.toString(), domain(), topicName.getEncodedLocalName()); byte[] data = jsonMapper().writeValueAsBytes(new PartitionedTopicMetadata(numPartitions)); zkCreateOptimistic(path, data); // we wait for the data to be synced in all quorums and the observers Thread.sleep(PARTITIONED_TOPIC_WAIT_SYNC_TIME_MS); log.info("[{}] Successfully created partitioned topic {}", clientAppId(), topicName); } catch (KeeperException.NodeExistsException e) { log.warn("[{}] Failed to create already existing partitioned topic {}", clientAppId(), topicName); throw new RestException(Status.CONFLICT, "Partitioned topic already exists"); } catch (Exception e) { log.error("[{}] Failed to create partitioned topic {}", clientAppId(), topicName, e); throw new RestException(e); } }
String partitionedTopicPath = path(AdminResource.PARTITIONED_TOPIC_PATH_ZNODE, topicName.getNamespace().toString(), topicName.getDomain().toString(), topicName.getEncodedLocalName()); boolean isPartitionedTopic = false; try {
topicName.getEncodedLocalName()); try { globalZk().delete(path, -1);
protected PartitionedTopicMetadata getPartitionedTopicMetadata(TopicName topicName, boolean authoritative) { validateClusterOwnership(topicName.getCluster()); // validates global-namespace contains local/peer cluster: if peer/local cluster present then lookup can // serve/redirect request else fail partitioned-metadata-request so, client fails while creating // producer/consumer validateGlobalNamespaceOwnership(topicName.getNamespaceObject()); try { checkConnect(topicName); } catch (WebApplicationException e) { validateAdminAccessForTenant(topicName.getTenant()); } catch (Exception e) { // unknown error marked as internal server error log.warn("Unexpected error while authorizing lookup. topic={}, role={}. Error: {}", topicName, clientAppId(), e.getMessage(), e); throw new RestException(e); } String path = path(PARTITIONED_TOPIC_PATH_ZNODE, namespaceName.toString(), domain(), topicName.getEncodedLocalName()); PartitionedTopicMetadata partitionMetadata = fetchPartitionedTopicMetadata(pulsar(), path); if (log.isDebugEnabled()) { log.debug("[{}] Total number of partitions for topic {} is {}", clientAppId(), topicName, partitionMetadata.partitions); } return partitionMetadata; }