diff --git a/akka-actor-tests/src/test/scala/akka/actor/SchedulerSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/SchedulerSpec.scala index 84dcdcc90f..0008c14e25 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/SchedulerSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/SchedulerSpec.scala @@ -17,6 +17,7 @@ import org.scalatest.BeforeAndAfterEach import com.typesafe.config.{ Config, ConfigFactory } import akka.pattern.ask import akka.testkit._ +import scala.util.control.NoStackTrace object SchedulerSpec { val testConfRevolver = ConfigFactory.parseString(""" @@ -78,6 +79,19 @@ trait SchedulerSpec extends BeforeAndAfterEach with DefaultTimeout with Implicit expectNoMsg(500 millis) } + "stop continuous scheduling if the task throws exception" taggedAs TimingTest in { + val count = new AtomicInteger(0) + collectCancellable(system.scheduler.schedule(0 milliseconds, 20.millis) { + val c = count.incrementAndGet() + testActor ! c + if (c == 3) throw new RuntimeException("TEST") with NoStackTrace + }) + expectMsg(1) + expectMsg(2) + expectMsg(3) + expectNoMsg(500 millis) + } + "schedule once" taggedAs TimingTest in { case object Tick val countDownLatch = new CountDownLatch(3) diff --git a/akka-actor/src/main/scala/akka/actor/Scheduler.scala b/akka-actor/src/main/scala/akka/actor/Scheduler.scala index 61f6fbf22f..8fb6c7e884 100644 --- a/akka-actor/src/main/scala/akka/actor/Scheduler.scala +++ b/akka-actor/src/main/scala/akka/actor/Scheduler.scala @@ -74,6 +74,9 @@ trait Scheduler { * of the function executions). In such cases, the actual execution interval * will differ from the interval passed to this method. * + * If the function throws an exception the repeated scheduling is aborted, + * i.e. the function will not be invoked any more. + * * Scala API */ final def schedule( @@ -83,7 +86,7 @@ trait Scheduler { schedule(initialDelay, interval, new Runnable { override def run = f }) /** - * Schedules a function to be run repeatedly with an initial delay and + * Schedules a `Runnable` to be run repeatedly with an initial delay and * a frequency. E.g. if you would like the function to be run after 2 * seconds and thereafter every 100ms you would set delay = Duration(2, * TimeUnit.SECONDS) and interval = Duration(100, TimeUnit.MILLISECONDS). If @@ -93,6 +96,8 @@ trait Scheduler { * the actual execution interval will differ from the interval passed to this * method. * + * If the `Runnable` throws an exception the repeated scheduling is aborted, + * i.e. the function will not be invoked any more. * * Java API */ @@ -287,6 +292,10 @@ class LightArrayRevolverScheduler(config: Config, case SchedulerException(msg) ⇒ throw new IllegalStateException(msg) } + /** + * Shutdown the scheduler. All scheduled task will be executed when the scheduler closed, + * i.e. the task may execute before its timeout. + */ override def close(): Unit = Await.result(stop(), getShutdownTimeout) foreach { task ⇒ try task.run() catch { @@ -372,7 +381,7 @@ class LightArrayRevolverScheduler(config: Config, tickNanos - 1 // rounding up ) / tickNanos).toInt // and converting to slot number // tick is an Int that will wrap around, but toInt of futureTick gives us modulo operations - // and the difference (offset) will be correct in any case + // and the difference (offset) will be correct in any case val offset = futureTick - tick val bucket = futureTick & wheelMask node.value.ticks = offset diff --git a/akka-docs/rst/java/scheduler.rst b/akka-docs/rst/java/scheduler.rst index 798ae5863b..ad2a02ed92 100644 --- a/akka-docs/rst/java/scheduler.rst +++ b/akka-docs/rst/java/scheduler.rst @@ -62,6 +62,10 @@ From ``akka.actor.ActorSystem`` .. includecode:: ../../../akka-actor/src/main/scala/akka/actor/ActorSystem.scala :include: scheduler +.. warning:: + + All scheduled task will be executed when the ``ActorSystem`` is terminated, i.e. + the task may execute before its timeout. The Scheduler Interface for Implementors ---------------------------------------- diff --git a/akka-docs/rst/scala/scheduler.rst b/akka-docs/rst/scala/scheduler.rst index 25d97cde7c..62667df27e 100644 --- a/akka-docs/rst/scala/scheduler.rst +++ b/akka-docs/rst/scala/scheduler.rst @@ -50,6 +50,10 @@ From ``akka.actor.ActorSystem`` .. includecode:: ../../../akka-actor/src/main/scala/akka/actor/ActorSystem.scala :include: scheduler +.. warning:: + + All scheduled task will be executed when the ``ActorSystem`` is terminated, i.e. + the task may execute before its timeout. The Scheduler interface -----------------------