/**
* Copyright 2016 Yahoo Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.yahoo.pulsar.client.api;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.util.concurrent.TimeUnit;
import com.google.common.base.Objects;
import com.yahoo.pulsar.client.impl.RoundRobinPartitionMessageRouterImpl;
import com.yahoo.pulsar.client.impl.SinglePartitionMessageRouterImpl;
/**
* Producer's configuration
*
*/
public class ProducerConfiguration implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private long sendTimeoutMs = 30000;
private int maxPendingMessages = 1000;
private boolean blockIfQueueFull = true;
private MessageRoutingMode messageRouteMode = MessageRoutingMode.SinglePartition;
private MessageRouter customMessageRouter = null;
private long batchingMaxPublishDelayMs = 10;
private int batchingMaxMessages = 1000;
private boolean batchingEnabled = false; // disabled by default
private CompressionType compressionType = CompressionType.NONE;
public enum MessageRoutingMode {
SinglePartition, RoundRobinPartition, CustomPartition
}
/**
* @return the message send timeout in ms
*/
public long getSendTimeoutMs() {
return sendTimeoutMs;
}
/**
* Set the send timeout <i>(default: 30 seconds)</i>
* <p>
* If a message is not acknowledged by the server before the sendTimeout expires, an error will be reported.
*
* @param sendTimeout
* the send timeout
* @param unit
* the time unit of the {@code sendTimeout}
*/
public ProducerConfiguration setSendTimeout(int sendTimeout, TimeUnit unit) {
checkArgument(sendTimeout >= 0);
this.sendTimeoutMs = unit.toMillis(sendTimeout);
return this;
}
/**
* @return the maximum number of messages allowed in the outstanding messages queue for the producer
*/
public int getMaxPendingMessages() {
return maxPendingMessages;
}
/**
* Set the max size of the queue holding the messages pending to receive an acknowledgment from the broker.
* <p>
* When the queue is full, by default, all calls to {@link Producer#send} and {@link Producer#sendAsync} and send
* will block the calling thread. Use {@link #setBlockIfQueueFull} to change the blocking behavior.
*
* @param maxPendingMessages
* @return
*/
public ProducerConfiguration setMaxPendingMessages(int maxPendingMessages) {
checkArgument(maxPendingMessages > 0);
this.maxPendingMessages = maxPendingMessages;
return this;
}
/**
*
* @return whether the producer will block {@link Producer#send} and {@link Producer#sendAsync} operations when the
* pending queue is full
*/
public boolean getBlockIfQueueFull() {
return blockIfQueueFull;
}
/**
* Set whether the {@link Producer#send} and {@link Producer#sendAsync} operations should block when the outgoing
* message queue is full.
* <p>
* Default is <code>true</code>. If set to <code>false</code>, send operations will immediately fail with
* {@link ProducerQueueIsFullError} when there is no space left in pending queue.
*
* @param blockIfQueueFull
* whether to block {@link Producer#send} and {@link Producer#sendAsync} operations on queue full
* @return
*/
public ProducerConfiguration setBlockIfQueueFull(boolean blockIfQueueFull) {
this.blockIfQueueFull = blockIfQueueFull;
return this;
}
/**
* Set the message routing mode for the partitioned producer
*
* @param mode
* @return
*/
public ProducerConfiguration setMessageRoutingMode(MessageRoutingMode messageRouteMode) {
checkNotNull(messageRouteMode);
this.messageRouteMode = messageRouteMode;
return this;
}
/**
* Get the message routing mode for the partitioned producer
*
* @return
*/
public MessageRoutingMode getMessageRoutingMode() {
return messageRouteMode;
}
/**
* Set the compression type for the producer.
* <p>
* By default, message payloads are not compressed. Supported compression types are:
* <ul>
* <li><code>CompressionType.LZ4</code></li>
* <li><code>CompressionType.ZLIB</code></li>
* </ul>
*
* @param compressionType
* @return
*
* @since 1.0.28 <br>
* Make sure all the consumer applications have been updated to use this client version, before starting to
* compress messages.
*/
public ProducerConfiguration setCompressionType(CompressionType compressionType) {
this.compressionType = compressionType;
return this;
}
/**
* @return the configured compression type for this producer
*/
public CompressionType getCompressionType() {
return compressionType;
}
/**
* Set a custom message routing policy by passing an implementation of MessageRouter
*
*
* @param messageRouter
*/
public ProducerConfiguration setMessageRouter(MessageRouter messageRouter) {
checkNotNull(messageRouter);
setMessageRoutingMode(MessageRoutingMode.CustomPartition);
customMessageRouter = messageRouter;
return this;
}
/**
* Get the message router object
*
* @return
*/
public MessageRouter getMessageRouter(int numPartitions) {
MessageRouter messageRouter;
switch (messageRouteMode) {
case CustomPartition:
checkNotNull(customMessageRouter);
messageRouter = customMessageRouter;
break;
case RoundRobinPartition:
messageRouter = new RoundRobinPartitionMessageRouterImpl(numPartitions);
break;
case SinglePartition:
default:
messageRouter = new SinglePartitionMessageRouterImpl(numPartitions);
}
return messageRouter;
}
/**
* @ return if batch messages are enabled
*/
public boolean getBatchingEnabled() {
return batchingEnabled;
}
/**
* Control whether automatic batching of messages is enabled for the producer. <i>default: false [No batching]</i>
*
* When batching is enabled, multiple calls to Producer.sendAsync can result in a single batch to be sent to the
* broker, leading to better throughput, especially when publishing small messages. If compression is enabled,
* messages will be compressed at the batch level, leading to a much better compression ratio for similar headers or
* contents.
*
* When enabled default batch delay is set to 10 ms and default batch size is 1000 messages
*
* @see ProducerConfiguration#setBatchingMaxPublishDelay(long, TimeUnit)
* @since 1.0.36 <br>
* Make sure all the consumer applications have been updated to use this client version, before starting to
* batch messages.
*/
public ProducerConfiguration setBatchingEnabled(boolean batchMessagesEnabled) {
this.batchingEnabled = batchMessagesEnabled;
return this;
}
/**
*
* @return the batch time period in ms.
* @see ProducerConfiguration#setBatchingMaxPublishDelay(long, TimeUnit)
*/
public long getBatchingMaxPublishDelayMs() {
return batchingMaxPublishDelayMs;
}
/**
* Set the time period within which the messages sent will be batched <i>default: 10ms</i> if batch messages are
* enabled. If set to a non zero value, messages will be queued until this time interval or until
*
* @see ProducerConfiguration#batchingMaxMessages threshold is reached; all messages will be published as a single
* batch message. The consumer will be delivered individual messages in the batch in the same order they were
* enqueued
* @since 1.0.36 <br>
* Make sure all the consumer applications have been updated to use this client version, before starting to
* batch messages.
* @param batchDelay
* the batch delay
* @param timeUnit
* the time unit of the {@code batchDelay}
* @return
*/
public ProducerConfiguration setBatchingMaxPublishDelay(long batchDelay, TimeUnit timeUnit) {
long delayInMs = timeUnit.toMillis(batchDelay);
checkArgument(delayInMs >= 1, "configured value for batch delay must be at least 1ms");
this.batchingMaxPublishDelayMs = delayInMs;
return this;
}
/**
*
* @return the maximum number of messages permitted in a batch.
*/
public int getBatchingMaxMessages() {
return batchingMaxMessages;
}
/**
* Set the maximum number of messages permitted in a batch. <i>default: 1000</i> If set to a value greater than 1,
* messages will be queued until this threshold is reached or batch interval has elapsed
*
* @see ProducerConfiguration#setBatchingMaxPublishDelay(long, TimeUnit) All messages in batch will be published as
* a single batch message. The consumer will be delivered individual messages in the batch in the same order
* they were enqueued
* @param batchMessagesMaxMessagesPerBatch
* maximum number of messages in a batch
* @return
*/
public ProducerConfiguration setBatchingMaxMessages(int batchMessagesMaxMessagesPerBatch) {
checkArgument(batchMessagesMaxMessagesPerBatch > 0);
this.batchingMaxMessages = batchMessagesMaxMessagesPerBatch;
return this;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof ProducerConfiguration) {
ProducerConfiguration other = (ProducerConfiguration) obj;
return Objects.equal(this.sendTimeoutMs, other.sendTimeoutMs)
&& Objects.equal(maxPendingMessages, other.maxPendingMessages)
&& Objects.equal(this.messageRouteMode, other.messageRouteMode);
}
return false;
}
}