com.flipkart.aesop.runtime.bootstrap.consumer.DefaultBlockingEventConsumer.java Source code

Java tutorial

Introduction

Here is the source code for com.flipkart.aesop.runtime.bootstrap.consumer.DefaultBlockingEventConsumer.java

Source

/*
 * Copyright 2012-2015, the original author or authors.
 * 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.flipkart.aesop.runtime.bootstrap.consumer;

import com.flipkart.aesop.event.AbstractEvent;
import com.flipkart.aesop.eventconsumer.AbstractEventConsumer;
import com.google.common.base.Joiner;
import com.linkedin.databus2.core.BackoffTimer;
import org.springframework.beans.factory.InitializingBean;
import org.trpr.platform.core.impl.logging.LogFactory;
import org.trpr.platform.core.spi.logging.Logger;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * <code>DefaultBlockingEventConsumer</code> is the default blocking implementation for {@link SourceEventConsumer}. It
 * submits the events to the appropriate thread pool.
 * @author nrbafna
 */
public class DefaultBlockingEventConsumer implements SourceEventConsumer, InitializingBean {
    public static final Logger LOGGER = LogFactory.getLogger(DefaultBlockingEventConsumer.class);

    private static final long DEFAULT_THREAD_AWAIT_TERMINATION_TIME_IN_SECS = 60;
    private final String PRIMARY_KEY_SEPERATOR = ";";
    /** executor pool for parallelizing consumption */
    private List<ThreadPoolExecutor> executors = new ArrayList<ThreadPoolExecutor>();
    /** No. Of Partitions to create  */
    private int numberOfPartition;
    /* Event Consumer to send events to */
    private AbstractEventConsumer eventConsumer;
    /* Back-Off Timer config */
    private BackoffTimer backoffTimer;
    /*
     * Thread Termination Max time. This config will ensure that threads
     * termination during shut-down is waiting for max these many secs
     * */
    private long threadTerminationMaxTime = DEFAULT_THREAD_AWAIT_TERMINATION_TIME_IN_SECS;
    private int executorQueueSize;
    private RejectedExecutionHandler rejectedExecutionHandler;

    @Override
    public void onEvent(AbstractEvent sourceEvent) {
        /** partition and submit */
        String primaryKeyValues = Joiner.on(PRIMARY_KEY_SEPERATOR).join(sourceEvent.getPrimaryKeyValues());
        Integer partitionNumber = ((primaryKeyValues.hashCode() & 0x7fffffff) % numberOfPartition);
        LOGGER.debug("Partition:" + primaryKeyValues.hashCode() + ":" + partitionNumber);
        executors.get(partitionNumber).execute(new SourceEventProcessor(sourceEvent, eventConsumer, backoffTimer));
    }

    public void shutdown() {
        for (int i = 0; i < numberOfPartition; i++) {
            executors.get(i).shutdown();
        }

        try {
            for (int i = 0; i < numberOfPartition; i++) {
                executors.get(i).awaitTermination(threadTerminationMaxTime, TimeUnit.NANOSECONDS);
            }
        } catch (InterruptedException e) {
            LOGGER.error("Error while stopping bootstrap consumer", e);
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        this.numberOfPartition = Math.min(numberOfPartition, Runtime.getRuntime().availableProcessors());
        LOGGER.info("numberOfPartition used: " + numberOfPartition);
        for (int i = 0; i < numberOfPartition; i++) {
            BlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(executorQueueSize);
            executors.add(new ThreadPoolExecutor(1, 1, 0, TimeUnit.MILLISECONDS, queue, rejectedExecutionHandler));
        }
    }

    /** Getters and Setters */
    public AbstractEventConsumer getEventConsumer() {
        return eventConsumer;
    }

    public void setEventConsumer(AbstractEventConsumer eventConsumer) {
        this.eventConsumer = eventConsumer;
    }

    public BackoffTimer getBackoffTimer() {
        return backoffTimer;
    }

    public void setBackoffTimer(BackoffTimer backoffTimer) {
        this.backoffTimer = backoffTimer;
    }

    public long getThreadTerminationMaxTime() {
        return threadTerminationMaxTime;
    }

    public void setThreadTerminationMaxTime(long threadTerminationMaxTime) {
        this.threadTerminationMaxTime = threadTerminationMaxTime;
    }

    public int getExecutorQueueSize() {
        return executorQueueSize;
    }

    public void setExecutorQueueSize(int executorQueueSize) {
        this.executorQueueSize = executorQueueSize;
    }

    public RejectedExecutionHandler getRejectedExecutionHandler() {
        return rejectedExecutionHandler;
    }

    public void setRejectedExecutionHandler(RejectedExecutionHandler rejectedExecutionHandler) {
        this.rejectedExecutionHandler = rejectedExecutionHandler;
    }

    public int getNumberOfPartition() {
        return numberOfPartition;
    }

    public void setNumberOfPartition(int numberOfPartition) {
        this.numberOfPartition = numberOfPartition;
    }
}