github.com/99designs/gqlgen@v0.17.45/graphql/handler/transport/websocket_resolver_error.go (about) 1 package transport 2 3 import ( 4 "context" 5 6 "github.com/vektah/gqlparser/v2/gqlerror" 7 ) 8 9 // A private key for context that only this package can access. This is important 10 // to prevent collisions between different context uses 11 var wsSubscriptionErrorCtxKey = &wsSubscriptionErrorContextKey{"subscription-error"} 12 13 type wsSubscriptionErrorContextKey struct { 14 name string 15 } 16 17 type subscriptionError struct { 18 errs []*gqlerror.Error 19 } 20 21 // AddSubscriptionError is used to let websocket return an error message after subscription resolver returns a channel. 22 // for example: 23 // 24 // func (r *subscriptionResolver) Method(ctx context.Context) (<-chan *model.Message, error) { 25 // ch := make(chan *model.Message) 26 // go func() { 27 // defer func() { 28 // close(ch) 29 // } 30 // // some kind of block processing (e.g.: gRPC client streaming) 31 // stream, err := gRPCClientStreamRequest(ctx) 32 // if err != nil { 33 // transport.AddSubscriptionError(ctx, err) 34 // return // must return and close channel so websocket can send error back 35 // } 36 // for { 37 // m, err := stream.Recv() 38 // if err == io.EOF { 39 // return 40 // } 41 // if err != nil { 42 // transport.AddSubscriptionError(ctx, err) 43 // return // must return and close channel so websocket can send error back 44 // } 45 // ch <- m 46 // } 47 // }() 48 // 49 // return ch, nil 50 // } 51 // 52 // see https://github.com/99designs/gqlgen/pull/2506 for more details 53 func AddSubscriptionError(ctx context.Context, err *gqlerror.Error) { 54 subscriptionErrStruct := getSubscriptionErrorStruct(ctx) 55 subscriptionErrStruct.errs = append(subscriptionErrStruct.errs, err) 56 } 57 58 func withSubscriptionErrorContext(ctx context.Context) context.Context { 59 return context.WithValue(ctx, wsSubscriptionErrorCtxKey, &subscriptionError{}) 60 } 61 62 func getSubscriptionErrorStruct(ctx context.Context) *subscriptionError { 63 v, _ := ctx.Value(wsSubscriptionErrorCtxKey).(*subscriptionError) 64 return v 65 } 66 67 func getSubscriptionError(ctx context.Context) []*gqlerror.Error { 68 return getSubscriptionErrorStruct(ctx).errs 69 }