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

com.cj.kafka.rx.OffsetManager.scala Maven / Gradle / Ivy

The newest version!
package com.cj.kafka.rx

import kafka.message.MessageAndMetadata

class OffsetManager[K, V](offsetCommitter: OffsetCommitter) {

  // Offset Manager keeps track of offsets per partition for a particular kafka stream
  private var currentOffsets = Map[TopicPartition, Long]()
  def getOffsets: OffsetMap = currentOffsets

  def check(message: MessageAndMetadata[K, V]): Option[Record[K, V]] = {
    // updates internal offset state & determines whether the message is stale due to replay
    currentOffsets.get(message.topic -> message.partition) match {
      case None => manageMessage(message)
      case Some(priorOffset) =>
        if (message.offset > priorOffset) manageMessage(message)
        else None
    }
  }

  def manage(externalOffsets: OffsetMap, internalOffsets: OffsetMap): OffsetMap = {
    // kafka rebalancing can cause skewed views of partition ownership
    currentOffsets = currentOffsets.filter { case (topicPartition, internalOffset) =>
      // we only own those topic partitions where our offsets are higher then external
      val externalOffset = externalOffsets.getOrElse(topicPartition, -1L)
      internalOffset >= externalOffset
    }
    internalOffsets filter { case (topicPartition, offset) =>
      currentOffsets.contains(topicPartition)
    }
  }

  def commitWith(internalOffsets: OffsetMap)(merge: OffsetMerge): OffsetMap = {
    offsetCommitter.commit(internalOffsets, { case (externalOffsets, _) =>
      manage(externalOffsets, merge(externalOffsets, internalOffsets))
    })
  }

  private def manageMessage(msg:  MessageAndMetadata[K, V]): Some[Record[K, V]] = {
    currentOffsets += msg.topic -> msg.partition -> msg.offset
    Some(new Record(msg, commitWith(currentOffsets)))
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy