
com.intellifylearning.flush.Flusher Maven / Gradle / Ivy
package com.intellifylearning.flush;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.intellify.api.caliper.CaliperEntity;
import com.intellify.api.caliper.impl.IntellifyBase;
import com.intellifylearning.Client;
import com.intellifylearning.Constants;
import com.intellifylearning.IntellifyQueueFullException;
import com.intellifylearning.models.BatchIntellifyBase;
import com.intellifylearning.request.BlockingRequester;
import com.intellifylearning.utils.ManualResetEvent;
public class Flusher extends Thread {
private static final Logger LOG = LoggerFactory.getLogger(Constants.LOGGER);
private final LinkedBlockingQueue queue;
private final LinkedBlockingQueue queue2;
private final ManualResetEvent idle;
private final ManualResetEvent idle2;
private final Client client;
private final IBatchFactory factory;
private final BlockingRequester requester;
private final boolean errorOnQueueFull;
private final int queueWaitTimeout;
private boolean go;
public Flusher(Client client, IBatchFactory factory, BlockingRequester requester) {
this.client = client;
this.factory = factory;
this.requester = requester;
int maxQueueSize = client.getOptions().getMaxQueueSize();
this.queue = new LinkedBlockingQueue(maxQueueSize);
this.queue2 = new LinkedBlockingQueue(maxQueueSize);
this.errorOnQueueFull = client.getOptions().isErrorOnQueueFull();
this.queueWaitTimeout = client.getOptions().getQueueWaitTimeout();
this.go = true;
this.idle = new ManualResetEvent(true);
this.idle2 = new ManualResetEvent(true);
}
@Override
public void run() {
while (go) {
batchAndSendIntellifyBaseObjects();
try {
// thread context switch to avoid resource contention
Thread.sleep(0);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
LOG.error("Interrupted while sleeping flushing thread.", e);
}
}
}
/**
* Batch and send Caliper beta style events
*/
private void batchAndSendIntellifyBaseObjects() {
List current = new LinkedList();
int batchSize = getBatchSize();
do {
if (queue2.size() == 0) {
idle2.set();
}
IntellifyBase intellifyBaseEntity = null;
try {
// wait half a second for an item to appear
// otherwise yield to confirm that we aren't restarting
intellifyBaseEntity = queue2.poll(500, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
LOG.error("Interrupted while trying to flush intellisense queue for IntellifyBase objects", e);
}
if (intellifyBaseEntity != null) {
// we are no longer idle since there's messages to be
// processed
idle2.reset();
current.add(intellifyBaseEntity);
client.getStatistics().updateQueued(this.queue2.size());
}
}
// keep iterating and collecting the current batch
// while we're active, there's something in the queue, and we
// haven't already
// over-filled this batch
while (go && queue2.size() > 0
&& current.size() < batchSize);
if (current.size() > 0) {
// we have something to send in this batch
LOG.debug("Preparing to send batch of IntellifyBase objects.. [ "
+ current.size() + " items]");
BatchIntellifyBase batch = factory
.createIntellifyBaseBatch(current);
client.getStatistics().updateFlushAttempts(1);
requester.sendIntellifyBaseBatch(batch);
client.getStatistics().updateSuccessful(batch.getBatch().size());
LOG.debug("Initiated batch of IntellifyBase objects request for [ "
+ current.size() + " items]");
}
}
private int getBatchSize() {
int batchSize = Constants.BATCH_INCREMENT;
if (this.client.getOptions().getBatchSize() > 0) {
batchSize = this.client.getOptions().getBatchSize();
}
return batchSize;
}
public void enqueue(CaliperEntity payload) {
enqueue(queue, payload);
}
/**
* EntityData for Jan 2015 implementation using Caliper beta as base
*
* @param intellifyBaseObj
* data to send
*/
public void enqueue(IntellifyBase intellifyBaseObj) {
enqueue(queue2, intellifyBaseObj);
}
private void enqueue(LinkedBlockingQueue q, T obj) {
try {
boolean success;
if (errorOnQueueFull) {
success = q.offer(obj);
} else {
success = q.offer(obj, queueWaitTimeout, TimeUnit.MILLISECONDS);
}
if (!success) {
throw new IntellifyQueueFullException(
"Exceeded wait timeout of " + (errorOnQueueFull ? 0 : queueWaitTimeout)
+ "ms for intellify queue with capacity: " + client.getOptions().getMaxQueueSize());
}
client.getStatistics().updateInserted(1);
client.getStatistics().updateQueued(q.size());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IntellifyQueueFullException("Interrupted waiting on full intellify queue with capacity: "
+ client.getOptions().getMaxQueueSize());
}
}
public void flush() {
try {
idle.waitOne();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
LOG.error("Interrupted while waiting for the thread to flush.", e);
}
}
public void close() {
go = false;
queue.clear();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy