16
16
17
17
import static com .google .firebase .perf .metrics .resource .ResourceType .NETWORK ;
18
18
import static com .google .firebase .perf .metrics .resource .ResourceType .TRACE ;
19
+ import static java .util .concurrent .TimeUnit .SECONDS ;
19
20
20
21
import android .content .Context ;
21
22
import androidx .annotation .NonNull ;
25
26
import com .google .firebase .perf .metrics .resource .ResourceType ;
26
27
import com .google .firebase .perf .util .Clock ;
27
28
import com .google .firebase .perf .util .Constants ;
29
+ import com .google .firebase .perf .util .Rate ;
28
30
import com .google .firebase .perf .util .Timer ;
29
31
import com .google .firebase .perf .util .Utils ;
30
32
import com .google .firebase .perf .v1 .NetworkRequestMetric ;
34
36
import com .google .firebase .perf .v1 .TraceMetric ;
35
37
import java .util .List ;
36
38
import java .util .Random ;
37
- import java .util .concurrent .TimeUnit ;
38
39
39
40
/**
40
41
* Implement the Token Bucket rate limiting algorithm. The token bucket initially holds "capacity"
@@ -60,10 +61,10 @@ final class RateLimiter {
60
61
* Construct a token bucket rate limiter.
61
62
*
62
63
* @param appContext the application's context.
63
- * @param rate number of token generated per minute.
64
+ * @param rate the Rate object representing the number of tokens generated per specified time unit
64
65
* @param capacity token bucket capacity
65
66
*/
66
- public RateLimiter (@ NonNull Context appContext , final double rate , final long capacity ) {
67
+ public RateLimiter (@ NonNull Context appContext , final Rate rate , final long capacity ) {
67
68
this (rate , capacity , new Clock (), getSamplingBucketId (), ConfigResolver .getInstance ());
68
69
this .isLogcatEnabled = Utils .isDebugLoggingEnabled (appContext );
69
70
}
@@ -75,7 +76,7 @@ static float getSamplingBucketId() {
75
76
}
76
77
77
78
RateLimiter (
78
- final double rate ,
79
+ final Rate rate ,
79
80
final long capacity ,
80
81
final Clock clock ,
81
82
float samplingBucketId ,
@@ -211,29 +212,29 @@ boolean getIsDeviceAllowedToSendNetworkEvents() {
211
212
static class RateLimiterImpl {
212
213
213
214
private static final AndroidLogger logger = AndroidLogger .getInstance ();
214
- private static final long MICROS_IN_A_SECOND = TimeUnit . SECONDS .toMicros (1 );
215
+ private static final long MICROS_IN_A_SECOND = SECONDS .toMicros (1 );
215
216
216
217
private final Clock clock ;
217
218
private final boolean isLogcatEnabled ;
218
219
219
220
// Last time a token is consumed.
220
- private Timer lastTimeTokenConsumed ;
221
+ private Timer lastTimeTokenReplenished ;
221
222
222
- // Number of new tokens generated per second.
223
- private double rate ;
223
+ // The Rate object representing the number of tokens generated per specified time unit
224
+ private Rate rate ;
224
225
// Token bucket capacity, also the initial number of tokens in the bucket.
225
226
private long capacity ;
226
227
// Number of tokens in the bucket.
227
228
private long tokenCount ;
228
229
229
- private double foregroundRate ;
230
- private double backgroundRate ;
230
+ private Rate foregroundRate ;
231
+ private Rate backgroundRate ;
231
232
232
233
private long foregroundCapacity ;
233
234
private long backgroundCapacity ;
234
235
235
236
RateLimiterImpl (
236
- final double rate ,
237
+ final Rate rate ,
237
238
final long capacity ,
238
239
final Clock clock ,
239
240
ConfigResolver configResolver ,
@@ -243,7 +244,7 @@ static class RateLimiterImpl {
243
244
this .capacity = capacity ;
244
245
this .rate = rate ;
245
246
tokenCount = capacity ;
246
- lastTimeTokenConsumed = this .clock .getTime ();
247
+ lastTimeTokenReplenished = this .clock .getTime ();
247
248
setRateByReadingRemoteConfigValues (configResolver , type , isLogcatEnabled );
248
249
this .isLogcatEnabled = isLogcatEnabled ;
249
250
}
@@ -260,11 +261,20 @@ synchronized boolean check(@NonNull PerfMetric metric) {
260
261
Timer now = clock .getTime ();
261
262
long newTokens =
262
263
Math .max (
263
- 0 , (long ) (lastTimeTokenConsumed .getDurationMicros (now ) * rate / MICROS_IN_A_SECOND ));
264
+ 0 ,
265
+ (long )
266
+ (lastTimeTokenReplenished .getDurationMicros (now )
267
+ * rate .getTokenPerSeconds ()
268
+ / MICROS_IN_A_SECOND ));
264
269
tokenCount = Math .min (tokenCount + newTokens , capacity );
270
+ if (newTokens > 0 ) {
271
+ lastTimeTokenReplenished =
272
+ new Timer (
273
+ lastTimeTokenReplenished .getMicros ()
274
+ + (long ) (newTokens * MICROS_IN_A_SECOND / rate .getTokenPerSeconds ()));
275
+ }
265
276
if (tokenCount > 0 ) {
266
277
tokenCount --;
267
- lastTimeTokenConsumed = now ;
268
278
return true ;
269
279
}
270
280
if (isLogcatEnabled ) {
@@ -297,7 +307,7 @@ private void setRateByReadingRemoteConfigValues(
297
307
long fLimitTime = getFlimitSec (configResolver , type );
298
308
long fLimitEvents = getFlimitEvents (configResolver , type );
299
309
300
- foregroundRate = (( double ) fLimitEvents ) / fLimitTime ;
310
+ foregroundRate = new Rate ( fLimitEvents , fLimitTime , SECONDS ) ;
301
311
foregroundCapacity = fLimitEvents ;
302
312
if (isLogcatEnabled ) {
303
313
logger .debug (
@@ -309,7 +319,7 @@ private void setRateByReadingRemoteConfigValues(
309
319
long bLimitTime = getBlimitSec (configResolver , type );
310
320
long bLimitEvents = getBlimitEvents (configResolver , type );
311
321
312
- backgroundRate = (( double ) bLimitEvents ) / bLimitTime ;
322
+ backgroundRate = new Rate ( bLimitEvents , bLimitTime , SECONDS ) ;
313
323
backgroundCapacity = bLimitEvents ;
314
324
if (isLogcatEnabled ) {
315
325
logger .debug (
@@ -350,7 +360,7 @@ private static long getBlimitEvents(
350
360
}
351
361
352
362
@ VisibleForTesting
353
- double getForegroundRate () {
363
+ Rate getForegroundRate () {
354
364
return foregroundRate ;
355
365
}
356
366
@@ -360,7 +370,7 @@ long getForegroundCapacity() {
360
370
}
361
371
362
372
@ VisibleForTesting
363
- double getBackgroundRate () {
373
+ Rate getBackgroundRate () {
364
374
return backgroundRate ;
365
375
}
366
376
@@ -370,12 +380,12 @@ long getBackgroundCapacity() {
370
380
}
371
381
372
382
@ VisibleForTesting
373
- double getRate () {
383
+ Rate getRate () {
374
384
return rate ;
375
385
}
376
386
377
387
@ VisibleForTesting
378
- void setRate (double newRate ) {
388
+ void setRate (Rate newRate ) {
379
389
rate = newRate ;
380
390
}
381
391
}
0 commit comments