@Override public CompletableFuture<Void> seekAsync(MessageId messageId) { return FutureUtil.failedFuture(new PulsarClientException("Seek operation not supported on topics consumer")); }
@Override public CompletableFuture<Reader<T>> createAsync() { if (conf.getTopicName() == null) { return FutureUtil .failedFuture(new IllegalArgumentException("Topic name must be set on the reader builder")); } if (conf.getStartMessageId() == null) { return FutureUtil .failedFuture(new IllegalArgumentException("Start message id must be set on the reader builder")); } return client.createReaderAsync(conf, schema); }
@Override public CompletableFuture<Message<T>> receiveAsync() { if (listener != null) { return FutureUtil.failedFuture(new PulsarClientException.InvalidConfigurationException( "Cannot use receive() when a listener has been set")); } switch (getState()) { case Ready: case Connecting: break; // Ok case Closing: case Closed: return FutureUtil.failedFuture(new PulsarClientException.AlreadyClosedException("Consumer already closed")); case Terminated: return FutureUtil.failedFuture(new PulsarClientException.AlreadyClosedException("Topic was terminated")); case Failed: case Uninitialized: return FutureUtil.failedFuture(new PulsarClientException.NotConnectedException()); } return internalReceiveAsync(); }
public CompletableFuture<PartitionedTopicMetadata> getPartitionedTopicMetadata(String topic) { CompletableFuture<PartitionedTopicMetadata> metadataFuture; try { TopicName topicName = TopicName.get(topic); metadataFuture = lookup.getPartitionedTopicMetadata(topicName); } catch (IllegalArgumentException e) { return FutureUtil.failedFuture(new PulsarClientException.InvalidConfigurationException(e.getMessage())); } return metadataFuture; }
@Override public CompletableFuture<Producer<T>> createAsync() { if (conf.getTopicName() == null) { return FutureUtil .failedFuture(new IllegalArgumentException("Topic name must be set on the producer builder")); } try { setMessageRoutingMode(); } catch(PulsarClientException pce) { return FutureUtil.failedFuture(pce); } return interceptorList == null || interceptorList.size() == 0 ? client.createProducerAsync(conf, schema, null) : client.createProducerAsync(conf, schema, new ProducerInterceptors<>(interceptorList)); }
@Override public CompletableFuture<Void> acknowledgeCumulativeAsync(Message<?> message) { try { return acknowledgeCumulativeAsync(message.getMessageId()); } catch (NullPointerException npe) { return FutureUtil.failedFuture(new PulsarClientException.InvalidMessageException(npe.getMessage())); } }
@Override public CompletableFuture<Void> acknowledgeAsync(Message<?> message) { try { return acknowledgeAsync(message.getMessageId()); } catch (NullPointerException npe) { return FutureUtil.failedFuture(new PulsarClientException.InvalidMessageException(npe.getMessage())); } }
public CompletableFuture<Void> subscribeAsync(String topicName) { if (!topicNameValid(topicName)) { return FutureUtil.failedFuture( new PulsarClientException.AlreadyClosedException("Topic name not valid")); } if (getState() == State.Closing || getState() == State.Closed) { return FutureUtil.failedFuture( new PulsarClientException.AlreadyClosedException("Topics Consumer was already closed")); } CompletableFuture<Void> subscribeResult = new CompletableFuture<>(); client.getPartitionedTopicMetadata(topicName) .thenAccept(metadata -> subscribeTopicPartitions(subscribeResult, topicName, metadata.partitions)) .exceptionally(ex1 -> { log.warn("[{}] Failed to get partitioned topic metadata: {}", topicName, ex1.getMessage()); subscribeResult.completeExceptionally(ex1); return null; }); return subscribeResult; }
private CompletableFuture<Void> subscribeAsync(String topicName, int numberPartitions) { if (!topicNameValid(topicName)) { return FutureUtil.failedFuture( new PulsarClientException.AlreadyClosedException("Topic name not valid")); } if (getState() == State.Closing || getState() == State.Closed) { return FutureUtil.failedFuture( new PulsarClientException.AlreadyClosedException("Topics Consumer was already closed")); } CompletableFuture<Void> subscribeResult = new CompletableFuture<>(); subscribeTopicPartitions(subscribeResult, topicName, numberPartitions); return subscribeResult; }
@Override CompletableFuture<MessageId> internalSendAsync(Message<T> message) { switch (getState()) { case Ready: case Connecting: break; // Ok case Closing: case Closed: return FutureUtil.failedFuture(new PulsarClientException.AlreadyClosedException("Producer already closed")); case Terminated: return FutureUtil.failedFuture(new PulsarClientException.TopicTerminatedException("Topic was terminated")); case Failed: case Uninitialized: return FutureUtil.failedFuture(new PulsarClientException.NotConnectedException()); } int partition = routerPolicy.choosePartition(message, topicMetadata); checkArgument(partition >= 0 && partition < topicMetadata.numPartitions(), "Illegal partition index chosen by the message routing policy: " + partition); return producers.get(partition).internalSendAsync(message); }
@Override public CompletableFuture<MessageId> sendAsync(T message) { try { return newMessage().value(message).sendAsync(); } catch (SchemaSerializationException e) { return FutureUtil.failedFuture(e); } }
@Override public CompletableFuture<Consumer<T>> subscribeAsync() { if (conf.getTopicNames().isEmpty() && conf.getTopicsPattern() == null) { return FutureUtil .failedFuture(new InvalidConfigurationException("Topic name must be set on the consumer builder")); } if (StringUtils.isBlank(conf.getSubscriptionName())) { return FutureUtil.failedFuture( new InvalidConfigurationException("Subscription name must be set on the consumer builder")); } return interceptorList == null || interceptorList.size() == 0 ? client.subscribeAsync(conf, schema, null) : client.subscribeAsync(conf, schema, new ConsumerInterceptors<>(interceptorList)); }
@Override public CompletableFuture<Void> acknowledgeCumulativeAsync(MessageId messageId) { if (!isCumulativeAcknowledgementAllowed(conf.getSubscriptionType())) { return FutureUtil.failedFuture(new PulsarClientException.InvalidConfigurationException( "Cannot use cumulative acks on a non-exclusive subscription")); } return doAcknowledge(messageId, AckType.Cumulative, Collections.emptyMap()); }
@Override public CompletableFuture<Void> unsubscribeAsync() { if (getState() == State.Closing || getState() == State.Closed) { return FutureUtil.failedFuture( new PulsarClientException.AlreadyClosedException("Topics Consumer was already closed")); } setState(State.Closing); CompletableFuture<Void> unsubscribeFuture = new CompletableFuture<>(); List<CompletableFuture<Void>> futureList = consumers.values().stream() .map(c -> c.unsubscribeAsync()).collect(Collectors.toList()); FutureUtil.waitForAll(futureList) .whenComplete((r, ex) -> { if (ex == null) { setState(State.Closed); unAckedMessageTracker.close(); unsubscribeFuture.complete(null); log.info("[{}] [{}] [{}] Unsubscribed Topics Consumer", topic, subscription, consumerName); } else { setState(State.Failed); unsubscribeFuture.completeExceptionally(ex); log.error("[{}] [{}] [{}] Could not unsubscribe Topics Consumer", topic, subscription, consumerName, ex.getCause()); } }); return unsubscribeFuture; }
/** * Read the schema information for a given topic. * * If the topic does not exist or it has no schema associated, it will return an empty response */ public CompletableFuture<Optional<SchemaInfo>> getSchema(String topic) { TopicName topicName; try { topicName = TopicName.get(topic); } catch (Throwable t) { return FutureUtil .failedFuture(new PulsarClientException.InvalidTopicNameException("Invalid topic name: " + topic)); } return lookup.getSchema(topicName); }
CompletableFuture<MessageId> getLastMessageIdAsync() { if (getState() == State.Closing || getState() == State.Closed) { return FutureUtil .failedFuture(new PulsarClientException.AlreadyClosedException("Consumer was already closed")); } AtomicLong opTimeoutMs = new AtomicLong(client.getConfiguration().getOperationTimeoutMs()); Backoff backoff = new Backoff(100, TimeUnit.MILLISECONDS, opTimeoutMs.get() * 2, TimeUnit.MILLISECONDS, 0 , TimeUnit.MILLISECONDS); CompletableFuture<MessageId> getLastMessageIdFuture = new CompletableFuture<>(); internalGetLastMessageIdAsync(backoff, opTimeoutMs, getLastMessageIdFuture); return getLastMessageIdFuture; }
@Override public CompletableFuture<Void> seekAsync(MessageId messageId) { if (getState() == State.Closing || getState() == State.Closed) { return FutureUtil .failedFuture(new PulsarClientException.AlreadyClosedException("Consumer was already closed")); } if (!isConnected()) { return FutureUtil.failedFuture(new PulsarClientException("Not connected to broker")); } final CompletableFuture<Void> seekFuture = new CompletableFuture<>(); long requestId = client.newRequestId(); MessageIdImpl msgId = (MessageIdImpl) messageId; ByteBuf seek = Commands.newSeek(consumerId, requestId, msgId.getLedgerId(), msgId.getEntryId()); ClientCnx cnx = cnx(); log.info("[{}][{}] Seek subscription to message id {}", topic, subscription, messageId); cnx.sendRequestWithId(seek, requestId).thenRun(() -> { log.info("[{}][{}] Successfully reset subscription to message id {}", topic, subscription, messageId); seekFuture.complete(null); }).exceptionally(e -> { log.error("[{}][{}] Failed to reset subscription: {}", topic, subscription, e.getCause().getMessage()); seekFuture.completeExceptionally(e.getCause()); return null; }); return seekFuture; }
public <T> CompletableFuture<Reader<T>> createReaderAsync(ReaderConfigurationData<T> conf, Schema<T> schema) { if (schema instanceof AutoConsumeSchema) { AutoConsumeSchema autoConsumeSchema = (AutoConsumeSchema) schema; return lookup.getSchema(TopicName.get(conf.getTopicName())) .thenCompose(schemaInfoOptional -> { if (schemaInfoOptional.isPresent() && schemaInfoOptional.get().getType() == SchemaType.AVRO) { GenericSchema genericSchema = GenericSchema.of(schemaInfoOptional.get()); log.info("Auto detected schema for topic {} : {}", conf.getTopicName(), new String(schemaInfoOptional.get().getSchema(), UTF_8)); autoConsumeSchema.setSchema(genericSchema); return doCreateReaderAsync(conf, schema); } else { return FutureUtil.failedFuture( new PulsarClientException.LookupException("Currently schema detection only works for topics with avro schemas")); } }); } else { return doCreateReaderAsync(conf, schema); } } <T> CompletableFuture<Reader<T>> doCreateReaderAsync(ReaderConfigurationData<T> conf, Schema<T> schema) {
private <T> CompletableFuture<Consumer<T>> singleTopicSubscribeAsync(ConsumerConfigurationData<T> conf, Schema<T> schema, ConsumerInterceptors<T> interceptors) { if (schema instanceof AutoConsumeSchema) { AutoConsumeSchema autoConsumeSchema = (AutoConsumeSchema) schema; return lookup.getSchema(TopicName.get(conf.getSingleTopic())) .thenCompose(schemaInfoOptional -> { if (schemaInfoOptional.isPresent() && schemaInfoOptional.get().getType() == SchemaType.AVRO) { GenericSchema genericSchema = GenericSchema.of(schemaInfoOptional.get()); log.info("Auto detected schema for topic {} : {}", conf.getSingleTopic(), new String(schemaInfoOptional.get().getSchema(), UTF_8)); autoConsumeSchema.setSchema(genericSchema); return doSingleTopicSubscribeAsync(conf, schema, interceptors); } else { return FutureUtil.failedFuture( new PulsarClientException.LookupException("Currently schema detection only works for topics with avro schemas")); } }); } else { return doSingleTopicSubscribeAsync(conf, schema, interceptors); } }
@Override protected CompletableFuture<Void> doAcknowledge(MessageId messageId, AckType ackType, Map<String,Long> properties) { checkArgument(messageId instanceof TopicMessageIdImpl); TopicMessageIdImpl topicMessageId = (TopicMessageIdImpl) messageId; if (getState() != State.Ready) { return FutureUtil.failedFuture(new PulsarClientException("Consumer already closed")); } if (ackType == AckType.Cumulative) { Consumer individualConsumer = consumers.get(topicMessageId.getTopicPartitionName()); if (individualConsumer != null) { MessageId innerId = topicMessageId.getInnerMessageId(); return individualConsumer.acknowledgeCumulativeAsync(innerId); } else { return FutureUtil.failedFuture(new PulsarClientException.NotConnectedException()); } } else { ConsumerImpl<T> consumer = consumers.get(topicMessageId.getTopicPartitionName()); MessageId innerId = topicMessageId.getInnerMessageId(); return consumer.doAcknowledge(innerId, ackType, properties) .thenRun(() -> unAckedMessageTracker.remove(topicMessageId)); } }