/
rate.hsl
69 lines (54 loc) · 2.1 KB
/
rate.hsl
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
import { Redis } from "extras://redis";
function rate_fixed_window($namespace, $entry, $count, $interval, $options = []) {
if ($options["profile"])
$redis = Redis($options["profile"]);
else
$redis = Redis();
if ($count === 0) {
$response = $redis->command("GET", "$namespace:$entry:count");
return number($response);
}
$response = $redis->command("GET", "$namespace:$entry:time");
$time = number($response);
if (time() - $time >= $interval) {
$redis->command("SET", "$namespace:$entry:time", string(time()), "EX", string($interval));
$redis->command("SET", "$namespace:$entry:count", "0", "EX", string($interval));
} else {
$response = $redis->command("GET", "$namespace:$entry:count");
$current = number($response);
if ($current >= $count) {
return false;
}
}
$redis->command("INCR", "$namespace:$entry:count");
return true;
}
function rate_sliding_window($namespace, $entry, $count, $interval, $options = []) {
if ($options["profile"])
$redis = Redis($options["profile"]);
else
$redis = Redis();
$time = time();
$currentWindow = floor($time / $interval);
$response = $redis->command("GET", "$namespace:$entry:$currentWindow");
$currentWindowCount = number($response);
if ($count !== 0 and $currentWindowCount === 0) {
$redis->command("SET", "$namespace:$entry:$currentWindow", "0", "EX", string($interval * 2));
}
if ($count and $currentWindowCount >= $count) {
return false;
}
$lastWindow = floor(($time - $interval) / $interval);
$response = $redis->command("GET", "$namespace:$entry:$lastWindow");
$lastWindowCount = number($response);
$elapsedTimePercentage = ($time % $interval) / $interval;
$combinedCount = floor($lastWindowCount * (1 - $elapsedTimePercentage)) + $currentWindowCount;
if ($count === 0) {
return $combinedCount;
}
if ($combinedCount >= $count) {
return false;
}
$redis->command("INCR", "$namespace:$entry:$currentWindow");
return true;
}