package org.sef4j.callstack.event.impl; import java.util.Collection; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import org.sef4j.callstack.event.StackEvent; import org.sef4j.callstack.event.StackEvent.CompoundPopPushStackEvent; import org.sef4j.callstack.event.StackEventListener; import org.sef4j.core.util.AsyncUtils; /** * listener of StackEvent, that bufferize events * and asynchronously (default: every 15 seconds) flush compound event to target EventLogger */ public class AsyncCompoundPushPopSenderListener extends StackEventListener { private ScheduledExecutorService scheduledExecutor; private long period; private CompoundPopPushStackEventBuilder compoundEventBuffer; private CompoundPushPopEventToEventListenerTask task; private ScheduledFuture<Void> scheduledTask; // ------------------------------------------------------------------------ public AsyncCompoundPushPopSenderListener(StackEventListener targetEventListener) { this(AsyncUtils.defaultScheduledThreadPool(), 15, targetEventListener); } public AsyncCompoundPushPopSenderListener(ScheduledExecutorService scheduledExecutor, long period, StackEventListener targetEventListener) { this.scheduledExecutor = scheduledExecutor; this.period = period; this.compoundEventBuffer = new CompoundPopPushStackEventBuilder(); this.task = new CompoundPushPopEventToEventListenerTask(compoundEventBuffer, targetEventListener); } // ------------------------------------------------------------------------ @Override public void onEvent(StackEvent event) { event.visit(compoundEventBuffer); } @Override public void onEvents(Collection<StackEvent> events) { for(StackEvent e : events) { e.visit(compoundEventBuffer); } } /** flush compound events without waiting next scheduled period */ public void flush() { task.run(); } // start/stop life-cycle management // ------------------------------------------------------------------------ public boolean isStarted() { return scheduledTask != null; } @SuppressWarnings("unchecked") public void start() { if (this.scheduledTask != null) { return; // already started } this.scheduledTask = (ScheduledFuture<Void>) scheduledExecutor.scheduleAtFixedRate(task, 0, period, TimeUnit.SECONDS); } public void stop() { if (this.scheduledTask == null) { return; // already stopped } ScheduledFuture<Void> tmp = this.scheduledTask; this.scheduledTask = null; tmp.cancel(false); } // ------------------------------------------------------------------------ /** * task for taking CompoundStackEvent from buffer, and sending to targetListener */ public static class CompoundPushPopEventToEventListenerTask implements Runnable { private CompoundPopPushStackEventBuilder compoundEventBuffer; private StackEventListener targetEventListener; // ------------------------------------------------------------------------ public CompoundPushPopEventToEventListenerTask(CompoundPopPushStackEventBuilder compoundEventBuffer, StackEventListener targetEventListener) { this.compoundEventBuffer = compoundEventBuffer; this.targetEventListener = targetEventListener; } // ------------------------------------------------------------------------ @Override public void run() { CompoundPopPushStackEvent eventOrNull = compoundEventBuffer.clearAndBuildOrNull(); if (eventOrNull != null) { targetEventListener.onEvent(eventOrNull); } } } }