-
Notifications
You must be signed in to change notification settings - Fork 935
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
Add exception when tryWrite returns false #5557
base: main
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #5557 +/- ##
============================================
- Coverage 74.10% 74.09% -0.02%
+ Complexity 21012 21007 -5
============================================
Files 1819 1819
Lines 77394 77399 +5
Branches 9889 9889
============================================
- Hits 57353 57347 -6
- Misses 15386 15396 +10
- Partials 4655 4656 +1 ☔ View full report in Codecov by Sentry. |
@@ -67,7 +68,7 @@ public void onNext(ExecutionResult executionResult) { | |||
protocol.sendGraphqlErrors(executionResult.getErrors()); | |||
subscription.cancel(); | |||
} | |||
} catch (JsonProcessingException e) { | |||
} catch (JsonProcessingException | ClosedStreamException e) { |
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.
Regardless of the exception type, it would be safe to cancel.
} catch (JsonProcessingException | ClosedStreamException e) { | |
} catch (Throwable e) { |
if (!out.tryWrite(event)) { | ||
throw ClosedStreamException.get(); |
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.
.write()
will raise ClosedStreamException
if it is closed.
if (!out.tryWrite(event)) { | |
throw ClosedStreamException.get(); | |
out.write(event); |
Should we also use write()
in other places to cancel the publisher?
A considering point is that writeError()
in completeWithError()
may cause an error again because out
was closed already. If writeNext()
fails, we may skip writeError()
.
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.
Should we also use
write()
in other places to cancel the publisher?
I think writeError
should be considered to use write
instead of tryWrite
.
armeria/graphql/src/main/java/com/linecorp/armeria/server/graphql/GraphqlWSSubProtocol.java
Line 358 in 89c7cf4
private static void writeError(WebSocketWriter out, String operationId, List<GraphQLError> errors) |
A considering point is that
writeError()
incompleteWithError()
may cause an error again becauseout
was closed already. IfwriteNext()
fails, we may skipwriteError()
.
I think we can fix like this below
private static void writeError(WebSocketWriter out, String operationId, Throwable t) {
...
try {
final String event = serializeToJson(errorResponse);
logger.trace("ERROR: {}", event);
out.write(event);
} catch (Throwable e) {
if (out.isOpen()) {
logger.warn("Error serializing error event", e);
out.close(e);
}
}
}
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.
We may simply return in the begging of the method if t
is an instance of ClosedStreamException
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.
Would you mind adding a test case for the problem you're trying to solve?
I'm trying to solve the problem to clean up the resources and cancel the publisher when |
@@ -352,7 +353,7 @@ private static void writeNext(WebSocketWriter out, String operationId, Execution | |||
"payload", executionResult.toSpecification()); | |||
final String event = serializeToJson(response); | |||
logger.trace("NEXT: {}", event); | |||
out.tryWrite(event); |
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.
Several tryWrite
are still used in this class. Could you also fix it?
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.
btw, do i have to handle for ClosedStreamException
in other place?
What do you think of merging armeria/graphql/src/main/java/com/linecorp/armeria/server/graphql/GraphqlWSSubProtocol.java Line 239 in 73f4765
|
I think we have to
final StreamWriter<Object> streaming = StreamMessage.streaming();
final GraphqlService graphqlService =
GraphqlService.builder()
.enableWebSocket(true)
.runtimeWiring(c -> {
c.type("Subscription",
typeWiring -> typeWiring.dataFetcher("hello", e -> streaming));
})
.build();
assert graphqlService instanceof WebSocketHandler;
final WebSocket out = ((WebSocketHandler) graphqlService).handle(ctx, in); |
Do i have to merge those files in this issue? or make another issue? And, Can i write test based on your suggestion? |
Motivation:
tryWrite
inGraphqlWSSubProtocol.writeNext(...)
can returnfalse
whenWebSocketWriter
is closed which makes not to cancel the publisher and cleanup the resource.Modifications:
tryWrite
returnsfalse
, it throwsClosedStreamException
.ClosedStreamException
is occurred, the exception handler inExecutionResultSubscriber.onNext(...)
can lead to cancel the publisher throughsubscription.cancel()
.Result: