-
Notifications
You must be signed in to change notification settings - Fork 3.6k
/
BackoffSupervisor.scala
111 lines (92 loc) · 3.35 KB
/
BackoffSupervisor.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/*
* Copyright (C) 2015-2023 Lightbend Inc. <https://www.lightbend.com>
*/
package akka.pattern
import java.util.Optional
import java.util.concurrent.ThreadLocalRandom
import scala.concurrent.duration.FiniteDuration
import scala.util.Try
import akka.actor.{ ActorRef, DeadLetterSuppression, Props }
import akka.annotation.InternalApi
object BackoffSupervisor {
/**
* Props for creating a `BackoffSupervisor` actor from [[BackoffOnStopOptions]].
*
* @param options the [[BackoffOnStopOptions]] that specify how to construct a backoff-supervisor.
*/
def props(options: BackoffOnStopOptions): Props = options.props
/**
* Props for creating a `BackoffSupervisor` actor from [[BackoffOnFailureOptions]].
*
* @param options the [[BackoffOnFailureOptions]] that specify how to construct a backoff-supervisor.
*/
def props(options: BackoffOnFailureOptions): Props = options.props
/**
* Send this message to the `BackoffSupervisor` and it will reply with
* [[BackoffSupervisor.CurrentChild]] containing the `ActorRef` of the current child, if any.
*/
case object GetCurrentChild
/**
* Java API: Send this message to the `BackoffSupervisor` and it will reply with
* [[BackoffSupervisor.CurrentChild]] containing the `ActorRef` of the current child, if any.
*/
def getCurrentChild = GetCurrentChild
/**
* Send this message to the `BackoffSupervisor` and it will reply with
* [[BackoffSupervisor.CurrentChild]] containing the `ActorRef` of the current child, if any.
*/
final case class CurrentChild(ref: Option[ActorRef]) {
/**
* Java API: The `ActorRef` of the current child, if any
*/
def getRef: Optional[ActorRef] = Optional.ofNullable(ref.orNull)
}
/**
* Send this message to the `BackoffSupervisor` and it will reset the back-off.
* This should be used in conjunction with `withManualReset` in [[BackoffOptions]].
*/
case object Reset
/**
* Java API: Send this message to the `BackoffSupervisor` and it will reset the back-off.
* This should be used in conjunction with `withManualReset` in [[BackoffOptions]].
*/
def reset = Reset
/**
* Send this message to the `BackoffSupervisor` and it will reply with
* [[BackoffSupervisor.RestartCount]] containing the current restart count.
*/
case object GetRestartCount
/**
* Java API: Send this message to the `BackoffSupervisor` and it will reply with
* [[BackoffSupervisor.RestartCount]] containing the current restart count.
*/
def getRestartCount = GetRestartCount
final case class RestartCount(count: Int)
/**
* INTERNAL API
*/
@InternalApi
private[akka] case object StartChild extends DeadLetterSuppression
/**
* INTERNAL API
*/
@InternalApi
private[akka] case class ResetRestartCount(current: Int) extends DeadLetterSuppression
/**
* INTERNAL API
*
* Calculates an exponential back off delay.
*/
private[akka] def calculateDelay(
restartCount: Int,
minBackoff: FiniteDuration,
maxBackoff: FiniteDuration,
randomFactor: Double): FiniteDuration = {
val rnd = 1.0 + ThreadLocalRandom.current().nextDouble() * randomFactor
val calculatedDuration = Try(maxBackoff.min(minBackoff * math.pow(2, restartCount)) * rnd).getOrElse(maxBackoff)
calculatedDuration match {
case f: FiniteDuration => f
case _ => maxBackoff
}
}
}