GCRA param renaming (#14950)
Some checks are pending
CI / test-ubuntu-latest (push) Waiting to run
CI / test-sanitizer-address (push) Waiting to run
CI / build-debian-old (push) Waiting to run
CI / build-macos-latest (push) Waiting to run
CI / build-32bit (push) Waiting to run
CI / build-libc-malloc (push) Waiting to run
CI / build-centos-jemalloc (push) Waiting to run
CI / build-old-chain-jemalloc (push) Waiting to run
Codecov / code-coverage (push) Waiting to run
External Server Tests / test-external-standalone (push) Waiting to run
External Server Tests / test-external-cluster (push) Waiting to run
External Server Tests / test-external-nodebug (push) Waiting to run
Reply-schemas linter / reply-schemas-linter (push) Waiting to run
Spellcheck / Spellcheck (push) Waiting to run

Renames the `GCRA` command interface to use token terminology:
`requests-per-period` becomes `tokens-per-period`, and the optional
`NUM_REQUESTS` argument becomes `TOKENS` (with corresponding error
messages/documentation updates).
This commit is contained in:
Mincho Paskalev 2026-03-31 11:57:42 +03:00 committed by GitHub
parent b22ce4abb5
commit ef536f48fd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 31 additions and 31 deletions

View file

@ -11062,9 +11062,9 @@ keySpec GCRA_Keyspecs[1] = {
struct COMMAND_ARG GCRA_Args[] = {
{MAKE_ARG("key",ARG_TYPE_KEY,0,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)},
{MAKE_ARG("max-burst",ARG_TYPE_INTEGER,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)},
{MAKE_ARG("requests-per-period",ARG_TYPE_INTEGER,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)},
{MAKE_ARG("tokens-per-period",ARG_TYPE_INTEGER,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)},
{MAKE_ARG("period",ARG_TYPE_DOUBLE,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)},
{MAKE_ARG("count",ARG_TYPE_INTEGER,-1,"NUM_REQUESTS",NULL,NULL,CMD_ARG_OPTIONAL,0,NULL)},
{MAKE_ARG("count",ARG_TYPE_INTEGER,-1,"TOKENS",NULL,NULL,CMD_ARG_OPTIONAL,0,NULL)},
};
/********** GET ********************/

View file

@ -74,7 +74,7 @@
"type": "integer"
},
{
"name": "requests-per-period",
"name": "tokens-per-period",
"type": "integer"
},
{
@ -84,7 +84,7 @@
{
"name": "count",
"type": "integer",
"token": "NUM_REQUESTS",
"token": "TOKENS",
"optional": true
}
]

View file

@ -65,21 +65,21 @@
*
* (ASCII art adapted from https://brandur.org/rate-limiting). */
/* GCRA key max_burst requests_per_period period [NUM_REQUESTS count]
/* GCRA key max_burst tokens_per_period period [TOKENS count]
*
* key: Key related to specific rate limiting case
* max_burst: Maximum requests allowed as burst (in addition to sustained rate)
* requests_per_period: Number of requests allowed per period
* max_burst: Maximum tokens allowed as burst (in addition to sustained rate)
* tokens_per_period: Number of tokens allowed per period
* period: Period in seconds for calculating sustained rate
* num_requests: Optional, cost of this request (default: 1)
* tokens: Optional, cost of this request (default: 1)
*/
void gcraCommand(client *c) {
robj *key = c->argv[1];
/* GCRA parameters */
long max_burst;
long requests_per_period;
long num_requests = 1;
long tokens_per_period;
long num_tokens = 1;
double period;
/* Variables used in the reply */
@ -98,7 +98,7 @@ void gcraCommand(client *c) {
}
if (likely(max_burst < LONG_MAX)) max_burst += 1;
if (getRangeLongFromObjectOrReply(c, c->argv[3], 1, LONG_MAX, &requests_per_period, NULL) != C_OK) {
if (getRangeLongFromObjectOrReply(c, c->argv[3], 1, LONG_MAX, &tokens_per_period, NULL) != C_OK) {
return;
}
@ -111,15 +111,15 @@ void gcraCommand(client *c) {
}
if (c->argc >= 6) {
if (strcasecmp("NUM_REQUESTS", c->argv[5]->ptr)) {
if (strcasecmp("tokens", c->argv[5]->ptr)) {
addReplyErrorObject(c, shared.syntaxerr);
return;
}
if (c->argc == 6) {
addReplyError(c, "Missing NUM_REQUESTS value");
addReplyError(c, "Missing TOKENS value");
return;
}
if (getRangeLongFromObjectOrReply(c, c->argv[6], 1, LONG_MAX, &num_requests, NULL) != C_OK) {
if (getRangeLongFromObjectOrReply(c, c->argv[6], 1, LONG_MAX, &num_tokens, NULL) != C_OK) {
return;
}
}
@ -158,18 +158,18 @@ void gcraCommand(client *c) {
* Even if emission_interval_us becomes less than 1us, we assume it's min
* 1ms. The API is already in seconds granularity so it is expected the user
* won't need a submicrosecond accuracy. */
long long emission_interval_us = (long long)(period_us / requests_per_period + 0.5);
long long emission_interval_us = (long long)(period_us / tokens_per_period + 0.5);
if (unlikely(emission_interval_us == 0)) emission_interval_us = 1;
/* overflow checks. In normal circumstances we shouldn't get these but the
* user may have wrongfully specified very large values.
* Note that all values are positive. */
if (emission_interval_us > LLONG_MAX / num_requests) {
addReplyError(c, "GCRA limiting uses microsecond accuracy. Combination of period, requests_per_period and num_requests would cause an overflow");
if (emission_interval_us > LLONG_MAX / num_tokens) {
addReplyError(c, "GCRA limiting uses microsecond accuracy. Combination of period, tokens_per_period and TOKENS would cause an overflow");
return;
}
if (emission_interval_us > LLONG_MAX / max_burst) {
addReplyError(c, "GCRA limiting uses microsecond accuracy. Combination of period, requests_per_period and max_burst would cause an overflow");
addReplyError(c, "GCRA limiting uses microsecond accuracy. Combination of period, tokens_per_period and max_burst would cause an overflow");
return;
}
@ -180,11 +180,11 @@ void gcraCommand(client *c) {
/* If a request is allowed the next TaT is after an emission_interval_us time.
* Hence for multiple requests we multiple by their number. */
long long increment_us = emission_interval_us * num_requests;
long long increment_us = emission_interval_us * num_tokens;
long long base_us = (now > tat_us) ? now : tat_us;
if (LLONG_MAX - base_us < increment_us) {
addReplyError(c, "GCRA limiting uses microsecond accuracy. Combination of period, requests_per_period and num_requests would cause an overflow");
addReplyError(c, "GCRA limiting uses microsecond accuracy. Combination of period, tokens_per_period and TOKENS would cause an overflow");
return;
}
new_tat_us = base_us + increment_us;

View file

@ -33,13 +33,13 @@ start_server {tags {"gcra" "external:skip"}} {
assert_match "*not a valid float*" $err
# tokens (optional) must be >= 1
catch {r gcra mykey 10 5 10 NUM_REQUESTS} err
assert_match "*Missing NUM_REQUESTS value*" $err
catch {r gcra mykey 10 5 10 NUM_REQUESTS 0} err
catch {r gcra mykey 10 5 10 TOKENS} err
assert_match "*Missing TOKENS value*" $err
catch {r gcra mykey 10 5 10 TOKENS 0} err
assert_match "*out of range*" $err
catch {r gcra mykey 10 5 10 NUM_REQUESTS -1} err
catch {r gcra mykey 10 5 10 TOKENS -1} err
assert_match "*out of range*" $err
catch {r gcra mykey 10 5 10 NUM_REQUESTS notanumber} err
catch {r gcra mykey 10 5 10 TOKENS notanumber} err
assert_match "*not an integer*" $err
# Valid arguments with default tokens
@ -53,7 +53,7 @@ start_server {tags {"gcra" "external:skip"}} {
# Valid arguments with explicit tokens
r del mykey
set result [r gcra mykey 10 5 60 NUM_REQUESTS 2]
set result [r gcra mykey 10 5 60 TOKENS 2]
assert_equal 5 [llength $result]
assert_equal 11 [lindex $result 1]
@ -130,7 +130,7 @@ start_server {tags {"gcra" "external:skip"}} {
r del mykey
# Consume 3 tokens from fresh state
set result2 [r gcra mykey 5 1 60 NUM_REQUESTS 3]
set result2 [r gcra mykey 5 1 60 TOKENS 3]
set avail2 [lindex $result2 2]
assert_equal 3 $avail2
}
@ -168,7 +168,7 @@ start_server {tags {"gcra" "external:skip"}} {
r del mykey
r gcra mykey 5 1 60
set result [r gcra mykey 5 1 60 NUM_REQUESTS 4]
set result [r gcra mykey 5 1 60 TOKENS 4]
set full_burst_after [lindex $result 4]
assert {$full_burst_after >= 299}
}
@ -216,7 +216,7 @@ start_server {tags {"gcra" "external:skip"}} {
test {GCRA - overflow} {
r del mykey
catch {r gcra mykey 1 1 86400 NUM_REQUESTS 200000000} err
catch {r gcra mykey 1 1 86400 TOKENS 200000000} err
assert_match "*would cause an overflow*" $err
r del mykey
@ -224,7 +224,7 @@ start_server {tags {"gcra" "external:skip"}} {
assert_match "*would cause an overflow*" $err
r del mykey
catch {r gcra mykey 1 1 2147483647 NUM_REQUESTS 2147483647} err
catch {r gcra mykey 1 1 2147483647 TOKENS 2147483647} err
assert_match "*would cause an overflow*" $err
}
}
@ -255,7 +255,7 @@ start_server {tags {"gcra repl" "external:skip"}} {
assert_equal [lsearch -glob $cmdinfo "cmdstat_set:*"] -1
$master del mykey
$master gcra mykey 2 1 1000 NUM_REQUESTS 2
$master gcra mykey 2 1 1000 TOKENS 2
wait_for_ofs_sync $master $replica