title: Non-Blocking Timer Tasks and Akka Actors
body: <p><strong>Please note:</strong> Although I'd <em>prefer</em> a solution using Akka's Java API (which is what I'm using), I'm happy with any working solution and can probably figure out how to translate Scala-based answers into Java-land.</p>
  
  <hr>
  
  <p>I have an Akka app that has many actors, two of which are <code>Fizz</code> and <code>Buzz</code>. The <code>Fizz</code> actor can accept 2 types of messages:</p>
  
  <ul>
  <li><code>StartNewTimerTask</code>; and</li>
  <li><code>ResetAllTimerTasks</code></li>
  </ul>
  
  <p>The <code>Buzz</code> actor simply accepts a <code>DoItNow</code> message. The message flow between these actors and the rest of the system is as follows:</p>
  
  <ol>
  <li>Anything (other actors, even event-driven components <em>outside</em> the actor system) can send <code>StartNewTimerTask</code> messages to the <code>Fizz</code> actor at any time</li>
  <li>Each time the <code>Fizz</code> actor receives a <code>StartNewTimerTask</code> message, it creates and starts a new asynchronous/non-blocking timer that <em>attempts</em> to run for, say, 8 seconds. If the timer gets to the end (8 seconds) then a <code>DoItNow</code> message is sent to the <code>Buzz</code> actor</li>
  <li>The <code>Fizz</code> actor can accept any number of concurrent <code>StartNewTimerTask</code> messages, and as such, can be "managing" potentially multiple timers at the same time, with each one counting towards that 8-second magical number. Hence if 20 other actors send <code>StartNewTimerTask</code> messages to the <code>Fizz</code> actor all within a few seconds of each other, then the <code>Fizz</code> actor would be "managing" 20 non-blocking, independent timers at the same time. And when each of those 20 timers reaches their respective 8-second duration, they send 20 independent <code>DoItNow</code> messages to the <code>Buzz</code> actor</li>
  <li>When the <code>Fizz</code> actor receives a <code>ResetAllTimerTasks</code> message, <em>any</em> timers that are currently "in progress" will be interrupted/cancelled (so that they stop counting down to the 8-second duration, thus preventing them from sending a <code>DoItNow</code> message to <code>Buzz</code>). Hence, borrowing from our example above, if between times <code>t=1</code> and <code>t=3</code> the <code>Fizz</code> actor received 20 <code>StartNewTimerTask</code> messages, then at <code>t=10</code> perhaps 14 of their respective timers would have elapsed and fired <code>DoItNow</code> messages, and perhaps 6 would still be in progress. If at that exact moment <code>Fizz</code> received a <code>ResetAllTimerTasks</code> message, it would stop those 6 timers from elapsing and firing messages, and so in this example <code>Buzz</code> would only receive 14 <code>DoItNow</code> messages</li>
  </ol>
  
  <p>I know that the Java 8 API (sans Akka) advocates extending <code>TimerTask</code> and submitting these tasks to the <code>Timer#scheduleAtFixedRate</code> method, but I'm not sure if that conflicts with Akka at all or if there is a better way to implement this functionality with the Akka API. My best attempt thus far:</p>
  
  <pre><code>// Groovy pseudo-code
  class MyTimerTask extends TimerTask {
    @Inject
    ActorRef buzz
  
    @Override
    void run() {
      // No op!
    }
  
    void completeTask() {
      buzz.tell(new DoItNow(), null)
    }
  }
  
  class Fizz extends UntypedAbstractActor {
    @Inject
    Timer timer
  
    @Override
    void onReceive(Object message) {
      if(message in StartNewTimerTask) {
        timer.scheduleAtFixedRate(new MyTimerTask(), 0, 8 * 1000)
      } else if(message in ResetAllTimerTasks) {
        timer.cancel()
      }
    }
  }
  
  class Buzz extends UntypedAbstractActor {
    @Override
    void onReceive(Object message) {
      if(message in DoItNow) {
        // Do something super cool now...
      }
    }
  }
  </code></pre>
  
  <p>However I don't think I'm managing timers correctly or tapping into the full potential of the Akka scheduler/timer API. <strong>Any thoughts?</strong></p>