Skip to content

Commit 569e06f

Browse files
HearyShentpfz
andauthored
[feat][evaluation] add plain limiter factory (#297)
* feat: add evaluator-level rate limit to RunEvaluator * feat: add evaluator-level rate limit to RunEvaluator * fix trace * feat: add evaluator-level rate limit to RunEvaluator * fix: fix the authBuiltinManagement R/W auth issue * feat: add plain limiter factory * feat: add more condition protection for plain limiter factory --------- Co-authored-by: tpfz <[email protected]>
1 parent 64659d9 commit 569e06f

File tree

15 files changed

+233
-85
lines changed

15 files changed

+233
-85
lines changed

backend/api/api.go

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/api/handler/coze/loop/apis/wire.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ import (
1010
"context"
1111

1212
"github.com/cloudwego/kitex/pkg/endpoint"
13+
"github.com/google/wire"
14+
1315
"github.com/coze-dev/coze-loop/backend/kitex_gen/coze/loop/evaluation/experimentservice"
1416
task_processor "github.com/coze-dev/coze-loop/backend/modules/observability/domain/task/service/taskexe/processor"
15-
"github.com/google/wire"
1617

1718
"github.com/coze-dev/coze-loop/backend/infra/ck"
1819
"github.com/coze-dev/coze-loop/backend/infra/db"
@@ -169,6 +170,7 @@ func InitEvaluationHandler(
169170
fileClient fileservice.Client,
170171
tagClient tagservice.Client,
171172
objectStorage fileserver.ObjectStorage,
173+
plainLimiterFactory limiter.IPlainRateLimiterFactory,
172174
) (*EvaluationHandler, error) {
173175
wire.Build(
174176
evaluationSet,

backend/api/handler/coze/loop/apis/wire_gen.go

Lines changed: 3 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/cmd/main.go

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func main() {
5252
panic(err)
5353
}
5454

55-
handler, err := api.Init(ctx, c.idgen, c.db, c.redis, c.cfgFactory, c.mqFactory, c.objectStorage, c.batchObjectStorage, c.benefitSvc, c.auditClient, c.metric, c.limiterFactory, c.ckDb, c.translater)
55+
handler, err := api.Init(ctx, c.idgen, c.db, c.redis, c.cfgFactory, c.mqFactory, c.objectStorage, c.batchObjectStorage, c.benefitSvc, c.auditClient, c.metric, c.limiterFactory, c.ckDb, c.translater, c.plainLimiterFactory)
5656
if err != nil {
5757
panic(err)
5858
}
@@ -118,19 +118,20 @@ func getComponentConfig(configFactory conf.IConfigLoaderFactory) (*ComponentConf
118118
}
119119

120120
type component struct {
121-
idgen idgen.IIDGenerator
122-
db db.Provider
123-
redis redis.Cmdable
124-
cfgFactory conf.IConfigLoaderFactory
125-
mqFactory mq.IFactory
126-
objectStorage fileserver.ObjectStorage
127-
batchObjectStorage fileserver.BatchObjectStorage
128-
benefitSvc benefit.IBenefitService
129-
auditClient audit.IAuditService
130-
metric metrics.Meter
131-
limiterFactory limiter.IRateLimiterFactory
132-
ckDb ck.Provider
133-
translater i18n.ITranslater
121+
idgen idgen.IIDGenerator
122+
db db.Provider
123+
redis redis.Cmdable
124+
cfgFactory conf.IConfigLoaderFactory
125+
mqFactory mq.IFactory
126+
objectStorage fileserver.ObjectStorage
127+
batchObjectStorage fileserver.BatchObjectStorage
128+
benefitSvc benefit.IBenefitService
129+
auditClient audit.IAuditService
130+
metric metrics.Meter
131+
limiterFactory limiter.IRateLimiterFactory
132+
ckDb ck.Provider
133+
translater i18n.ITranslater
134+
plainLimiterFactory limiter.IPlainRateLimiterFactory
134135
}
135136

136137
func initTracer(handler *apis.APIHandler) error {
@@ -250,19 +251,20 @@ func newComponent(ctx context.Context) (*component, error) {
250251
}
251252

252253
return &component{
253-
idgen: idgenerator,
254-
db: db,
255-
redis: cmdable,
256-
cfgFactory: cfgFactory,
257-
mqFactory: rocketmq.NewFactory(),
258-
objectStorage: objectStorage,
259-
batchObjectStorage: objectStorage,
260-
benefitSvc: benefit.NewNoopBenefitService(),
261-
auditClient: audit.NewNoopAuditService(),
262-
metric: metrics.GetMeter(),
263-
limiterFactory: dist.NewRateLimiterFactory(cmdable),
264-
ckDb: ckDb,
265-
translater: translater,
254+
idgen: idgenerator,
255+
db: db,
256+
redis: cmdable,
257+
cfgFactory: cfgFactory,
258+
mqFactory: rocketmq.NewFactory(),
259+
objectStorage: objectStorage,
260+
batchObjectStorage: objectStorage,
261+
benefitSvc: benefit.NewNoopBenefitService(),
262+
auditClient: audit.NewNoopAuditService(),
263+
metric: metrics.GetMeter(),
264+
limiterFactory: dist.NewRateLimiterFactory(cmdable),
265+
ckDb: ckDb,
266+
translater: translater,
267+
plainLimiterFactory: dist.NewPlainLimiterFactory(cmdable),
266268
}, nil
267269
}
268270

backend/infra/limiter/dist/dist.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,9 @@ func WithExprCacheSize(size int) FactoryOpt {
3636
type factoryOpt struct {
3737
exprCacheSize int
3838
}
39+
40+
func NewPlainLimiterFactory(cmdable redis.Cmdable) limiter.IPlainRateLimiterFactory {
41+
return &plainLimiterFactory{
42+
cmdable: cmdable,
43+
}
44+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package dist
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/go-redis/redis_rate/v10"
7+
8+
"github.com/coze-dev/coze-loop/backend/infra/limiter"
9+
"github.com/coze-dev/coze-loop/backend/infra/redis"
10+
"github.com/coze-dev/coze-loop/backend/pkg/logs"
11+
)
12+
13+
type plainLimiterFactory struct {
14+
cmdable redis.Cmdable
15+
}
16+
17+
func (f *plainLimiterFactory) NewPlainRateLimiter(opts ...limiter.FactoryOptionFn) limiter.IPlainRateLimiter {
18+
opt := &limiter.FactoryOption{}
19+
for _, fn := range opts {
20+
fn(opt)
21+
}
22+
23+
rawRedis, ok := redis.Unwrap(f.cmdable)
24+
if !ok {
25+
panic(fmt.Errorf("redis cmdable must be unwrappable"))
26+
}
27+
28+
rl := &rateLimiter{
29+
rules: make([]*rule, 0, len(opt.Rules)),
30+
limiter: redis_rate.NewLimiter(rawRedis),
31+
}
32+
33+
for _, r := range opt.Rules {
34+
if rr, err := rl.newRule(r); err != nil {
35+
logs.Error("rate limiter set rule failed, rule: %v, err: %v", r, err)
36+
} else {
37+
rl.addRule(rr)
38+
}
39+
}
40+
41+
return rl
42+
}

backend/infra/limiter/limiter.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,13 @@ type Limit struct {
7979
Burst int `json:"burst" yaml:"burst" mapstructure:"burst"`
8080
Period time.Duration `json:"period" yaml:"period" mapstructure:"period"`
8181
}
82+
83+
//go:generate mockgen -destination=mocks/rate_limiter_factory.go -package=mocks . IPlainRateLimiterFactory
84+
type IPlainRateLimiterFactory interface {
85+
NewPlainRateLimiter(opts ...FactoryOptionFn) IPlainRateLimiter
86+
}
87+
88+
//go:generate mockgen -destination=mocks/rate_limiter.go -package=mocks . IPlainRateLimiter
89+
type IPlainRateLimiter interface {
90+
AllowN(ctx context.Context, key string, n int, opts ...LimitOptionFn) (*Result, error)
91+
}

backend/infra/limiter/mocks/rate_limiter.go

Lines changed: 20 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/infra/limiter/mocks/rate_limiter_factory.go

Lines changed: 22 additions & 21 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)