[#1689] node/config: Allow zero max_ops in RPC limits config
All checks were successful
Vulncheck / Vulncheck (push) Successful in 1m14s
Pre-commit hooks / Pre-commit (push) Successful in 1m51s
Build / Build Components (push) Successful in 2m1s
Tests and linters / Run gofumpt (push) Successful in 2m38s
Tests and linters / Tests (push) Successful in 2m53s
Tests and linters / Staticcheck (push) Successful in 3m9s
Tests and linters / Lint (push) Successful in 4m5s
Tests and linters / gopls check (push) Successful in 4m34s
OCI image / Build container images (push) Successful in 4m58s
Tests and linters / Tests with -race (push) Successful in 5m59s

The limiter allows zeros for limits, meaning "this operation is
disabled".  However, the config didn't allow zero due to the lack of
distinction between "no value" and "zero" - cast functions read both
`nil` and zero as zero.

Now, the config allows a zero limit. Added tests.

Managing such cases should be easier after #1610.

Change-Id: Ifc840732390b2feb975f230573b34bf479406e05
Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
This commit is contained in:
Aleksey Savchuk 2025-03-21 15:51:22 +03:00
parent d951289131
commit 4919b6a206
Signed by: a-savchuk
GPG key ID: 70C0A7FF6F9C4639
8 changed files with 59 additions and 4 deletions

View file

@ -31,12 +31,11 @@ func Limits(c *config.Config) []LimitConfig {
break
}
maxOps := config.IntSafe(sc, "max_ops")
if maxOps == 0 {
if sc.Value("max_ops") == nil {
panic("no max operations for method group")
}
limits = append(limits, LimitConfig{methods, maxOps})
limits = append(limits, LimitConfig{methods, config.IntSafe(sc, "max_ops")})
}
return limits

View file

@ -38,7 +38,7 @@ func TestRPCSection(t *testing.T) {
})
t.Run("no max operations", func(t *testing.T) {
const path = "testdata/node"
const path = "testdata/no_max_ops"
fileConfigTest := func(c *config.Config) {
require.Panics(t, func() { _ = Limits(c) })
@ -50,4 +50,28 @@ func TestRPCSection(t *testing.T) {
configtest.ForEnvFileType(t, path, fileConfigTest)
})
})
t.Run("zero max operations", func(t *testing.T) {
const path = "testdata/zero_max_ops"
fileConfigTest := func(c *config.Config) {
limits := Limits(c)
require.Len(t, limits, 2)
limit0 := limits[0]
limit1 := limits[1]
require.ElementsMatch(t, limit0.Methods, []string{"/neo.fs.v2.object.ObjectService/PutSingle", "/neo.fs.v2.object.ObjectService/Put"})
require.Equal(t, limit0.MaxOps, int64(0))
require.ElementsMatch(t, limit1.Methods, []string{"/neo.fs.v2.object.ObjectService/Get"})
require.Equal(t, limit1.MaxOps, int64(10000))
}
configtest.ForEachFileType(path, fileConfigTest)
t.Run("ENV", func(t *testing.T) {
configtest.ForEnvFileType(t, path, fileConfigTest)
})
})
}

View file

@ -0,0 +1,4 @@
FROSTFS_RPC_LIMITS_0_METHODS="/neo.fs.v2.object.ObjectService/PutSingle /neo.fs.v2.object.ObjectService/Put"
FROSTFS_RPC_LIMITS_0_MAX_OPS=0
FROSTFS_RPC_LIMITS_1_METHODS="/neo.fs.v2.object.ObjectService/Get"
FROSTFS_RPC_LIMITS_1_MAX_OPS=10000

View file

@ -0,0 +1,19 @@
{
"rpc": {
"limits": [
{
"methods": [
"/neo.fs.v2.object.ObjectService/PutSingle",
"/neo.fs.v2.object.ObjectService/Put"
],
"max_ops": 0
},
{
"methods": [
"/neo.fs.v2.object.ObjectService/Get"
],
"max_ops": 10000
}
]
}
}

View file

@ -0,0 +1,9 @@
rpc:
limits:
- methods:
- /neo.fs.v2.object.ObjectService/PutSingle
- /neo.fs.v2.object.ObjectService/Put
max_ops: 0
- methods:
- /neo.fs.v2.object.ObjectService/Get
max_ops: 10000