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

com.ebay.jetstream.event.EventBatcher Maven / Gradle / Ivy

/*******************************************************************************
 *  Copyright © 2012-2015 eBay Software Foundation
 *  This program is dual licensed under the MIT and Apache 2.0 licenses.
 *  Please see LICENSE for more information.
 *******************************************************************************/
package com.ebay.jetstream.event;


import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;

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


/**
 * 
 * @author [email protected] ([email protected])
 * 
 */

@edu.umd.cs.findbugs.annotations.SuppressWarnings(value="NN_NAKED_NOTIFY")

public class EventBatcher implements Runnable {

		
	private static final Logger LOGGER = LoggerFactory.getLogger("com.ebay.jetstream.event");
	private static final int BATCH_SIZE = 5;
	private static final int MAX_RETRIES = 3;
	private final ConcurrentLinkedQueue m_queue = new ConcurrentLinkedQueue();
	private int m_batchSize = BATCH_SIZE;
	private int m_flushTime = 20; // 20 secs
	private int m_maxQueueSz = 5000;

	public EventBatcher() {}
	
	public int getMaxQueueSz() {
		return m_maxQueueSz;
	}

	public void setMaxQueueSz(int m_maxQueueSz) {
		this.m_maxQueueSz = m_maxQueueSz;
	}

	private final AtomicBoolean m_shutdown = new AtomicBoolean(false);
	private BatchEventSink m_batchEventSink;
	private Thread m_queueProcessor;
	
	public void start() {
		m_queueProcessor = new Thread(this, "EventBatcherThread");
		m_queueProcessor.start();
	}
	
	public BatchEventSink getBatchEventSink() {
		return m_batchEventSink;
	}

	public void setBatchEventSink(BatchEventSink m_batchEventSink) {
		this.m_batchEventSink = m_batchEventSink;
	}

	public EventBatcher(BatchEventSink sink) {
		m_batchEventSink = sink;
	}

	public void flushQueue() {
		List eventList = new ArrayList();


		while(!m_queue.isEmpty()) {
			eventList.clear();

			for (int i = 0; i < Math.min(m_batchSize, m_queue.size()); i++) {
				eventList.add(m_queue.poll());
			}

			writeEvents(eventList);

		}
	}

	/**
	 * @return the batchSize
	 */
	public int getBatchSize() {
		return m_batchSize;
	}



	/**
	 * @return the flushTime
	 */
	public int getFlushTime() {
		return m_flushTime;
	}



	private void processQueue() {

		List eventList = new ArrayList();

		while(!m_shutdown.get()) {

			try {

				eventList.clear();

				if (m_queue.size() != 0) {

					for (int i = 0; i < m_batchSize; i++) {
						eventList.add(m_queue.poll());
					}

					writeEvents(eventList);

				}
				synchronized (this) {
					try {
						this.wait(m_flushTime * 1000);
					}
					catch (InterruptedException e) {
						LOGGER.debug( "EventBatcher:processQueue wait interrupted");
					}
					if (m_shutdown.get())
						break;
				}

			} catch (Throwable t) {
				LOGGER.error( "EventBatcher:processQueue Exception " + t.getLocalizedMessage());
			}
		}
	}


	private void writeEvents(List eventList) {
		int retryCount = MAX_RETRIES;

		while (--retryCount > 0) {

			m_batchEventSink.sendEvents(eventList, null);
			
			break;

		}
	}

	@Override
	public void run() {
		
		try {
			processQueue();

			flushQueue(); // we will flush whatever is remaining in queue
		} catch (Throwable t) {
			LOGGER.error( "EventBatcher:run - shutting down");
		}
	}

	/**
	 * @param batchSize
	 *          the batchSize to set
	 */
	public void setBatchSize(int batchSize) {
		m_batchSize = batchSize;
	}

	/**
	 * @param flushTime
	 *          the flushTime to set
	 */
	public void setFlushTime(int flushTime) {
		m_flushTime = flushTime;
	}

	/**
	 * @param shutdown
	 *          the shutdown to set
	 */
	public void shutdown() {
		m_shutdown.set(true);

		synchronized (this) {
			this.notifyAll();  
		}

	}

	public void submit(JetstreamEvent event) throws Exception {
		if (m_shutdown.get())
			throw new Exception("shutting down");
		

		if (m_queue.size() >= m_maxQueueSz)
			throw new Exception("Queue full");

		m_queue.add(event);

		if (m_queue.size() >= m_batchSize)
			synchronized (this) {
				this.notifyAll();  
			}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy