// - failures are logged
// - when storage queue is full, we throttle backwards to the serialization threadpool
// - when serialization queue is full, we abort execution for new entries
// - fetching uses a synchronous queue and therefore is a blocking operation, with a timeout
ThreadFactory storageThreadFactory = new ThreadFactoryBuilder().setNameFormat("Checkpointing-storage-%d")
.setUncaughtExceptionHandler(new UncaughtExceptionLogger("storage")).build();
storageThreadPool = new ThreadPoolExecutor(1, storageMaxThreads, storageThreadKeepAliveSeconds,
TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(storageMaxOutstandingRequests),
storageThreadFactory, new ThreadPoolExecutor.CallerRunsPolicy());
storageThreadPool.allowCoreThreadTimeOut(true);
ThreadFactory serializationThreadFactory = new ThreadFactoryBuilder()
.setNameFormat("Checkpointing-serialization-%d")
.setUncaughtExceptionHandler(new UncaughtExceptionLogger("serialization")).build();
serializationThreadPool = new ThreadPoolExecutor(1, serializationMaxThreads,
serializationThreadKeepAliveSeconds, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(
serializationMaxOutstandingRequests), serializationThreadFactory,
new ThreadPoolExecutor.AbortPolicy());
serializationThreadPool.allowCoreThreadTimeOut(true);
ThreadFactory fetchingThreadFactory = new ThreadFactoryBuilder().setNameFormat("Checkpointing-fetching-%d")
.setUncaughtExceptionHandler(new UncaughtExceptionLogger("fetching")).build();
fetchingThreadPool = new ThreadPoolExecutor(0, fetchingMaxThreads, fetchingThreadKeepAliveSeconds,
TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(fetchingQueueSize), fetchingThreadFactory);
fetchingThreadPool.allowCoreThreadTimeOut(true);