-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Open
Labels
SSEServer-Sent EventsServer-Sent Eventshelp wantedExtra attention is neededExtra attention is neededsubscriptionswebsocket
Description
Problem
Interceptors in gqlgen only receive the request context as their first parameter.
For queries and mutations, this works fine because execution is linear:
- Receive request
- Execute resolver
- Return response (context == request context)
For subscriptions, however:
- gqlgen starts a goroutine that publishes values to a channel
- gqlgen reads from this channel and encodes responses
- At this point, the response has no associated context that interceptors can access
As a result, interceptors cannot access or enrich the "response context" (e.g., metadata, tracing, request-scoped values) for subscription payloads.
They only see the request context from when the subscription was created.
Proposed Changes
1. Extend Response struct with a Context field
Current:
type Response struct {
Errors gqlerror.List `json:"errors,omitempty"`
Data json.RawMessage `json:"data"`
Label string `json:"label,omitempty"`
Path ast.Path `json:"path,omitempty"`
HasNext *bool `json:"hasNext,omitempty"`
Extensions map[string]any `json:"extensions,omitempty"`
}Proposed:
type Response struct {
Context context.Context `json:"-"`
Errors gqlerror.List `json:"errors,omitempty"`
Data json.RawMessage `json:"data"`
Label string `json:"label,omitempty"`
Path ast.Path `json:"path,omitempty"`
HasNext *bool `json:"hasNext,omitempty"`
Extensions map[string]any `json:"extensions,omitempty"`
}This allows interceptors to access response-level context.
2. Introduce a SubscriptionField interface for subscription result payloads
Instead of subscription resolvers returning (<-chan *T, error), have them return something like:
type SubscriptionField[T any] interface {
GetContext() context.Context
GetField() T
}So subscription resolvers could return:
(<-chan SubscriptionField[*T], error)This lets each published item carry its own context, which flows naturally into the modified Response.Context.
Some benefit
- Consistent interceptor behavior across queries, mutations, and subscriptions withouth break current interceptor code
- Enables request/response tracing, per-event metadata, and richer observability for subscriptions
- Clean separation of concerns: business payload stays in GetField(), while per-response metadata lives in context.Context
nmazzon
Metadata
Metadata
Assignees
Labels
SSEServer-Sent EventsServer-Sent Eventshelp wantedExtra attention is neededExtra attention is neededsubscriptionswebsocket