@@ -22,7 +22,7 @@ pub struct RateLimitState {
22
22
pub enum RateLimitResult {
23
23
/// If the rate limit is not exceeded, the transfer is immediate,
24
24
/// and the capacity is reduced.
25
- Consumed ,
25
+ Consumed ( UnixTimestamp ) ,
26
26
/// If the rate limit is exceeded, the transfer is delayed until the
27
27
/// given timestamp.
28
28
Delayed ( UnixTimestamp ) ,
@@ -81,21 +81,21 @@ impl RateLimitState {
81
81
/// returned.
82
82
pub fn consume_or_delay ( & mut self , amount : u64 ) -> RateLimitResult {
83
83
let now = current_timestamp ( ) ;
84
- let capacity = self . capacity ( ) ;
84
+ let capacity = self . capacity_at ( now ) ;
85
85
if capacity >= amount {
86
86
self . capacity_at_last_tx = capacity - amount;
87
87
self . last_tx_timestamp = now;
88
- RateLimitResult :: Consumed
88
+ RateLimitResult :: Consumed ( now )
89
89
} else {
90
90
RateLimitResult :: Delayed ( now + Self :: RATE_LIMIT_DURATION )
91
91
}
92
92
}
93
93
94
94
/// Refills the capacity by the given amount.
95
95
/// This is used to replenish the capacity via backflows.
96
- pub fn refill ( & mut self , amount : u64 ) {
96
+ pub fn refill ( & mut self , now : UnixTimestamp , amount : u64 ) {
97
97
self . capacity_at_last_tx = self . capacity ( ) . saturating_add ( amount) . min ( self . limit ) ;
98
- self . last_tx_timestamp = current_timestamp ( ) ;
98
+ self . last_tx_timestamp = now ;
99
99
}
100
100
101
101
pub fn set_limit ( & mut self , limit : u64 ) {
@@ -127,30 +127,32 @@ mod tests {
127
127
128
128
#[ test]
129
129
fn test_rate_limit ( ) {
130
+ let now = current_timestamp ( ) ;
130
131
let mut rate_limit_state = RateLimitState {
131
132
limit : 100_000 ,
132
133
capacity_at_last_tx : 100_000 ,
133
- last_tx_timestamp : current_timestamp ( ) ,
134
+ last_tx_timestamp : now ,
134
135
} ;
135
136
136
137
// consume 30k. should be immediate
137
138
let immediately = rate_limit_state. consume_or_delay ( 30_000 ) ;
138
139
139
- assert_eq ! ( immediately, RateLimitResult :: Consumed ) ;
140
+ assert_eq ! ( immediately, RateLimitResult :: Consumed ( now ) ) ;
140
141
assert_eq ! ( rate_limit_state. capacity( ) , 70_000 ) ;
141
142
assert_eq ! ( rate_limit_state. limit, 100_000 ) ; // unchanged
142
143
assert_eq ! ( rate_limit_state. last_tx_timestamp, current_timestamp( ) ) ;
143
144
144
145
// replenish 1/4 of the limit, i.e. 25k
145
146
set_test_timestamp ( current_timestamp ( ) + RateLimitState :: RATE_LIMIT_DURATION / 4 ) ;
147
+ let now = current_timestamp ( ) ;
146
148
147
149
assert_eq ! ( rate_limit_state. capacity( ) , 70_000 + 25_000 ) ;
148
150
149
151
// now consume 150k. should be delayed
150
152
let tomorrow = rate_limit_state. consume_or_delay ( 150_000 ) ;
151
153
assert_eq ! (
152
154
tomorrow,
153
- RateLimitResult :: Delayed ( current_timestamp ( ) + RateLimitState :: RATE_LIMIT_DURATION )
155
+ RateLimitResult :: Delayed ( now + RateLimitState :: RATE_LIMIT_DURATION )
154
156
) ;
155
157
156
158
// the limit is not changed, since the tx was delayed
@@ -168,11 +170,11 @@ mod tests {
168
170
assert_eq ! ( rate_limit_state. capacity( ) , 95_000 ) ;
169
171
170
172
// now refill 2k
171
- rate_limit_state. refill ( 2_000 ) ;
173
+ rate_limit_state. refill ( now , 2_000 ) ;
172
174
assert_eq ! ( rate_limit_state. capacity( ) , 97_000 ) ;
173
175
174
176
// now refill 50k
175
- rate_limit_state. refill ( 50_000 ) ;
177
+ rate_limit_state. refill ( now , 50_000 ) ;
176
178
assert_eq ! ( rate_limit_state. capacity( ) , 100_000 ) ;
177
179
}
178
180
}
0 commit comments