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

com.xiaomi.infra.galaxy.talos.consumer.MessageReader Maven / Gradle / Ivy

There is a newer version: 2.6.1.4
Show newest version
/**
 * Copyright 2015, Xiaomi.
 * All rights reserved.
 * Author: [email protected]
 */

package com.xiaomi.infra.galaxy.talos.consumer;

import java.util.concurrent.atomic.AtomicLong;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.xiaomi.infra.galaxy.talos.client.Utils;
import com.xiaomi.infra.galaxy.talos.thrift.ConsumerService;
import com.xiaomi.infra.galaxy.talos.thrift.MessageOffset;
import com.xiaomi.infra.galaxy.talos.thrift.TopicAndPartition;

/**
 * The base class using by PartitionFetcher
 */

public abstract class MessageReader {
  private static final Logger LOG = LoggerFactory.getLogger(MessageReader.class);
  protected int commitThreshold;
  protected int commitInterval;
  protected int fetchInterval;

  protected long lastCommitTime;
  protected long lastFetchTime;

  protected AtomicLong startOffset;
  protected long finishedOffset;
  protected long lastCommitOffset;
  protected MessageProcessor messageProcessor;

  protected String workerId;
  protected String consumerGroup;
  protected TopicAndPartition topicAndPartition;
  protected TalosConsumerConfig consumerConfig;
  protected SimpleConsumer simpleConsumer;
  protected ConsumerService.Iface consumerClient;

  public MessageReader(TalosConsumerConfig consumerConfig) {
    this.consumerConfig = consumerConfig;
    lastCommitOffset = finishedOffset = -1;
    lastCommitTime = lastFetchTime = System.currentTimeMillis();
    startOffset = new AtomicLong(-1);
    commitThreshold = consumerConfig.getCommitOffsetThreshold();
    commitInterval = consumerConfig.getCommitOffsetInterval();
    fetchInterval = consumerConfig.getFetchMessageInterval();
  }

  public MessageReader setWorkerId(String workerId) {
    this.workerId = workerId;
    return this;
  }

  public MessageReader setConsumerGroup(String consumerGroup) {
    Utils.checkNameValidity(consumerGroup);
    this.consumerGroup = consumerGroup;
    return this;
  }

  public MessageReader setTopicAndPartition(TopicAndPartition topicAndPartition) {
    this.topicAndPartition = topicAndPartition;
    return this;
  }

  public MessageReader setSimpleConsumer(SimpleConsumer simpleConsumer) {
    this.simpleConsumer = simpleConsumer;
    return this;
  }

  public MessageReader setMessageProcessor(MessageProcessor messageProcessor) {
    this.messageProcessor = messageProcessor;
    return this;
  }

  public MessageReader setConsumerClient(ConsumerService.Iface consumerClient) {
    this.consumerClient = consumerClient;
    return this;
  }

  public AtomicLong getStartOffset() {
    return startOffset;
  }

  protected boolean shoudCommit() {
    return (System.currentTimeMillis() - lastCommitTime >= commitInterval) ||
        (finishedOffset - lastCommitOffset >= commitThreshold);
  }

  protected void cleanReader() {
    // wait task quit gracefully: stop reading, commit offset, clean and shutdown
    if (finishedOffset > lastCommitOffset) {
      try {
        commitCheckPoint();
      } catch (Exception e) {
        LOG.error("Error: " + e.toString() + " when commit offset for topic: " +
            topicAndPartition.getTopicTalosResourceName() +
            " partition: " + topicAndPartition.getPartitionId());
      }
    }
  }

  protected void processFetchException(Throwable e) {
    // delay when partitionNotServing
    if (Utils.isPartitionNotServing(e)) {
      LOG.warn("Partition: " + topicAndPartition.getPartitionId() +
          " is not serving state, sleep a while for waiting it work.");
      try {
        Thread.sleep(consumerConfig.getWaitPartitionWorkingTime());
      } catch (InterruptedException e1) {
        e1.printStackTrace();
      }
    } // if

    // process message offset out of range, reset start offset
    if (Utils.isOffsetOutOfRange(e)) {
      if (consumerConfig.isResetLatestOffsetWhenOutOfRange()) {
        LOG.warn("Got PartitionOutOfRange error, " +
            " offset by current latest offset");
        startOffset.set(MessageOffset.LATEST_OFFSET.getValue());
        lastCommitOffset = finishedOffset = - 1;
        lastCommitTime = System.currentTimeMillis();
      } else {
        LOG.warn("Got PartitionOutOfRange error," +
            " reset offset by current start offset");
        startOffset.set(MessageOffset.START_OFFSET.getValue());
        lastCommitOffset = finishedOffset = - 1;
        lastCommitTime = System.currentTimeMillis();
      }
    } // if
  }

  /**
   * query start offset to read, if failed, throw the exception
   */
  public abstract void initStartOffset() throws Exception;

  /**
   * commit the last processed offset and update the startOffset
   * throw the Exception when appear error
   */
  public abstract void commitCheckPoint() throws Exception;

  /**
   * you should implement this method as follow process:
   * 1. control fetch qps by fetchInterval
   * 2. fetchMessage with try/catch structure and process exception
   * 2.1 catch chunk process PARTITION_NOT_SERVING by sleep a while
   * 2.2 catch chunk process MESSAGE_OFFSET_OUT_OF_RANGE by fixOffsetOutofRange()
   * 2.3 reset lastFetchTime
   * 3. process fetched message by MessageProcessor and update finishedOffset/startOffset
   * 4. check whether should commit offset
   */
  public abstract void fetchData();

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy