All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sksamuel.pulsar4s.Consumer.scala Maven / Gradle / Ivy

package com.sksamuel.pulsar4s

import java.io.Closeable
import java.util.concurrent.TimeUnit

import com.sksamuel.exts.Logging
import org.apache.pulsar.client.api.ConsumerStats

import scala.concurrent.duration.FiniteDuration
import scala.language.{higherKinds, implicitConversions}
import scala.util.Try

trait Consumer[T] extends Closeable {

  /**
    * Receives a single message.
    * This calls blocks until a message is available.
    */
  def receive: Try[ConsumerMessage[T]]

  /**
    * Receive a single message waiting up to the given duration
    * if necessary. If no message is received within the duration
    * then None is returned.
    */
  def receive(duration: FiniteDuration): Try[Option[ConsumerMessage[T]]]

  def receiveAsync[F[_] : AsyncHandler]: F[ConsumerMessage[T]]

  def stats: ConsumerStats

  def subscription: Subscription

  def topic: Topic

  /**
    * Return true if the topic was terminated and this consumer has already consumed all the messages in the topic.
    *
    * Please note that this does not simply mean that the consumer is caught up with the last message published by
    * producers, rather the topic needs to be explicitly "terminated".
    */
  def hasReachedEndOfTopic: Boolean

  def redeliverUnacknowledgedMessages(): Unit

  def seek(messageId: MessageId): Unit
  def seekEarliest(): Unit = seek(MessageId.earliest)
  def seekLatest(): Unit = seek(MessageId.latest)
  def seekAsync[F[_] : AsyncHandler](messageId: MessageId): F[Unit]

  def close(): Unit
  def closeAsync[F[_] : AsyncHandler]: F[Unit]

  def acknowledge(message: ConsumerMessage[T]): Unit = acknowledge(message.messageId)
  def acknowledge(messageId: MessageId): Unit

  def negativeAcknowledge(message: ConsumerMessage[T]): Unit = negativeAcknowledge(message.messageId)
  def negativeAcknowledge(messageId: MessageId): Unit

  def acknowledgeCumulative(message: ConsumerMessage[T]): Unit
  def acknowledgeCumulative(messageId: MessageId): Unit

  final def acknowledgeAsync[F[_] : AsyncHandler](message: ConsumerMessage[T]): F[Unit] =
    acknowledgeAsync(message.messageId)

  def acknowledgeAsync[F[_] : AsyncHandler](messageId: MessageId): F[Unit]

  final def negativeAcknowledgeAsync[F[_] : AsyncHandler](message: ConsumerMessage[T]): F[Unit] =
    negativeAcknowledgeAsync(message.messageId)

  def negativeAcknowledgeAsync[F[_] : AsyncHandler](messageId: MessageId): F[Unit]

  final def acknowledgeCumulativeAsync[F[_] : AsyncHandler](message: ConsumerMessage[T]): F[Unit] =
    acknowledgeCumulativeAsync(message.messageId)

  def acknowledgeCumulativeAsync[F[_] : AsyncHandler](messageId: MessageId): F[Unit]

  def unsubscribe(): Unit
  def unsubscribeAsync[F[_] : AsyncHandler]: F[Unit]
}

class DefaultConsumer[T](consumer: JConsumer[T]) extends Consumer[T] with Logging {

  override def receive: Try[ConsumerMessage[T]] = Try {
    logger.trace("About to block until a message is received..")
    val msg = consumer.receive()
    ConsumerMessage.fromJava(msg)
  }

  override def receive(duration: FiniteDuration): Try[Option[ConsumerMessage[T]]] = Try {
    logger.trace(s"About to block for duration $duration or until a message is received..")
    val msg = consumer.receive(duration.toMillis.toInt, TimeUnit.MILLISECONDS)
    Option(msg).map(ConsumerMessage.fromJava)
  }

  override def receiveAsync[F[_] : AsyncHandler]: F[ConsumerMessage[T]] = implicitly[AsyncHandler[F]].receive(consumer)

  override def acknowledge(messageId: MessageId): Unit = consumer.acknowledge(messageId)
  override def acknowledgeCumulative(message: ConsumerMessage[T]): Unit = consumer.acknowledgeCumulative(message.messageId)
  override def acknowledgeCumulative(messageId: MessageId): Unit = consumer.acknowledgeCumulative(messageId)

  override def acknowledgeAsync[F[_] : AsyncHandler](messageId: MessageId): F[Unit] =
    implicitly[AsyncHandler[F]].acknowledgeAsync(consumer, messageId)
  override def acknowledgeCumulativeAsync[F[_] : AsyncHandler](messageId: MessageId): F[Unit] =
    implicitly[AsyncHandler[F]].acknowledgeCumulativeAsync(consumer, messageId)

  override def negativeAcknowledge(messageId: MessageId): Unit = consumer.negativeAcknowledge(messageId)
  override def negativeAcknowledgeAsync[F[_]: AsyncHandler](messageId: MessageId): F[Unit] =
    implicitly[AsyncHandler[F]].negativeAcknowledgeAsync(consumer, messageId)

  override def stats: ConsumerStats = consumer.getStats
  override def subscription = Subscription(consumer.getSubscription)
  override def topic = Topic(consumer.getTopic)

  override def hasReachedEndOfTopic: Boolean = consumer.hasReachedEndOfTopic

  override def redeliverUnacknowledgedMessages(): Unit = consumer.redeliverUnacknowledgedMessages()

  override def seek(messageId: MessageId): Unit = consumer.seek(messageId)

  override def seekAsync[F[_] : AsyncHandler](messageId: MessageId): F[Unit] =
    implicitly[AsyncHandler[F]].seekAsync(consumer, messageId)

  override def close(): Unit = {
    logger.info("Closing consumer")
    consumer.close()
  }

  override def closeAsync[F[_] : AsyncHandler]: F[Unit] = implicitly[AsyncHandler[F]].close(consumer)

  override def unsubscribe(): Unit = consumer.unsubscribe()
  override def unsubscribeAsync[F[_] : AsyncHandler]: F[Unit] = implicitly[AsyncHandler[F]].unsubscribeAsync(consumer)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy