The context:
- scala/docs.scala-lang#295
- https://docs.google.com/document/d/1Vza2-B3FzgtleX8RNs6rqRbhOn9jotrUfFB77h0DIGU/edit?hl=en_US#heading=h.bu8cg3api4vx
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): Cancelabledef scheduleWithFixedDelay(initialDelay: FiniteDuration, delay: FiniteDuration, r: Runnable): Cancelabledef scheduleAtFixedRate(initialDelay: FiniteDuration, period: FiniteDuration, r: Runnable): Cancelabledef currentTimeMillis(): Long(the equivalent of callingSystem.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:
cancel()returnsBooleanand 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'sCancellable- for
isCanceledI 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).