
forklift.consumer.ConsumerThread Maven / Gradle / Ivy
package forklift.consumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Consumers need to run in their own thread so that they can spawn more
* threads to process messages. This also allows the system to isolate
* different processes.
* @author mconroy
*
*/
public class ConsumerThread extends Thread {
// Hold a lock object to allow for shutdowns during exponential backoff of reconnects.
private Object lock = new Object();
// Store a basic exponential backoff sequence.
private static final long[] expoSeq = {3, 5, 8, 13, 21, 34, 55};
private AtomicBoolean running;
private Consumer consumer;
private Logger log;
public ConsumerThread(Consumer consumer) {
super(consumer.getName());
this.running = new AtomicBoolean(false);
this.consumer = consumer;
this.log = LoggerFactory.getLogger("consumer-thread-" + consumer.getName());
}
@Override
public void run() {
running.set(true);
LocalDateTime lastConnectAttemptTime;
int connectAttempt = 0;
do {
lastConnectAttemptTime = LocalDateTime.now();
log.info("starting consumer");
try {
consumer.listen();
} catch (Exception e) {
log.debug("Couldn't get connection", e);
}
synchronized (lock) {
// If we are still running let's wait a little while and attempt to reconnect.
if (running.get()) {
// Reset connection attempts if we have been connected for longer than the max wait time.
if (LocalDateTime.now().isAfter(lastConnectAttemptTime.plus(expoSeq[expoSeq.length - 1], ChronoUnit.SECONDS)))
connectAttempt = 0;
try {
log.info("unexpected consumer shutdown - trying reconnect in {} seconds", expoSeq[connectAttempt]);
lock.wait(expoSeq[connectAttempt] * 1000);
// Never let the attempt number get bigger than the greatest backoff sequence number.
connectAttempt = Math.min(connectAttempt + 1, expoSeq.length - 1);
} catch (InterruptedException ignored) {
log.error("", ignored);
}
}
}
} while (running.get());
}
public void shutdown() {
// Jump us out of any exponential backoff wait we might be in.
synchronized (lock) {
lock.notify();
consumer.shutdown();
running.set(false);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy