99designs / 99designs/gqlgen

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

Aperta
#4,269 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub
Lingua principale
Go
Stelle
10.8k
Fork
1.3k
Merge medio
2g 36m
PR unite (30g)
26

Descrizione

### 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`

Guida per i contributori

Apri la guida per i contributori

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.