Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions core/src/main/scala/kafka/consumer/BaseConsumer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ trait BaseConsumer {

case class BaseConsumerRecord(topic: String, partition: Int, offset: Long, key: Array[Byte], value: Array[Byte])

class NewShinyConsumer(topic: String, consumerProps: Properties) extends BaseConsumer {
class NewShinyConsumer(topic: String, consumerProps: Properties, val timeoutMs: Long = Long.MaxValue) extends BaseConsumer {
import org.apache.kafka.clients.consumer.KafkaConsumer
import scala.collection.JavaConversions._

Expand All @@ -41,8 +41,11 @@ class NewShinyConsumer(topic: String, consumerProps: Properties) extends BaseCon
var recordIter = consumer.poll(0).iterator

override def receive(): BaseConsumerRecord = {
while (!recordIter.hasNext)
recordIter = consumer.poll(Long.MaxValue).iterator
if (!recordIter.hasNext) {
recordIter = consumer.poll(timeoutMs).iterator
if (!recordIter.hasNext)
throw new ConsumerTimeoutException
}

val record = recordIter.next
BaseConsumerRecord(record.topic, record.partition, record.offset, record.key, record.value)
Expand Down
16 changes: 12 additions & 4 deletions core/src/main/scala/kafka/tools/ConsoleConsumer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ object ConsoleConsumer extends Logging {

val consumer =
if (conf.useNewConsumer) {
new NewShinyConsumer(conf.topicArg, getNewConsumerProps(conf))
val timeoutMs = if (conf.timeoutMs >= 0) conf.timeoutMs else Long.MaxValue

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be ok to throw an Exception if a negative timeout is specified

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@auradkar The timeout parameter is consistent with "consumer.timeout.ms" config option in the old consumer. With the old consumer, timeout less than zero indicates that there is no timeout. The same behaviour is used here for consistency.

new NewShinyConsumer(conf.topicArg, getNewConsumerProps(conf), timeoutMs)
} else {
checkZk(conf)
new OldConsumer(conf.filterSpec, getOldConsumerProps(conf))
Expand Down Expand Up @@ -100,8 +101,8 @@ object ConsoleConsumer extends Logging {
consumer.receive()
} catch {
case e: Throwable => {
error("Error processing message, stopping consumer: ", e)
consumer.stop()
error("Error processing message, terminating consumer process: ", e)
// Consumer will be closed
return
}
}
Expand All @@ -112,7 +113,7 @@ object ConsoleConsumer extends Logging {
if (skipMessageOnError) {
error("Error processing message, skipping this message: ", e)
} else {
consumer.stop()
// Consumer will be closed
throw e
}
}
Expand Down Expand Up @@ -149,6 +150,8 @@ object ConsoleConsumer extends Logging {

if (config.options.has(config.deleteConsumerOffsetsOpt))
ZkUtils.maybeDeletePath(config.options.valueOf(config.zkConnectOpt), "/consumers/" + config.consumerProps.getProperty("group.id"))
if (config.timeoutMs >= 0)
props.put("consumer.timeout.ms", config.timeoutMs.toString)

props
}
Expand Down Expand Up @@ -204,6 +207,10 @@ object ConsoleConsumer extends Logging {
.withRequiredArg
.describedAs("num_messages")
.ofType(classOf[java.lang.Integer])
val timeoutMsOpt = parser.accepts("timeout-ms", "If specified, exit if no message is available for consumption for the specified interval.")
.withRequiredArg
.describedAs("timeout_ms")
.ofType(classOf[java.lang.Integer])
val skipMessageOnErrorOpt = parser.accepts("skip-message-on-error", "If there is an error when processing a message, " +
"skip it instead of halt.")
val csvMetricsReporterEnabledOpt = parser.accepts("csv-reporter-enabled", "If set, the CSV metrics reporter will be enabled")
Expand Down Expand Up @@ -246,6 +253,7 @@ object ConsoleConsumer extends Logging {
val messageFormatterClass = Class.forName(options.valueOf(messageFormatterOpt))
val formatterArgs = CommandLineUtils.parseKeyValueArgs(options.valuesOf(messageFormatterArgOpt))
val maxMessages = if (options.has(maxMessagesOpt)) options.valueOf(maxMessagesOpt).intValue else -1
val timeoutMs = if (options.has(timeoutMsOpt)) options.valueOf(timeoutMsOpt).intValue else -1
val bootstrapServer = options.valueOf(bootstrapServerOpt)
val keyDeserializer = options.valueOf(keyDeserializerOpt)
val valueDeserializer = options.valueOf(valueDeserializerOpt)
Expand Down
2 changes: 2 additions & 0 deletions tests/kafkatest/services/console_consumer.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ def start_cmd(self):
cmd += " --zookeeper %(zk_connect)s" % args
if self.from_beginning:
cmd += " --from-beginning"
if self.consumer_timeout_ms is not None:
cmd += " --timeout-ms %s" % self.consumer_timeout_ms

cmd += " 2>> %(stderr)s | tee -a %(stdout)s &" % args
return cmd
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@
# limitations under the License.
# see kafka.server.KafkaConfig for additional details and defaults

{% if consumer_timeout_ms is defined and consumer_timeout_ms is not none %}
consumer.timeout.ms={{ consumer_timeout_ms }}
{% endif %}

group.id={{ group_id|default('test-consumer-group') }}

{% if client_id is defined and client_id is not none %}
Expand Down