99designs / 99designs/gqlgen

Allow configuring worker_limit at runtime (server startup and per-request)

Đang mở
#4,269 0 bình luận 0 reaction 0 người được giao Xem trên GitHub
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

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.