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): 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 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()
returnsBoolean
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'sCancellable
- 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).