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

com.github.segmentio.safeclient.flusher.ThreadPoolFlusher Maven / Gradle / Ivy

package com.github.segmentio.safeclient.flusher;

import java.lang.Thread.UncaughtExceptionHandler;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

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

import com.github.segmentio.safeclient.BatchedOperation;
import com.google.common.util.concurrent.ThreadFactoryBuilder;

public class ThreadPoolFlusher implements IFlusher {
	
	private static final Logger logger = LoggerFactory.getLogger(ThreadPoolFlusher .class);

	private ThreadPoolExecutor executor;
	private int maxRunnableQueueSize;
	
	public ThreadPoolFlusher(int coreThreads, int maxThreads, 
			int maxRunnableQueueSize) {
		
		this.maxRunnableQueueSize = maxRunnableQueueSize;
		
		executor = createNamedFixedBoundedThreadPool(
				coreThreads, 
				maxThreads, 
				maxRunnableQueueSize,
				"SafeClient - ThreadPoolFlusher");
		
	}

	public boolean canFlush() {
		// we don't want threads to race, so we go for a little bit less than the
		// maximum queue size
		return executor.getQueue().size() < Math.max(1, (maxRunnableQueueSize/2));
	}
	
	public  void flush(
			final BatchedOperation operation, 
			final List batch) {
		
		try {
			
			executor.execute(new Runnable() {
				public void run() {
					operation.performFlush(batch);
				};
			});
			
		} catch (RejectedExecutionException e) {
			
			// this is happening if we are flushing at a faster rate
			// than we can flush out. In this case, we choose to drop packets
			// rather than fill up a queue and hurt system resources
			
			logger.error(
					"Thread pool flusher can not keep up to the flush rate, dropping flush batch.", e);
		}
		
	}
	
	private static ThreadFactoryBuilder createThreadPoolBuilder(String threadPoolName)
	{
		ThreadFactoryBuilder builder = new ThreadFactoryBuilder();
		builder.setNameFormat(threadPoolName + "-%d" );
		builder.setUncaughtExceptionHandler(new UncaughtExceptionHandler()
		{
			public void uncaughtException(Thread t, Throwable e) {

				logger.error( 
						String.format("Uncaught thread pool exception in thread %s and exception %s.", 
								String.format("%s-%s", 
										t.getThreadGroup().getName(), 
										t.getName()),  
										e.getMessage()), e);
			}	
		});

		return builder;
	}
	
	
	public static ThreadPoolExecutor createNamedFixedBoundedThreadPool(
			int corePoolSize, 
			int maxPoolSize, 
			int maxRunnableQueueSize, 
			String threadPoolName)
	{
		
		ThreadFactoryBuilder builder = createThreadPoolBuilder(threadPoolName);
		
		ThreadPoolExecutor executor = new ThreadPoolExecutor(
				corePoolSize, 
				maxPoolSize, 
				5, 
				TimeUnit.SECONDS, 
				new LinkedBlockingQueue(maxRunnableQueueSize), 
				builder.build());
		
		return executor;
	}

	public void close() {
		if (executor != null) executor.shutdown();
	}
	
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy