Allow configuring worker_limit at runtime (server startup and per-request)
- Ngôn ngữ chính
- Go
- Star
- 10.8k
- Fork
- 1.3k
- Merge trung bình
- 2 ngày 36 phút
- Pull request đã merge (30 ngày)
- 26
Mô tả
### What happened?
`exec.worker_limit` can only be configured at codegen time via `gqlgen.yml`. gqlgen bakes the value into every generated `graphql.MarshalSliceConcurrently(...)` call as a compile-time integer literal (see `codegen/type.gotpl`), so the slice-marshalling concurrency limit is frozen at generation time. Changing it requires editing `gqlgen.yml` and regenerating the whole server.
### What did you expect?
The ability to configure the worker limit at runtime:
- **Server-wide at startup** — e.g. `srv.SetWorkerLimit(n)`, so the limit can be set from configuration/env without regenerating.
- **Per request** — e.g. from an extension / middleware, so it can be tuned by request shape, tenant, query complexity, headers, etc.
The runtime function `graphql.MarshalSliceConcurrently` already accepts `workerLimit int64` as an argument (`0` = unlimited), so today only the hard-coded codegen literal stands in the way.
### Proposal
Resolve the limit at runtime with the following precedence:
**per-request override > server-wide default > codegen `worker_limit` (fallback).**
- Add `WorkerLimit *int64` to `graphql.OperationContext`, plus `EffectiveWorkerLimit(codegenDefault int64) int64` and `SetWorkerLimit(limit int64)` helpers (`*int64` so "unset" is distinguishable from an explicit `0` = unlimited).
- Add `SetWorkerLimit(int64)` to `executor.Executor` and `handler.Server`; copy it into each `OperationContext` in `CreateOperationContext`.
- Change codegen to emit `ec.EffectiveWorkerLimit({{ .Config.Exec.WorkerLimit }})` instead of the raw literal, keeping the YAML value as the default.
Fully backward compatible: with nothing set at runtime, `EffectiveWorkerLimit` returns the codegen default, so behaviour is unchanged. `MarshalSliceConcurrently`'s signature is untouched.
Usage:
```go
// server-wide at startup
srv.SetWorkerLimit(1000)
// per request, e.g. based on headers / complexity
srv.AroundOperations(func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler {
graphql.GetOperationContext(ctx).SetWorkerLimit(4)
return next(ctx)
})
```
I have a PR ready implementing this.
### versions
- `gqlgen`: `master`
- `go`: `go1.26.5`
Hướng dẫn đóng góp
Đánh giá
Issue này chưa được đánh giá.