parent
b208265e5c
commit
4081638fd8
10 changed files with 371 additions and 22 deletions
|
|
@ -214,14 +214,20 @@ object Effect {
|
||||||
}
|
}
|
||||||
|
|
||||||
object TimerScheduled {
|
object TimerScheduled {
|
||||||
|
import akka.util.JavaDurationConverters._
|
||||||
|
|
||||||
sealed trait TimerMode
|
sealed trait TimerMode
|
||||||
case object FixedRateMode extends TimerMode
|
case object FixedRateMode extends TimerMode
|
||||||
|
case class FixedRateModeWithInitialDelay(initialDelay: FiniteDuration) extends TimerMode
|
||||||
case object FixedDelayMode extends TimerMode
|
case object FixedDelayMode extends TimerMode
|
||||||
|
case class FixedDelayModeWithInitialDelay(initialDelay: FiniteDuration) extends TimerMode
|
||||||
case object SingleMode extends TimerMode
|
case object SingleMode extends TimerMode
|
||||||
|
|
||||||
/*Java API*/
|
/*Java API*/
|
||||||
def fixedRateMode = FixedRateMode
|
def fixedRateMode = FixedRateMode
|
||||||
|
def fixedRateMode(initialDelay: java.time.Duration) = FixedRateModeWithInitialDelay(initialDelay.asScala)
|
||||||
def fixedDelayMode = FixedDelayMode
|
def fixedDelayMode = FixedDelayMode
|
||||||
|
def fixedDelayMode(initialDelay: java.time.Duration) = FixedDelayModeWithInitialDelay(initialDelay.asScala)
|
||||||
def singleMode = SingleMode
|
def singleMode = SingleMode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -91,9 +91,15 @@ import scala.reflect.ClassTag
|
||||||
override def startTimerWithFixedDelay(key: Any, msg: T, delay: FiniteDuration): Unit =
|
override def startTimerWithFixedDelay(key: Any, msg: T, delay: FiniteDuration): Unit =
|
||||||
startTimer(key, msg, delay, Effect.TimerScheduled.FixedDelayMode)
|
startTimer(key, msg, delay, Effect.TimerScheduled.FixedDelayMode)
|
||||||
|
|
||||||
|
override def startTimerWithFixedDelay(key: Any, msg: T, initialDelay: FiniteDuration, delay: FiniteDuration): Unit =
|
||||||
|
startTimer(key, msg, delay, Effect.TimerScheduled.FixedDelayModeWithInitialDelay(initialDelay))
|
||||||
|
|
||||||
override def startTimerAtFixedRate(key: Any, msg: T, interval: FiniteDuration): Unit =
|
override def startTimerAtFixedRate(key: Any, msg: T, interval: FiniteDuration): Unit =
|
||||||
startTimer(key, msg, interval, Effect.TimerScheduled.FixedRateMode)
|
startTimer(key, msg, interval, Effect.TimerScheduled.FixedRateMode)
|
||||||
|
|
||||||
|
override def startTimerAtFixedRate(key: Any, msg: T, initialDelay: FiniteDuration, interval: FiniteDuration): Unit =
|
||||||
|
startTimer(key, msg, interval, Effect.TimerScheduled.FixedRateModeWithInitialDelay(initialDelay))
|
||||||
|
|
||||||
override def startPeriodicTimer(key: Any, msg: T, interval: FiniteDuration): Unit =
|
override def startPeriodicTimer(key: Any, msg: T, interval: FiniteDuration): Unit =
|
||||||
startTimer(key, msg, interval, Effect.TimerScheduled.FixedRateMode)
|
startTimer(key, msg, interval, Effect.TimerScheduled.FixedRateMode)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -123,8 +123,12 @@ object BehaviorTestKitSpec {
|
||||||
case ScheduleCommand(key, delay, mode, cmd) =>
|
case ScheduleCommand(key, delay, mode, cmd) =>
|
||||||
mode match {
|
mode match {
|
||||||
case Effect.TimerScheduled.SingleMode => timers.startSingleTimer(key, cmd, delay)
|
case Effect.TimerScheduled.SingleMode => timers.startSingleTimer(key, cmd, delay)
|
||||||
case Effect.TimerScheduled.FixedDelayMode => timers.startTimerWithFixedDelay(key, cmd, delay)
|
case Effect.TimerScheduled.FixedDelayMode => timers.startTimerWithFixedDelay(key, cmd, delay, delay)
|
||||||
case Effect.TimerScheduled.FixedRateMode => timers.startTimerAtFixedRate(key, cmd, delay)
|
case m: Effect.TimerScheduled.FixedDelayModeWithInitialDelay =>
|
||||||
|
timers.startTimerWithFixedDelay(key, cmd, m.initialDelay, delay)
|
||||||
|
case Effect.TimerScheduled.FixedRateMode => timers.startTimerAtFixedRate(key, cmd, delay, delay)
|
||||||
|
case m: Effect.TimerScheduled.FixedRateModeWithInitialDelay =>
|
||||||
|
timers.startTimerAtFixedRate(key, cmd, m.initialDelay, delay)
|
||||||
}
|
}
|
||||||
Behaviors.same
|
Behaviors.same
|
||||||
case CancelScheduleCommand(key) =>
|
case CancelScheduleCommand(key) =>
|
||||||
|
|
@ -445,16 +449,17 @@ class BehaviorTestKitSpec extends AnyWordSpec with Matchers with LogCapturing {
|
||||||
}
|
}
|
||||||
|
|
||||||
"schedule and fire timers multiple times" in {
|
"schedule and fire timers multiple times" in {
|
||||||
|
val delay = 42.seconds
|
||||||
val testkit = BehaviorTestKit[Parent.Command](Parent.init)
|
val testkit = BehaviorTestKit[Parent.Command](Parent.init)
|
||||||
testkit.run(ScheduleCommand("abc", 42.seconds, Effect.TimerScheduled.FixedRateMode, SpawnChild))
|
testkit.run(ScheduleCommand("abc", delay, Effect.TimerScheduled.FixedRateMode, SpawnChild))
|
||||||
val send = testkit.expectEffectPF {
|
val send = testkit.expectEffectPF {
|
||||||
case e @ Effect.TimerScheduled(
|
case e @ Effect.TimerScheduled(
|
||||||
"abc",
|
"abc",
|
||||||
SpawnChild,
|
SpawnChild,
|
||||||
finiteDuration,
|
finiteDuration,
|
||||||
Effect.TimerScheduled.FixedRateMode,
|
Effect.TimerScheduled.FixedRateModeWithInitialDelay(`delay`),
|
||||||
false /*not overriding*/ ) =>
|
false /*not overriding*/ ) =>
|
||||||
finiteDuration should equal(42.seconds)
|
finiteDuration should equal(delay)
|
||||||
e.send
|
e.send
|
||||||
}
|
}
|
||||||
send()
|
send()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
# marked with @DoNotInherit
|
||||||
|
ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.actor.typed.javadsl.TimerScheduler.startTimerWithFixedDelay")
|
||||||
|
ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.actor.typed.javadsl.TimerScheduler.startTimerAtFixedRate")
|
||||||
|
ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.actor.typed.scaladsl.TimerScheduler.startTimerWithFixedDelay")
|
||||||
|
ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.actor.typed.scaladsl.TimerScheduler.startTimerAtFixedRate")
|
||||||
|
# marked with @InternalApi
|
||||||
|
ProblemFilters.exclude[MissingTypesProblem]("akka.actor.typed.internal.TimerSchedulerImpl$FixedRateMode$")
|
||||||
|
ProblemFilters.exclude[DirectMissingMethodProblem]("akka.actor.typed.internal.TimerSchedulerImpl#FixedRateMode.*")
|
||||||
|
ProblemFilters.exclude[FinalMethodProblem]("akka.actor.typed.internal.TimerSchedulerImpl#FixedRateMode.toString")
|
||||||
|
ProblemFilters.exclude[MissingTypesProblem]("akka.actor.typed.internal.TimerSchedulerImpl$FixedDelayMode$")
|
||||||
|
ProblemFilters.exclude[DirectMissingMethodProblem]("akka.actor.typed.internal.TimerSchedulerImpl#FixedDelayMode.*")
|
||||||
|
ProblemFilters.exclude[FinalMethodProblem]("akka.actor.typed.internal.TimerSchedulerImpl#FixedDelayMode.toString")
|
||||||
|
|
@ -40,10 +40,10 @@ import scala.concurrent.duration.FiniteDuration
|
||||||
private sealed trait TimerMode {
|
private sealed trait TimerMode {
|
||||||
def repeat: Boolean
|
def repeat: Boolean
|
||||||
}
|
}
|
||||||
private case object FixedRateMode extends TimerMode {
|
private case class FixedRateMode(initialDelay: FiniteDuration) extends TimerMode {
|
||||||
override def repeat: Boolean = true
|
override def repeat: Boolean = true
|
||||||
}
|
}
|
||||||
private case object FixedDelayMode extends TimerMode {
|
private case class FixedDelayMode(initialDelay: FiniteDuration) extends TimerMode {
|
||||||
override def repeat: Boolean = true
|
override def repeat: Boolean = true
|
||||||
}
|
}
|
||||||
private case object SingleMode extends TimerMode {
|
private case object SingleMode extends TimerMode {
|
||||||
|
|
@ -59,9 +59,15 @@ import scala.concurrent.duration.FiniteDuration
|
||||||
override final def startTimerWithFixedDelay(key: Any, msg: T, delay: Duration): Unit =
|
override final def startTimerWithFixedDelay(key: Any, msg: T, delay: Duration): Unit =
|
||||||
startTimerWithFixedDelay(key, msg, delay.asScala)
|
startTimerWithFixedDelay(key, msg, delay.asScala)
|
||||||
|
|
||||||
|
override final def startTimerWithFixedDelay(key: Any, msg: T, initialDelay: Duration, delay: Duration): Unit =
|
||||||
|
startTimerWithFixedDelay(key, msg, initialDelay.asScala, delay.asScala)
|
||||||
|
|
||||||
override final def startTimerAtFixedRate(key: Any, msg: T, interval: Duration): Unit =
|
override final def startTimerAtFixedRate(key: Any, msg: T, interval: Duration): Unit =
|
||||||
startTimerAtFixedRate(key, msg, interval.asScala)
|
startTimerAtFixedRate(key, msg, interval.asScala)
|
||||||
|
|
||||||
|
override final def startTimerAtFixedRate(key: Any, msg: T, initialDelay: Duration, interval: Duration): Unit =
|
||||||
|
startTimerAtFixedRate(key, msg, initialDelay.asScala, interval.asScala)
|
||||||
|
|
||||||
override final def startPeriodicTimer(key: Any, msg: T, interval: Duration): Unit = {
|
override final def startPeriodicTimer(key: Any, msg: T, interval: Duration): Unit = {
|
||||||
//this follows the deprecation note in the super class
|
//this follows the deprecation note in the super class
|
||||||
startTimerWithFixedDelay(key, msg, interval.asScala)
|
startTimerWithFixedDelay(key, msg, interval.asScala)
|
||||||
|
|
@ -83,13 +89,19 @@ import scala.concurrent.duration.FiniteDuration
|
||||||
private val timerGen = Iterator.from(1)
|
private val timerGen = Iterator.from(1)
|
||||||
|
|
||||||
override def startTimerAtFixedRate(key: Any, msg: T, interval: FiniteDuration): Unit =
|
override def startTimerAtFixedRate(key: Any, msg: T, interval: FiniteDuration): Unit =
|
||||||
startTimer(key, msg, interval, FixedRateMode)
|
startTimer(key, msg, interval, FixedRateMode(interval))
|
||||||
|
|
||||||
|
override def startTimerAtFixedRate(key: Any, msg: T, initialDelay: FiniteDuration, interval: FiniteDuration): Unit =
|
||||||
|
startTimer(key, msg, interval, FixedRateMode(initialDelay))
|
||||||
|
|
||||||
override def startTimerWithFixedDelay(key: Any, msg: T, delay: FiniteDuration): Unit =
|
override def startTimerWithFixedDelay(key: Any, msg: T, delay: FiniteDuration): Unit =
|
||||||
startTimer(key, msg, delay, FixedDelayMode)
|
startTimer(key, msg, delay, FixedDelayMode(delay))
|
||||||
|
|
||||||
|
override def startTimerWithFixedDelay(key: Any, msg: T, initialDelay: FiniteDuration, delay: FiniteDuration): Unit =
|
||||||
|
startTimer(key, msg, delay, FixedDelayMode(initialDelay))
|
||||||
|
|
||||||
override def startPeriodicTimer(key: Any, msg: T, interval: FiniteDuration): Unit =
|
override def startPeriodicTimer(key: Any, msg: T, interval: FiniteDuration): Unit =
|
||||||
startTimer(key, msg, interval, FixedRateMode)
|
startTimer(key, msg, interval, FixedRateMode(interval))
|
||||||
|
|
||||||
override def startSingleTimer(key: Any, msg: T, delay: FiniteDuration): Unit =
|
override def startSingleTimer(key: Any, msg: T, delay: FiniteDuration): Unit =
|
||||||
startTimer(key, msg, delay, SingleMode)
|
startTimer(key, msg, delay, SingleMode)
|
||||||
|
|
@ -110,11 +122,11 @@ import scala.concurrent.duration.FiniteDuration
|
||||||
val task = mode match {
|
val task = mode match {
|
||||||
case SingleMode =>
|
case SingleMode =>
|
||||||
ctx.system.scheduler.scheduleOnce(delay, () => ctx.self.unsafeUpcast ! timerMsg)(ExecutionContexts.parasitic)
|
ctx.system.scheduler.scheduleOnce(delay, () => ctx.self.unsafeUpcast ! timerMsg)(ExecutionContexts.parasitic)
|
||||||
case FixedDelayMode =>
|
case m: FixedDelayMode =>
|
||||||
ctx.system.scheduler.scheduleWithFixedDelay(delay, delay)(() => ctx.self.unsafeUpcast ! timerMsg)(
|
ctx.system.scheduler.scheduleWithFixedDelay(m.initialDelay, delay)(() => ctx.self.unsafeUpcast ! timerMsg)(
|
||||||
ExecutionContexts.parasitic)
|
ExecutionContexts.parasitic)
|
||||||
case FixedRateMode =>
|
case m: FixedRateMode =>
|
||||||
ctx.system.scheduler.scheduleAtFixedRate(delay, delay)(() => ctx.self.unsafeUpcast ! timerMsg)(
|
ctx.system.scheduler.scheduleAtFixedRate(m.initialDelay, delay)(() => ctx.self.unsafeUpcast ! timerMsg)(
|
||||||
ExecutionContexts.parasitic)
|
ExecutionContexts.parasitic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,24 @@ trait TimerScheduler[T] {
|
||||||
*/
|
*/
|
||||||
def startTimerWithFixedDelay(key: Any, msg: T, delay: java.time.Duration): Unit
|
def startTimerWithFixedDelay(key: Any, msg: T, delay: java.time.Duration): Unit
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a message to be sent repeatedly to the `self` actor with a
|
||||||
|
* fixed `delay` between messages after `initialDelay`.
|
||||||
|
*
|
||||||
|
* It will not compensate the delay between messages if scheduling is delayed
|
||||||
|
* longer than specified for some reason. The delay between sending of subsequent
|
||||||
|
* messages will always be (at least) the given `delay`.
|
||||||
|
*
|
||||||
|
* In the long run, the frequency of messages will generally be slightly lower than
|
||||||
|
* the reciprocal of the specified `delay`.
|
||||||
|
*
|
||||||
|
* Each timer has a key and if a new timer with same key is started
|
||||||
|
* the previous is cancelled. It is guaranteed that a message from the
|
||||||
|
* previous timer is not received, even if it was already enqueued
|
||||||
|
* in the mailbox when the new timer was started.
|
||||||
|
*/
|
||||||
|
def startTimerWithFixedDelay(key: Any, msg: T, initialDelay: java.time.Duration, delay: java.time.Duration): Unit
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Schedules a message to be sent repeatedly to the `self` actor with a
|
* Schedules a message to be sent repeatedly to the `self` actor with a
|
||||||
* fixed `delay` between messages.
|
* fixed `delay` between messages.
|
||||||
|
|
@ -60,6 +78,26 @@ trait TimerScheduler[T] {
|
||||||
def startTimerWithFixedDelay(msg: T, delay: java.time.Duration): Unit =
|
def startTimerWithFixedDelay(msg: T, delay: java.time.Duration): Unit =
|
||||||
startTimerWithFixedDelay(msg, msg, delay)
|
startTimerWithFixedDelay(msg, msg, delay)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a message to be sent repeatedly to the `self` actor with a
|
||||||
|
* fixed `delay` between messages after `initialDelay`.
|
||||||
|
*
|
||||||
|
* It will not compensate the delay between messages if scheduling is delayed
|
||||||
|
* longer than specified for some reason. The delay between sending of subsequent
|
||||||
|
* messages will always be (at least) the given `delay`.
|
||||||
|
*
|
||||||
|
* In the long run, the frequency of messages will generally be slightly lower than
|
||||||
|
* the reciprocal of the specified `delay`.
|
||||||
|
*
|
||||||
|
* When a new timer is started with the same message,
|
||||||
|
* the previous is cancelled. It is guaranteed that a message from the
|
||||||
|
* previous timer is not received, even if it was already enqueued
|
||||||
|
* in the mailbox when the new timer was started. If you do not want this,
|
||||||
|
* you can start start them as individual timers by specifying distinct keys.
|
||||||
|
*/
|
||||||
|
def startTimerWithFixedDelay(msg: T, initialDelay: java.time.Duration, delay: java.time.Duration): Unit =
|
||||||
|
startTimerWithFixedDelay(msg, msg, initialDelay, delay)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Schedules a message to be sent repeatedly to the `self` actor with a
|
* Schedules a message to be sent repeatedly to the `self` actor with a
|
||||||
* given frequency.
|
* given frequency.
|
||||||
|
|
@ -87,6 +125,33 @@ trait TimerScheduler[T] {
|
||||||
*/
|
*/
|
||||||
def startTimerAtFixedRate(key: Any, msg: T, interval: java.time.Duration): Unit
|
def startTimerAtFixedRate(key: Any, msg: T, interval: java.time.Duration): Unit
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a message to be sent repeatedly to the `self` actor with a
|
||||||
|
* given frequency.
|
||||||
|
*
|
||||||
|
* It will compensate the delay for a subsequent message if the sending of previous
|
||||||
|
* message was delayed more than specified. In such cases, the actual message interval
|
||||||
|
* will differ from the interval passed to the method.
|
||||||
|
*
|
||||||
|
* If the execution is delayed longer than the `interval`, the subsequent message will
|
||||||
|
* be sent immediately after the prior one. This also has the consequence that after
|
||||||
|
* long garbage collection pauses or other reasons when the JVM was suspended all
|
||||||
|
* "missed" messages will be sent when the process wakes up again.
|
||||||
|
*
|
||||||
|
* In the long run, the frequency of messages will be exactly the reciprocal of the
|
||||||
|
* specified `interval` after `initialDelay`.
|
||||||
|
*
|
||||||
|
* Warning: `startTimerAtFixedRate` can result in bursts of scheduled messages after long
|
||||||
|
* garbage collection pauses, which may in worst case cause undesired load on the system.
|
||||||
|
* Therefore `startTimerWithFixedDelay` is often preferred.
|
||||||
|
*
|
||||||
|
* Each timer has a key and if a new timer with same key is started
|
||||||
|
* the previous is cancelled. It is guaranteed that a message from the
|
||||||
|
* previous timer is not received, even if it was already enqueued
|
||||||
|
* in the mailbox when the new timer was started.
|
||||||
|
*/
|
||||||
|
def startTimerAtFixedRate(key: Any, msg: T, initialDelay: java.time.Duration, interval: java.time.Duration): Unit
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Schedules a message to be sent repeatedly to the `self` actor with a
|
* Schedules a message to be sent repeatedly to the `self` actor with a
|
||||||
* given frequency.
|
* given frequency.
|
||||||
|
|
@ -116,6 +181,35 @@ trait TimerScheduler[T] {
|
||||||
def startTimerAtFixedRate(msg: T, interval: java.time.Duration): Unit =
|
def startTimerAtFixedRate(msg: T, interval: java.time.Duration): Unit =
|
||||||
startTimerAtFixedRate(msg, msg, interval)
|
startTimerAtFixedRate(msg, msg, interval)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a message to be sent repeatedly to the `self` actor with a
|
||||||
|
* given frequency.
|
||||||
|
*
|
||||||
|
* It will compensate the delay for a subsequent message if the sending of previous
|
||||||
|
* message was delayed more than specified. In such cases, the actual message interval
|
||||||
|
* will differ from the interval passed to the method.
|
||||||
|
*
|
||||||
|
* If the execution is delayed longer than the `interval`, the subsequent message will
|
||||||
|
* be sent immediately after the prior one. This also has the consequence that after
|
||||||
|
* long garbage collection pauses or other reasons when the JVM was suspended all
|
||||||
|
* "missed" messages will be sent when the process wakes up again.
|
||||||
|
*
|
||||||
|
* In the long run, the frequency of messages will be exactly the reciprocal of the
|
||||||
|
* specified `interval` after `initialDelay`.
|
||||||
|
*
|
||||||
|
* Warning: `startTimerAtFixedRate` can result in bursts of scheduled messages after long
|
||||||
|
* garbage collection pauses, which may in worst case cause undesired load on the system.
|
||||||
|
* Therefore `startTimerWithFixedDelay` is often preferred.
|
||||||
|
*
|
||||||
|
* When a new timer is started with the same message,
|
||||||
|
* the previous is cancelled. It is guaranteed that a message from the
|
||||||
|
* previous timer is not received, even if it was already enqueued
|
||||||
|
* in the mailbox when the new timer was started. If you do not want this,
|
||||||
|
* you can start start them as individual timers by specifying distinct keys.
|
||||||
|
*/
|
||||||
|
def startTimerAtFixedRate(msg: T, initialDelay: java.time.Duration, interval: java.time.Duration): Unit =
|
||||||
|
startTimerAtFixedRate(msg, msg, initialDelay, interval)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deprecated API: See [[TimerScheduler#startTimerWithFixedDelay]] or [[TimerScheduler#startTimerAtFixedRate]].
|
* Deprecated API: See [[TimerScheduler#startTimerWithFixedDelay]] or [[TimerScheduler#startTimerAtFixedRate]].
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,24 @@ trait TimerScheduler[T] {
|
||||||
*/
|
*/
|
||||||
def startTimerWithFixedDelay(key: Any, msg: T, delay: FiniteDuration): Unit
|
def startTimerWithFixedDelay(key: Any, msg: T, delay: FiniteDuration): Unit
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a message to be sent repeatedly to the `self` actor with a
|
||||||
|
* fixed `delay` between messages after the `initialDelay`.
|
||||||
|
*
|
||||||
|
* It will not compensate the delay between messages if scheduling is delayed
|
||||||
|
* longer than specified for some reason. The delay between sending of subsequent
|
||||||
|
* messages will always be (at least) the given `delay`.
|
||||||
|
*
|
||||||
|
* In the long run, the frequency of messages will generally be slightly lower than
|
||||||
|
* the reciprocal of the specified `delay`.
|
||||||
|
*
|
||||||
|
* Each timer has a key and if a new timer with same key is started
|
||||||
|
* the previous is cancelled. It is guaranteed that a message from the
|
||||||
|
* previous timer is not received, even if it was already be enqueued
|
||||||
|
* in the mailbox before the new timer was started.
|
||||||
|
*/
|
||||||
|
def startTimerWithFixedDelay(key: Any, msg: T, initialDelay: FiniteDuration, delay: FiniteDuration): Unit
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Schedules a message to be sent repeatedly to the `self` actor with a
|
* Schedules a message to be sent repeatedly to the `self` actor with a
|
||||||
* fixed `delay` between messages.
|
* fixed `delay` between messages.
|
||||||
|
|
@ -60,6 +78,26 @@ trait TimerScheduler[T] {
|
||||||
def startTimerWithFixedDelay(msg: T, delay: FiniteDuration): Unit =
|
def startTimerWithFixedDelay(msg: T, delay: FiniteDuration): Unit =
|
||||||
startTimerWithFixedDelay(msg, msg, delay)
|
startTimerWithFixedDelay(msg, msg, delay)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a message to be sent repeatedly to the `self` actor with a
|
||||||
|
* fixed `delay` between messages after the `initialDelay`.
|
||||||
|
*
|
||||||
|
* It will not compensate the delay between messages if scheduling is delayed
|
||||||
|
* longer than specified for some reason. The delay between sending of subsequent
|
||||||
|
* messages will always be (at least) the given `delay`.
|
||||||
|
*
|
||||||
|
* In the long run, the frequency of messages will generally be slightly lower than
|
||||||
|
* the reciprocal of the specified `delay`.
|
||||||
|
*
|
||||||
|
* When a new timer is started with the same message,
|
||||||
|
* the previous is cancelled. It is guaranteed that a message from the
|
||||||
|
* previous timer is not received, even if it was already enqueued
|
||||||
|
* in the mailbox when the new timer was started. If you do not want this,
|
||||||
|
* you can start start them as individual timers by specifying distinct keys.
|
||||||
|
*/
|
||||||
|
def startTimerWithFixedDelay(msg: T, initialDelay: FiniteDuration, delay: FiniteDuration): Unit =
|
||||||
|
startTimerWithFixedDelay(msg, msg, initialDelay, delay)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Schedules a message to be sent repeatedly to the `self` actor with a
|
* Schedules a message to be sent repeatedly to the `self` actor with a
|
||||||
* given frequency.
|
* given frequency.
|
||||||
|
|
@ -87,6 +125,33 @@ trait TimerScheduler[T] {
|
||||||
*/
|
*/
|
||||||
def startTimerAtFixedRate(key: Any, msg: T, interval: FiniteDuration): Unit
|
def startTimerAtFixedRate(key: Any, msg: T, interval: FiniteDuration): Unit
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a message to be sent repeatedly to the `self` actor with a
|
||||||
|
* given frequency.
|
||||||
|
*
|
||||||
|
* It will compensate the delay for a subsequent message if the sending of previous
|
||||||
|
* message was delayed more than specified. In such cases, the actual message interval
|
||||||
|
* will differ from the interval passed to the method.
|
||||||
|
*
|
||||||
|
* If the execution is delayed longer than the `interval`, the subsequent message will
|
||||||
|
* be sent immediately after the prior one. This also has the consequence that after
|
||||||
|
* long garbage collection pauses or other reasons when the JVM was suspended all
|
||||||
|
* "missed" messages will be sent when the process wakes up again.
|
||||||
|
*
|
||||||
|
* In the long run, the frequency of messages will be exactly the reciprocal of the
|
||||||
|
* specified `interval` after `initialDelay`.
|
||||||
|
*
|
||||||
|
* Warning: `startTimerAtFixedRate` can result in bursts of scheduled messages after long
|
||||||
|
* garbage collection pauses, which may in worst case cause undesired load on the system.
|
||||||
|
* Therefore `startTimerWithFixedDelay` is often preferred.
|
||||||
|
*
|
||||||
|
* Each timer has a key and if a new timer with same key is started
|
||||||
|
* the previous is cancelled. It is guaranteed that a message from the
|
||||||
|
* previous timer is not received, even if it was already enqueued
|
||||||
|
* in the mailbox when the new timer was started.
|
||||||
|
*/
|
||||||
|
def startTimerAtFixedRate(key: Any, msg: T, initialDelay: FiniteDuration, interval: FiniteDuration): Unit
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Schedules a message to be sent repeatedly to the `self` actor with a
|
* Schedules a message to be sent repeatedly to the `self` actor with a
|
||||||
* given frequency.
|
* given frequency.
|
||||||
|
|
@ -116,6 +181,35 @@ trait TimerScheduler[T] {
|
||||||
def startTimerAtFixedRate(msg: T, interval: FiniteDuration): Unit =
|
def startTimerAtFixedRate(msg: T, interval: FiniteDuration): Unit =
|
||||||
startTimerAtFixedRate(msg, msg, interval)
|
startTimerAtFixedRate(msg, msg, interval)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a message to be sent repeatedly to the `self` actor with a
|
||||||
|
* given frequency.
|
||||||
|
*
|
||||||
|
* It will compensate the delay for a subsequent message if the sending of previous
|
||||||
|
* message was delayed more than specified. In such cases, the actual message interval
|
||||||
|
* will differ from the interval passed to the method.
|
||||||
|
*
|
||||||
|
* If the execution is delayed longer than the `interval`, the subsequent message will
|
||||||
|
* be sent immediately after the prior one. This also has the consequence that after
|
||||||
|
* long garbage collection pauses or other reasons when the JVM was suspended all
|
||||||
|
* "missed" messages will be sent when the process wakes up again.
|
||||||
|
*
|
||||||
|
* In the long run, the frequency of messages will be exactly the reciprocal of the
|
||||||
|
* specified `interval` after `initialDelay`.
|
||||||
|
*
|
||||||
|
* Warning: `startTimerAtFixedRate` can result in bursts of scheduled messages after long
|
||||||
|
* garbage collection pauses, which may in worst case cause undesired load on the system.
|
||||||
|
* Therefore `startTimerWithFixedDelay` is often preferred.
|
||||||
|
*
|
||||||
|
* When a new timer is started with the same message
|
||||||
|
* the previous is cancelled. It is guaranteed that a message from the
|
||||||
|
* previous timer is not received, even if it was already enqueued
|
||||||
|
* in the mailbox when the new timer was started. If you do not want this,
|
||||||
|
* you can start start them as individual timers by specifying distinct keys.
|
||||||
|
*/
|
||||||
|
def startTimerAtFixedRate(msg: T, initialDelay: FiniteDuration, interval: FiniteDuration): Unit =
|
||||||
|
startTimerAtFixedRate(msg, msg, initialDelay, interval)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deprecated API: See [[TimerScheduler#startTimerWithFixedDelay]] or [[TimerScheduler#startTimerAtFixedRate]].
|
* Deprecated API: See [[TimerScheduler#startTimerWithFixedDelay]] or [[TimerScheduler#startTimerAtFixedRate]].
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
# marked with @DoNotInherit
|
||||||
|
ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.actor.TimerScheduler.startTimerWithFixedDelay")
|
||||||
|
ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.actor.TimerScheduler.startTimerAtFixedRate")
|
||||||
|
# marked with @InternalApi
|
||||||
|
ProblemFilters.exclude[MissingTypesProblem]("akka.actor.TimerSchedulerImpl$FixedRateMode$")
|
||||||
|
ProblemFilters.exclude[MissingTypesProblem]("akka.actor.TimerSchedulerImpl$FixedDelayMode$")
|
||||||
|
ProblemFilters.exclude[FinalMethodProblem]("akka.actor.TimerSchedulerImpl#FixedRateMode.toString")
|
||||||
|
ProblemFilters.exclude[FinalMethodProblem]("akka.actor.TimerSchedulerImpl#FixedDelayMode.toString")
|
||||||
|
ProblemFilters.exclude[DirectMissingMethodProblem]("akka.actor.TimerSchedulerImpl#FixedRateMode.*")
|
||||||
|
ProblemFilters.exclude[DirectMissingMethodProblem]("akka.actor.TimerSchedulerImpl#FixedDelayMode.*")
|
||||||
|
ProblemFilters.exclude[DirectMissingMethodProblem]("akka.actor.TimerSchedulerImpl#FixedRateMode.productElementName")
|
||||||
|
ProblemFilters.exclude[DirectMissingMethodProblem]("akka.actor.TimerSchedulerImpl#FixedRateMode.productElementNames")
|
||||||
|
ProblemFilters.exclude[DirectMissingMethodProblem]("akka.actor.TimerSchedulerImpl#FixedDelayMode.productElementName")
|
||||||
|
ProblemFilters.exclude[DirectMissingMethodProblem]("akka.actor.TimerSchedulerImpl#FixedDelayMode.productElementNames")
|
||||||
|
|
@ -104,6 +104,24 @@ abstract class AbstractActorWithTimers extends AbstractActor with Timers {
|
||||||
*/
|
*/
|
||||||
def startTimerWithFixedDelay(key: Any, msg: Any, delay: FiniteDuration): Unit
|
def startTimerWithFixedDelay(key: Any, msg: Any, delay: FiniteDuration): Unit
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scala API: Schedules a message to be sent repeatedly to the `self` actor with a
|
||||||
|
* fixed `delay` between messages after the `initialDelay`.
|
||||||
|
*
|
||||||
|
* It will not compensate the delay between messages if scheduling is delayed
|
||||||
|
* longer than specified for some reason. The delay between sending of subsequent
|
||||||
|
* messages will always be (at least) the given `delay`.
|
||||||
|
*
|
||||||
|
* In the long run, the frequency of messages will generally be slightly lower than
|
||||||
|
* the reciprocal of the specified `delay`.
|
||||||
|
*
|
||||||
|
* Each timer has a key and if a new timer with same key is started
|
||||||
|
* the previous is cancelled. It is guaranteed that a message from the
|
||||||
|
* previous timer is not received, even if it was already enqueued
|
||||||
|
* in the mailbox when the new timer was started.
|
||||||
|
*/
|
||||||
|
def startTimerWithFixedDelay(key: Any, msg: Any, initialDelay: FiniteDuration, delay: FiniteDuration): Unit
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Java API: Schedules a message to be sent repeatedly to the `self` actor with a
|
* Java API: Schedules a message to be sent repeatedly to the `self` actor with a
|
||||||
* fixed `delay` between messages.
|
* fixed `delay` between messages.
|
||||||
|
|
@ -123,6 +141,29 @@ abstract class AbstractActorWithTimers extends AbstractActor with Timers {
|
||||||
final def startTimerWithFixedDelay(key: Any, msg: Any, delay: java.time.Duration): Unit =
|
final def startTimerWithFixedDelay(key: Any, msg: Any, delay: java.time.Duration): Unit =
|
||||||
startTimerWithFixedDelay(key, msg, delay.asScala)
|
startTimerWithFixedDelay(key, msg, delay.asScala)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Java API: Schedules a message to be sent repeatedly to the `self` actor with a
|
||||||
|
* fixed `delay` between messages after the `initialDelay`.
|
||||||
|
*
|
||||||
|
* It will not compensate the delay between messages if scheduling is delayed
|
||||||
|
* longer than specified for some reason. The delay between sending of subsequent
|
||||||
|
* messages will always be (at least) the given `delay`.
|
||||||
|
*
|
||||||
|
* In the long run, the frequency of messages will generally be slightly lower than
|
||||||
|
* the reciprocal of the specified `delay`.
|
||||||
|
*
|
||||||
|
* Each timer has a key and if a new timer with same key is started
|
||||||
|
* the previous is cancelled. It is guaranteed that a message from the
|
||||||
|
* previous timer is not received, even if it was already enqueued
|
||||||
|
* in the mailbox when the new timer was started.
|
||||||
|
*/
|
||||||
|
final def startTimerWithFixedDelay(
|
||||||
|
key: Any,
|
||||||
|
msg: Any,
|
||||||
|
initialDelay: java.time.Duration,
|
||||||
|
delay: java.time.Duration): Unit =
|
||||||
|
startTimerWithFixedDelay(key, msg, initialDelay.asScala, delay.asScala)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scala API: Schedules a message to be sent repeatedly to the `self` actor with a
|
* Scala API: Schedules a message to be sent repeatedly to the `self` actor with a
|
||||||
* given frequency.
|
* given frequency.
|
||||||
|
|
@ -150,6 +191,33 @@ abstract class AbstractActorWithTimers extends AbstractActor with Timers {
|
||||||
*/
|
*/
|
||||||
def startTimerAtFixedRate(key: Any, msg: Any, interval: FiniteDuration): Unit
|
def startTimerAtFixedRate(key: Any, msg: Any, interval: FiniteDuration): Unit
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scala API: Schedules a message to be sent repeatedly to the `self` actor with a
|
||||||
|
* given frequency.
|
||||||
|
*
|
||||||
|
* It will compensate the delay for a subsequent message if the sending of previous
|
||||||
|
* message was delayed more than specified. In such cases, the actual message interval
|
||||||
|
* will differ from the interval passed to the method.
|
||||||
|
*
|
||||||
|
* If the execution is delayed longer than the `interval`, the subsequent message will
|
||||||
|
* be sent immediately after the prior one. This also has the consequence that after
|
||||||
|
* long garbage collection pauses or other reasons when the JVM was suspended all
|
||||||
|
* "missed" messages will be sent when the process wakes up again.
|
||||||
|
*
|
||||||
|
* In the long run, the frequency of messages will be exactly the reciprocal of the
|
||||||
|
* specified `interval` after `initialDelay`.
|
||||||
|
*
|
||||||
|
* Warning: `startTimerAtFixedRate` can result in bursts of scheduled messages after long
|
||||||
|
* garbage collection pauses, which may in worst case cause undesired load on the system.
|
||||||
|
* Therefore `startTimerWithFixedDelay` is often preferred.
|
||||||
|
*
|
||||||
|
* Each timer has a key and if a new timer with same key is started
|
||||||
|
* the previous is cancelled. It is guaranteed that a message from the
|
||||||
|
* previous timer is not received, even if it was already enqueued
|
||||||
|
* in the mailbox when the new timer was started.
|
||||||
|
*/
|
||||||
|
def startTimerAtFixedRate(key: Any, msg: Any, initialDelay: FiniteDuration, interval: FiniteDuration): Unit
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Java API: Schedules a message to be sent repeatedly to the `self` actor with a
|
* Java API: Schedules a message to be sent repeatedly to the `self` actor with a
|
||||||
* given frequency.
|
* given frequency.
|
||||||
|
|
@ -178,6 +246,38 @@ abstract class AbstractActorWithTimers extends AbstractActor with Timers {
|
||||||
final def startTimerAtFixedRate(key: Any, msg: Any, interval: java.time.Duration): Unit =
|
final def startTimerAtFixedRate(key: Any, msg: Any, interval: java.time.Duration): Unit =
|
||||||
startTimerAtFixedRate(key, msg, interval.asScala)
|
startTimerAtFixedRate(key, msg, interval.asScala)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Java API: Schedules a message to be sent repeatedly to the `self` actor with a
|
||||||
|
* given frequency.
|
||||||
|
*
|
||||||
|
* It will compensate the delay for a subsequent message if the sending of previous
|
||||||
|
* message was delayed more than specified. In such cases, the actual message interval
|
||||||
|
* will differ from the interval passed to the method.
|
||||||
|
*
|
||||||
|
* If the execution is delayed longer than the `interval`, the subsequent message will
|
||||||
|
* be sent immediately after the prior one. This also has the consequence that after
|
||||||
|
* long garbage collection pauses or other reasons when the JVM was suspended all
|
||||||
|
* "missed" messages will be sent when the process wakes up again.
|
||||||
|
*
|
||||||
|
* In the long run, the frequency of messages will be exactly the reciprocal of the
|
||||||
|
* specified `interval`.
|
||||||
|
*
|
||||||
|
* Warning: `startTimerAtFixedRate` can result in bursts of scheduled messages after long
|
||||||
|
* garbage collection pauses, which may in worst case cause undesired load on the system.
|
||||||
|
* Therefore `startTimerWithFixedDelay` is often preferred.
|
||||||
|
*
|
||||||
|
* Each timer has a key and if a new timer with same key is started
|
||||||
|
* the previous is cancelled. It is guaranteed that a message from the
|
||||||
|
* previous timer is not received, even if it was already enqueued
|
||||||
|
* in the mailbox when the new timer was started.
|
||||||
|
*/
|
||||||
|
final def startTimerAtFixedRate(
|
||||||
|
key: Any,
|
||||||
|
msg: Any,
|
||||||
|
initialDelay: java.time.Duration,
|
||||||
|
interval: java.time.Duration): Unit =
|
||||||
|
startTimerAtFixedRate(key, msg, initialDelay.asScala, interval.asScala)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deprecated API: See [[TimerScheduler#startTimerWithFixedDelay]] or [[TimerScheduler#startTimerAtFixedRate]].
|
* Deprecated API: See [[TimerScheduler#startTimerWithFixedDelay]] or [[TimerScheduler#startTimerAtFixedRate]].
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,10 @@ import akka.util.OptionVal
|
||||||
private sealed trait TimerMode {
|
private sealed trait TimerMode {
|
||||||
def repeat: Boolean
|
def repeat: Boolean
|
||||||
}
|
}
|
||||||
private case object FixedRateMode extends TimerMode {
|
private case class FixedRateMode(initialDelay: FiniteDuration) extends TimerMode {
|
||||||
override def repeat: Boolean = true
|
override def repeat: Boolean = true
|
||||||
}
|
}
|
||||||
private case object FixedDelayMode extends TimerMode {
|
private case class FixedDelayMode(initialDelay: FiniteDuration) extends TimerMode {
|
||||||
override def repeat: Boolean = true
|
override def repeat: Boolean = true
|
||||||
}
|
}
|
||||||
private case object SingleMode extends TimerMode {
|
private case object SingleMode extends TimerMode {
|
||||||
|
|
@ -58,10 +58,16 @@ import akka.util.OptionVal
|
||||||
}
|
}
|
||||||
|
|
||||||
override def startTimerAtFixedRate(key: Any, msg: Any, interval: FiniteDuration): Unit =
|
override def startTimerAtFixedRate(key: Any, msg: Any, interval: FiniteDuration): Unit =
|
||||||
startTimer(key, msg, interval, FixedRateMode)
|
startTimer(key, msg, interval, FixedRateMode(interval))
|
||||||
|
|
||||||
|
override def startTimerAtFixedRate(key: Any, msg: Any, initialDelay: FiniteDuration, interval: FiniteDuration): Unit =
|
||||||
|
startTimer(key, msg, interval, FixedRateMode(initialDelay))
|
||||||
|
|
||||||
override def startTimerWithFixedDelay(key: Any, msg: Any, delay: FiniteDuration): Unit =
|
override def startTimerWithFixedDelay(key: Any, msg: Any, delay: FiniteDuration): Unit =
|
||||||
startTimer(key, msg, delay, FixedDelayMode)
|
startTimer(key, msg, delay, FixedDelayMode(delay))
|
||||||
|
|
||||||
|
override def startTimerWithFixedDelay(key: Any, msg: Any, initialDelay: FiniteDuration, delay: FiniteDuration): Unit =
|
||||||
|
startTimer(key, msg, delay, FixedDelayMode(initialDelay))
|
||||||
|
|
||||||
override def startPeriodicTimer(key: Any, msg: Any, interval: FiniteDuration): Unit =
|
override def startPeriodicTimer(key: Any, msg: Any, interval: FiniteDuration): Unit =
|
||||||
startTimerAtFixedRate(key, msg, interval)
|
startTimerAtFixedRate(key, msg, interval)
|
||||||
|
|
@ -85,10 +91,10 @@ import akka.util.OptionVal
|
||||||
val task = mode match {
|
val task = mode match {
|
||||||
case SingleMode =>
|
case SingleMode =>
|
||||||
ctx.system.scheduler.scheduleOnce(timeout, ctx.self, timerMsg)(ctx.dispatcher)
|
ctx.system.scheduler.scheduleOnce(timeout, ctx.self, timerMsg)(ctx.dispatcher)
|
||||||
case FixedDelayMode =>
|
case m: FixedDelayMode =>
|
||||||
ctx.system.scheduler.scheduleWithFixedDelay(timeout, timeout, ctx.self, timerMsg)(ctx.dispatcher)
|
ctx.system.scheduler.scheduleWithFixedDelay(m.initialDelay, timeout, ctx.self, timerMsg)(ctx.dispatcher)
|
||||||
case FixedRateMode =>
|
case m: FixedRateMode =>
|
||||||
ctx.system.scheduler.scheduleAtFixedRate(timeout, timeout, ctx.self, timerMsg)(ctx.dispatcher)
|
ctx.system.scheduler.scheduleAtFixedRate(m.initialDelay, timeout, ctx.self, timerMsg)(ctx.dispatcher)
|
||||||
}
|
}
|
||||||
|
|
||||||
val nextTimer = Timer(key, msg, mode.repeat, nextGen, task)
|
val nextTimer = Timer(key, msg, mode.repeat, nextGen, task)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue