package codeine; import java.util.Random; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import javax.inject.Inject; import org.apache.log4j.Logger; import codeine.db.IStatusDatabaseConnector; import codeine.jsons.global.GlobalConfigurationJsonStore; import codeine.jsons.peer_status.PeerStatus; import codeine.utils.ThreadUtils; import com.google.common.base.Stopwatch; public class PeerStatusChangedUpdater implements Runnable{ private long MAX_TIME_BETWEEN_UPDATES_MILLIS = TimeUnit.MINUTES.toMillis(5); private long MIN_TIME_BETWEEN_UPDATES_MILLIS = TimeUnit.SECONDS.toMillis(31); private long SLEEP_TIME_AFTER_FAILURE_MILLIS = TimeUnit.MINUTES.toMillis(3); private static final Logger log = Logger.getLogger(PeerStatusChangedUpdater.class); private PeerStatus peerStatus; private IStatusDatabaseConnector databaseConnector; private BlockingQueue<Object> blockingQueue = new LinkedBlockingQueue<>(); @Inject public PeerStatusChangedUpdater(PeerStatus peerStatus, IStatusDatabaseConnector databaseConnector,GlobalConfigurationJsonStore globalConfigurationJson) { super(); this.peerStatus = peerStatus; this.databaseConnector = databaseConnector; if (!globalConfigurationJson.get().large_deployment()) { log.info("configuring small deployment updates"); MIN_TIME_BETWEEN_UPDATES_MILLIS = TimeUnit.SECONDS.toMillis(5); MAX_TIME_BETWEEN_UPDATES_MILLIS = TimeUnit.SECONDS.toMillis(10); SLEEP_TIME_AFTER_FAILURE_MILLIS = MAX_TIME_BETWEEN_UPDATES_MILLIS; } } public void pushUpdate(String whoCalled) { log.info("pushUpdate called by " + whoCalled); blockingQueue.add(new Object()); } @Override public void run() { long initialSleep = (MIN_TIME_BETWEEN_UPDATES_MILLIS / 2) + new Random().nextInt((int) MIN_TIME_BETWEEN_UPDATES_MILLIS); log.info("start updating, will sleep before " + initialSleep); ThreadUtils.sleep(initialSleep); while (true){ try { pushUpdateNow(); } catch (Exception e) { log.warn("got exception, will sleep before trying more updates", e); ThreadUtils.sleep(SLEEP_TIME_AFTER_FAILURE_MILLIS); } try { ThreadUtils.sleep(MIN_TIME_BETWEEN_UPDATES_MILLIS); waitForNextUpdate(); } catch (Exception e) { log.warn("got exception", e); } } } private void waitForNextUpdate() { try { Stopwatch s = Stopwatch.createStarted(); log.debug("going to wait at most " + MAX_TIME_BETWEEN_UPDATES_MILLIS + "milli"); blockingQueue.poll(MAX_TIME_BETWEEN_UPDATES_MILLIS, TimeUnit.MILLISECONDS); log.debug("waited " + s); } catch (InterruptedException e) { log.debug("interrupted", e); } } private void pushUpdateNow() { log.info("pushing update now"); blockingQueue.clear(); databaseConnector.putReplaceStatus(peerStatus.createJson()); } }