@@ -2,23 +2,24 @@ package ox.resilience
2
2
3
3
import scala .concurrent .duration .FiniteDuration
4
4
import ox .*
5
-
6
5
import scala .annotation .tailrec
7
6
8
- /** Rate limiter with a customizable algorithm. Operations can be blocked or dropped, when the rate limit is reached. */
7
+ /** Rate limiter with a customizable algorithm. Operations can be blocked or dropped, when the rate limit is reached. The rate limiter might
8
+ * take into account the start time of the operation, or its entire duration.
9
+ */
9
10
class RateLimiter private (algorithm : RateLimiterAlgorithm ):
10
11
/** Runs the operation, blocking if the rate limit is reached, until the rate limiter is replenished. */
11
12
def runBlocking [T ](operation : => T ): T =
12
13
algorithm.acquire()
13
- operation
14
+ algorithm.runOperation( operation)
14
15
15
- /** Runs or drops the operation , if the rate limit is reached.
16
+ /** Runs the operation or drops it , if the rate limit is reached.
16
17
*
17
18
* @return
18
- * `Some` if the operation has been allowed to run, `None` if the operation has been dropped.
19
+ * `Some` if the operation has been run, `None` if the operation has been dropped.
19
20
*/
20
21
def runOrDrop [T ](operation : => T ): Option [T ] =
21
- if algorithm.tryAcquire() then Some (operation)
22
+ if algorithm.tryAcquire() then Some (algorithm.runOperation( operation) )
22
23
else None
23
24
24
25
end RateLimiter
@@ -39,32 +40,36 @@ object RateLimiter:
39
40
new RateLimiter (algorithm)
40
41
end apply
41
42
42
- /** Creates a rate limiter using a fixed window algorithm.
43
+ /** Creates a rate limiter using a fixed window algorithm. Takes into account the start time of the operation only.
43
44
*
44
45
* Must be run within an [[Ox ]] concurrency scope, as a background fork is created, to replenish the rate limiter.
45
46
*
46
47
* @param maxOperations
47
48
* Maximum number of operations that are allowed to **start** within a time [[window ]].
48
49
* @param window
49
- * Interval of time between replenishing the rate limiter. THe rate limiter is replenished to allow up to [[maxOperations ]] in the next
50
+ * Interval of time between replenishing the rate limiter. The rate limiter is replenished to allow up to [[maxOperations ]] in the next
50
51
* time window.
52
+ * @see
53
+ * [[fixedWindowWithDuration ]]
51
54
*/
52
- def fixedWindow (maxOperations : Int , window : FiniteDuration )(using Ox ): RateLimiter =
53
- apply(RateLimiterAlgorithm .FixedWindow (maxOperations, window))
55
+ def fixedWindowWithStartTime (maxOperations : Int , window : FiniteDuration )(using Ox ): RateLimiter =
56
+ apply(StartTimeRateLimiterAlgorithm .FixedWindow (maxOperations, window))
54
57
55
- /** Creates a rate limiter using a sliding window algorithm.
58
+ /** Creates a rate limiter using a sliding window algorithm. Takes into account the start time of the operation only.
56
59
*
57
60
* Must be run within an [[Ox ]] concurrency scope, as a background fork is created, to replenish the rate limiter.
58
61
*
59
62
* @param maxOperations
60
63
* Maximum number of operations that are allowed to **start** within any [[window ]] of time.
61
64
* @param window
62
65
* Length of the window.
66
+ * @see
67
+ * [[slidingWindowWithDuration ]]
63
68
*/
64
- def slidingWindow (maxOperations : Int , window : FiniteDuration )(using Ox ): RateLimiter =
65
- apply(RateLimiterAlgorithm .SlidingWindow (maxOperations, window))
69
+ def slidingWindowWithStartTime (maxOperations : Int , window : FiniteDuration )(using Ox ): RateLimiter =
70
+ apply(StartTimeRateLimiterAlgorithm .SlidingWindow (maxOperations, window))
66
71
67
- /** Rate limiter with token/leaky bucket algorithm.
72
+ /** Creates a rate limiter with token/leaky bucket algorithm. Takes into account the start time of the operation only .
68
73
*
69
74
* Must be run within an [[Ox ]] concurrency scope, as a background fork is created, to replenish the rate limiter.
70
75
*
@@ -74,5 +79,40 @@ object RateLimiter:
74
79
* Interval of time between adding a single token to the bucket.
75
80
*/
76
81
def leakyBucket (maxTokens : Int , refillInterval : FiniteDuration )(using Ox ): RateLimiter =
77
- apply(RateLimiterAlgorithm .LeakyBucket (maxTokens, refillInterval))
82
+ apply(StartTimeRateLimiterAlgorithm .LeakyBucket (maxTokens, refillInterval))
83
+
84
+ /** Creates a rate limiter with a fixed window algorithm.
85
+ *
86
+ * Takes into account the entire duration of the operation. That is the instant at which the operation "happens" can be anywhere between
87
+ * its start and end. This ensures that the rate limit is always respected, although it might make it more restrictive.
88
+ *
89
+ * Must be run within an [[Ox ]] concurrency scope, as a background fork is created, to replenish the rate limiter.
90
+ *
91
+ * @param maxOperations
92
+ * Maximum number of operations that are allowed to **run** (finishing from previous windows or start new) within a time [[window ]].
93
+ * @param window
94
+ * Length of the window.
95
+ * @see
96
+ * [[fixedWindowWithStartTime ]]
97
+ */
98
+ def fixedWindowWithDuration (maxOperations : Int , window : FiniteDuration )(using Ox ): RateLimiter =
99
+ apply(DurationRateLimiterAlgorithm .FixedWindow (maxOperations, window))
100
+
101
+ /** Creates a rate limiter using a sliding window algorithm.
102
+ *
103
+ * Takes into account the entire duration of the operation. That is the instant at which the operation "happens" can be anywhere between
104
+ * its start and end. This ensures that the rate limit is always respected, although it might make it more restrictive.
105
+ *
106
+ * Must be run within an [[Ox ]] concurrency scope, as a background fork is created, to replenish the rate limiter.
107
+ *
108
+ * @param maxOperations
109
+ * Maximum number of operations that are allowed to **run** (start or finishing) within any [[window ]] of time.
110
+ * @param window
111
+ * Length of the window.
112
+ * @see
113
+ * [[slidingWindowWithStartTime ]]
114
+ */
115
+ def slidingWindowWithDuration (maxOperations : Int , window : FiniteDuration )(using Ox ): RateLimiter =
116
+ apply(DurationRateLimiterAlgorithm .SlidingWindow (maxOperations, window))
117
+
78
118
end RateLimiter
0 commit comments