-
Notifications
You must be signed in to change notification settings - Fork 320
Support for resolving exceptions from a subscription #398
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for resolving exceptions from a subscription #398
Conversation
@Munoon Please sign the Contributor License Agreement! Click here to manually synchronize the status of this Pull Request. See the FAQ for frequently asked questions. |
@Munoon Thank you for signing the Contributor License Agreement! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the proposed changes.
My first thought was, there is probably no need for a dedicated contract. We could just expose an additional method on WebSocketGraphQlInterceptor
.
However, a dedicated contract could work better, if it was supported for all transports. As it is right now, it is coupled to each transport handler which is what subscribes to the Publisher
.
One idea would be to intercept and transform the ExecutionResult
in DefaultExecutionGraphQlService
, so that if the data is a Publisher
, it is composed with Flux.onErrorResume
to invoke the SubscriptionExceptionResolver
and return something like a SubscriptionHandlingException
with the List<GraphQLError>
. Each transport handler can then handle this exception and turn it into the appropriate "error" message for the given transport.
Would you like to try and rework this? If not I can also take it from here.
I will gladly make changes. 🙂 However, I'm not sure if I understand you fully correct. As I understand, I should remove calls to |
Yes your understanding is correct, but on further thought, That means a |
Fine, @rstoyanchev, everything is done! Please, review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks very much! Overall headed in the right direction. Some comments below for another iteration.
...n/java/org/springframework/graphql/execution/SubscriptionSingleExceptionResolverAdapter.java
Outdated
Show resolved
Hide resolved
...raphql/src/main/java/org/springframework/graphql/execution/AbstractGraphQlSourceBuilder.java
Outdated
Show resolved
Hide resolved
...main/java/org/springframework/graphql/execution/DelegatingSubscriptionExceptionResolver.java
Outdated
Show resolved
Hide resolved
...main/java/org/springframework/graphql/execution/DelegatingSubscriptionExceptionResolver.java
Outdated
Show resolved
Hide resolved
private Publisher<?> interceptSubscriptionPublisherWithExceptionHandler(Publisher<?> publisher) { | ||
Function<? super Throwable, Mono<DataFetcherResult<?>>> onErrorResumeFunction = e -> | ||
subscriptionExceptionResolver.resolveException(e) | ||
.map(errors -> DataFetcherResult.newResult().errors(errors).build()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure how this even works, since it would emit a DataFetcherResult
while the transport expects the Publisher
to emit ExecutionResult
instances.
I think this should return a Mono.error
with a new exception (e.g. SubscriptionStreamException
) that wraps and exposes the List<GraphQLError>
through a getter. This would force the transport to terminate in the very least, but should actually handle this exception to extract the errors and create an error message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just added a handler of SubscriptionStreamException
in GraphQlWebSocketHandler
(both webflux
and webmvc
). Should I add it somewhere else?
…ion either to single error or list of errors
… with `createDefaultErrors` method
…` and add handlers in transports
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this looks good!
Closes gh-397