use of org.apache.pulsar.client.api.PulsarClientException in project incubator-pulsar by apache.
the class ProducerImpl method connectionOpened.
@Override
public void connectionOpened(final ClientCnx cnx) {
// we set the cnx reference before registering the producer on the cnx, so if the cnx breaks before creating the
// producer, it will try to grab a new cnx
connectionHandler.setClientCnx(cnx);
cnx.registerProducer(producerId, this);
log.info("[{}] [{}] Creating producer on cnx {}", topic, producerName, cnx.ctx().channel());
long requestId = client.newRequestId();
cnx.sendRequestWithId(Commands.newProducer(topic, producerId, requestId, producerName, conf.isEncryptionEnabled(), metadata), requestId).thenAccept(pair -> {
String producerName = pair.getLeft();
long lastSequenceId = pair.getRight();
// set the cnx pointer so that new messages will be sent immediately
synchronized (ProducerImpl.this) {
if (getState() == State.Closing || getState() == State.Closed) {
// Producer was closed while reconnecting, close the connection to make sure the broker
// drops the producer on its side
cnx.removeProducer(producerId);
cnx.channel().close();
return;
}
resetBackoff();
log.info("[{}] [{}] Created producer on cnx {}", topic, producerName, cnx.ctx().channel());
connectionId = cnx.ctx().channel().toString();
connectedSince = DateFormatter.now();
if (this.producerName == null) {
this.producerName = producerName;
}
if (this.lastSequenceIdPublished == -1 && conf.getInitialSequenceId() == null) {
this.lastSequenceIdPublished = lastSequenceId;
this.msgIdGenerator = lastSequenceId + 1;
}
if (!producerCreatedFuture.isDone() && isBatchMessagingEnabled()) {
// schedule the first batch message task
client.timer().newTimeout(batchMessageAndSendTask, conf.getBatchingMaxPublishDelayMicros(), TimeUnit.MICROSECONDS);
}
resendMessages(cnx);
}
}).exceptionally((e) -> {
Throwable cause = e.getCause();
cnx.removeProducer(producerId);
if (getState() == State.Closing || getState() == State.Closed) {
// Producer was closed while reconnecting, close the connection to make sure the broker
// drops the producer on its side
cnx.channel().close();
return null;
}
log.error("[{}] [{}] Failed to create producer: {}", topic, producerName, cause.getMessage());
if (cause instanceof PulsarClientException.ProducerBlockedQuotaExceededException) {
synchronized (this) {
log.warn("[{}] [{}] Topic backlog quota exceeded. Throwing Exception on producer.", topic, producerName);
if (log.isDebugEnabled()) {
log.debug("[{}] [{}] Pending messages: {}", topic, producerName, pendingMessages.size());
}
PulsarClientException bqe = new PulsarClientException.ProducerBlockedQuotaExceededException("Could not send pending messages as backlog exceeded");
failPendingMessages(cnx(), bqe);
}
} else if (cause instanceof PulsarClientException.ProducerBlockedQuotaExceededError) {
log.warn("[{}] [{}] Producer is blocked on creation because backlog exceeded on topic.", producerName, topic);
}
if (cause instanceof PulsarClientException.TopicTerminatedException) {
setState(State.Terminated);
failPendingMessages(cnx(), (PulsarClientException) cause);
producerCreatedFuture.completeExceptionally(cause);
client.cleanupProducer(this);
} else if (//
producerCreatedFuture.isDone() || (cause instanceof PulsarClientException && connectionHandler.isRetriableError((PulsarClientException) cause) && System.currentTimeMillis() < createProducerTimeout)) {
// Either we had already created the producer once (producerCreatedFuture.isDone()) or we are
// still within the initial timeout budget and we are dealing with a retriable error
reconnectLater(cause);
} else {
setState(State.Failed);
producerCreatedFuture.completeExceptionally(cause);
client.cleanupProducer(this);
}
return null;
});
}
use of org.apache.pulsar.client.api.PulsarClientException in project incubator-pulsar by apache.
the class ProducerImpl method batchMessageAndSend.
// must acquire semaphore before enqueuing
private void batchMessageAndSend() {
if (log.isDebugEnabled()) {
log.debug("[{}] [{}] Batching the messages from the batch container with {} messages", topic, producerName, batchMessageContainer.numMessagesInBatch);
}
OpSendMsg op = null;
int numMessagesInBatch = 0;
try {
if (!batchMessageContainer.isEmpty()) {
numMessagesInBatch = batchMessageContainer.numMessagesInBatch;
ByteBuf compressedPayload = batchMessageContainer.getCompressedBatchMetadataAndPayload();
long sequenceId = batchMessageContainer.sequenceId;
ByteBuf encryptedPayload = encryptMessage(batchMessageContainer.messageMetadata, compressedPayload);
ByteBufPair cmd = sendMessage(producerId, sequenceId, batchMessageContainer.numMessagesInBatch, batchMessageContainer.setBatchAndBuild(), encryptedPayload);
op = OpSendMsg.create(batchMessageContainer.messages, cmd, sequenceId, batchMessageContainer.firstCallback);
op.setNumMessagesInBatch(batchMessageContainer.numMessagesInBatch);
op.setBatchSizeByte(batchMessageContainer.currentBatchSizeBytes);
batchMessageContainer.clear();
pendingMessages.put(op);
if (isConnected()) {
// If we do have a connection, the message is sent immediately, otherwise we'll try again once a new
// connection is established
cmd.retain();
cnx().ctx().channel().eventLoop().execute(WriteInEventLoopCallback.create(this, cnx(), op));
stats.updateNumMsgsSent(numMessagesInBatch, op.batchSizeByte);
} else {
if (log.isDebugEnabled()) {
log.debug("[{}] [{}] Connection is not ready -- sequenceId {}", topic, producerName, sequenceId);
}
}
}
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
semaphore.release(numMessagesInBatch);
if (op != null) {
op.callback.sendComplete(new PulsarClientException(ie));
}
} catch (PulsarClientException e) {
Thread.currentThread().interrupt();
semaphore.release(numMessagesInBatch);
if (op != null) {
op.callback.sendComplete(e);
}
} catch (Throwable t) {
semaphore.release(numMessagesInBatch);
log.warn("[{}] [{}] error while closing out batch -- {}", topic, producerName, t);
if (op != null) {
op.callback.sendComplete(new PulsarClientException(t));
}
}
}
use of org.apache.pulsar.client.api.PulsarClientException in project incubator-pulsar by apache.
the class MessageCrypto method encrypt.
/*
* Encrypt the payload using the data key and update message metadata with the keyname & encrypted data key
*
* @param encKeys One or more public keys to encrypt data key
*
* @param msgMetadata Message Metadata
*
* @param payload Message which needs to be encrypted
*
* @return encryptedData if success
*/
public synchronized ByteBuf encrypt(Set<String> encKeys, CryptoKeyReader keyReader, MessageMetadata.Builder msgMetadata, ByteBuf payload) throws PulsarClientException {
if (encKeys.isEmpty()) {
return payload;
}
// Update message metadata with encrypted data key
for (String keyName : encKeys) {
if (encryptedDataKeyMap.get(keyName) == null) {
// Attempt to load the key. This will allow us to load keys as soon as
// a new key is added to producer config
addPublicKeyCipher(keyName, keyReader);
}
EncryptionKeyInfo keyInfo = encryptedDataKeyMap.get(keyName);
if (keyInfo != null) {
if (keyInfo.getMetadata() != null && !keyInfo.getMetadata().isEmpty()) {
List<KeyValue> kvList = new ArrayList<KeyValue>();
keyInfo.getMetadata().forEach((key, value) -> {
kvList.add(KeyValue.newBuilder().setKey(key).setValue(value).build());
});
msgMetadata.addEncryptionKeys(EncryptionKeys.newBuilder().setKey(keyName).setValue(ByteString.copyFrom(keyInfo.getKey())).addAllMetadata(kvList).build());
} else {
msgMetadata.addEncryptionKeys(EncryptionKeys.newBuilder().setKey(keyName).setValue(ByteString.copyFrom(keyInfo.getKey())).build());
}
} else {
// We should never reach here.
log.error("{} Failed to find encrypted Data key for key {}.", logCtx, keyName);
}
}
// Create gcm param
// TODO: Replace random with counter and periodic refreshing based on timer/counter value
secureRandom.nextBytes(iv);
GCMParameterSpec gcmParam = new GCMParameterSpec(tagLen, iv);
// Update message metadata with encryption param
msgMetadata.setEncryptionParam(ByteString.copyFrom(iv));
ByteBuf targetBuf = null;
try {
// Encrypt the data
cipher.init(Cipher.ENCRYPT_MODE, dataKey, gcmParam);
ByteBuffer sourceNioBuf = payload.nioBuffer(payload.readerIndex(), payload.readableBytes());
int maxLength = cipher.getOutputSize(payload.readableBytes());
targetBuf = PooledByteBufAllocator.DEFAULT.buffer(maxLength, maxLength);
ByteBuffer targetNioBuf = targetBuf.nioBuffer(0, maxLength);
int bytesStored = cipher.doFinal(sourceNioBuf, targetNioBuf);
targetBuf.writerIndex(bytesStored);
} catch (IllegalBlockSizeException | BadPaddingException | InvalidKeyException | InvalidAlgorithmParameterException | ShortBufferException e) {
targetBuf.release();
log.error("{} Failed to encrypt message. {}", logCtx, e);
throw new PulsarClientException.CryptoException(e.getMessage());
}
payload.release();
return targetBuf;
}
use of org.apache.pulsar.client.api.PulsarClientException in project incubator-pulsar by apache.
the class TopicsConsumerImpl method doAcknowledge.
@Override
protected CompletableFuture<Void> doAcknowledge(MessageId messageId, AckType ackType, Map<String, Long> properties) {
checkArgument(messageId instanceof TopicMessageIdImpl);
TopicMessageIdImpl messageId1 = (TopicMessageIdImpl) messageId;
if (getState() != State.Ready) {
return FutureUtil.failedFuture(new PulsarClientException("Consumer already closed"));
}
if (ackType == AckType.Cumulative) {
return FutureUtil.failedFuture(new PulsarClientException.NotSupportedException("Cumulative acknowledge not supported for topics consumer"));
} else {
ConsumerImpl<T> consumer = consumers.get(messageId1.getTopicName());
MessageId innerId = messageId1.getInnerMessageId();
return consumer.doAcknowledge(innerId, ackType, properties).thenRun(() -> unAckedMessageTracker.remove(messageId1));
}
}
use of org.apache.pulsar.client.api.PulsarClientException in project incubator-pulsar by apache.
the class TopicsConsumerImpl method internalReceive.
@Override
protected Message<T> internalReceive(int timeout, TimeUnit unit) throws PulsarClientException {
Message<T> message;
try {
message = incomingMessages.poll(timeout, unit);
if (message != null) {
checkArgument(message instanceof TopicMessageImpl);
unAckedMessageTracker.add(message.getMessageId());
}
resumeReceivingFromPausedConsumersIfNeeded();
return message;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new PulsarClientException(e);
}
}
Aggregations