Skip to content

Instantly share code, notes, and snippets.

@alexandru
Last active September 11, 2015 11:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alexandru/3de75c350c710161dc80 to your computer and use it in GitHub Desktop.
Save alexandru/3de75c350c710161dc80 to your computer and use it in GitHub Desktop.

The context:

First of all I must say that the Scheduler in Akka, while useful for Akka's purposes, it isn't adequate as is currently to be exposed as part of Scala's standard library. As part of a project I've been working on, I have defined a Scheduler interface that inherits from ExecutionContext (it's an enhanced execution context) that has the following methods and I believe that all of them are needed:

  • def scheduleOnce(initialDelay: FiniteDuration, r: Runnable): Cancelable
  • def scheduleWithFixedDelay(initialDelay: FiniteDuration, delay: FiniteDuration, r: Runnable): Cancelable
  • def scheduleAtFixedRate(initialDelay: FiniteDuration, period: FiniteDuration, r: Runnable): Cancelable
  • def currentTimeMillis(): Long (the equivalent of calling System.currentTimeMillis)

This to have a Scheduler that's an equivalent to Java's ScheduledExecutor or to Javascript's setTimeout.

See currentTimeMillis in that list? That's also necessary because we need to "know the time" and because using System.currentTimeMillis as a singleton is really bad for testing purposes and for clarity. With this function attached to the Scheduler interface it is now possible to "mock" the time. This is how I'm doing precise testing of things depending on scheduling, because I have a TestScheduler in which the clock is being controlled by me.

I also defined the UncaughtErrorReporter because having a separate interface for that reportFailure can be very useful, as there have been instances in which I've taken an implicit ExecutionContext just so I could log unhandled errors somewhere without hard-coding.

In the process I had to define a new Cancelable, which I believe is better than the one defined in Akka. This is because:

  1. cancel() returns Boolean and the contract specifies that the operation should be idempotent and atomic. And when you cancel things, you need this to be atomic and to find out whether the current thread was the one that managed to cancel or not and you can't do that with Akka's Cancellable
  2. for isCanceled I defined a different class called BooleanCancelable because it isn't always useful to query a cancelable on whether it was canceled or not (if point 1 above is taken care of that is), plus it might not be possible to do it

And then in the Future extensions I've defined, I also introduced Future.liftTry which is extremely useful like when working with scala-async doing await on those results (as a suggestion to introduce besides transform). And a Future.withTimeout for timing out futures with a TimeoutException after a given timespan.

Which I must mention that it's tested with a shared test on both the JVM and Scala.js because of how awesome my Scheduler is (as in my mocked clock).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment