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
graphql over rsocket spec #327
base: master
Are you sure you want to change the base?
Conversation
|
||
1. If `REQUEST_STREAM` request does not contain `subscription` GraphQL operation, such request must be rejected with an `ERROR` having `INVALID` as an error code. | ||
2. If `REQUEST_RESPONSE` request does not contain `query` or `mutation` GraphQL operation, such request must be rejected with an `ERROR` having `INVALID` as an error code. | ||
3. Hand |
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.
Hanging bullet item
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.
LGTM. Seems appropriate for an incubating spec.
|
||
## Introduction | ||
|
||
GraphQL protocol is one of the popular API protocol for building modern edge-network communication. This extension specification provides an interoperable structure for metadadata payloads and sub-specification which defines graphql communication over RSocket protocol. |
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.
nit
GraphQL protocol is one of the popular API protocol for building modern edge-network communication. This extension specification provides an interoperable structure for metadadata payloads and sub-specification which defines graphql communication over RSocket protocol. | |
GraphQL protocol is one of the popular API protocols for building modern edge-network communication. This extension specification provides an interoperable structure for metadadata payloads and sub-specification which defines graphql communication over RSocket protocol. |
|
||
## Handling GraphQL operation | ||
|
||
A GraphQL operation can be handled if it is agreed during the RSocket `SETUP` phase and specified in the data-mime type `application/graphql` or if composite metadata enabled, specified in the REQUEST PAYLOAD data mime-type `application/graphql` via [Stream Data MIME Types Metadata Extension](/PerStreamDataMimeTypesDefinition.md). |
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.
Is this inline with https://graphql.org/learn/serving-over-http/, which defines that mime type? Should we reference that?
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.
The spec draft is the place to look, for GraphQL over HTTP. The general practice today is to use application/json
or also application/graphql+json
although the latter is not all that common and is not set in stone. I see the latest draft has changed that to application/graphql-response+json
.
I gather that the intent with application/graphql
is to set up expectations for the use of GraphQL over RSocket but the data-mime
type is really about the format to use and not about choosing a higher level protocol (like sub-protocol in WebSocket). I think clients will simply need to know that a particular RSocket endpoint is for GraphQL when connecting, and the data-mime
type is about agreeing on the format of payloads (e.g. application/json
).
|
||
### Streaming operation | ||
To handle `subscription` GraphQL operation a `REQUESTER` MUST issue a `REQUEST_STREAM` payload. | ||
|
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 guess it never got standardised but do any potential backends support live queries?
https://medium.com/open-graphql/graphql-subscriptions-vs-live-queries-e38302c7ab8e
Mainly because this is where facebooks use of rsocket came from.
|
||
### Handling Graphql errors | ||
|
||
GraphQL errors must be encoded as a normal RSocket `PAYLOAD` with `NEXT` semantic followed by `PAYLOAD` with `COMPLETE` flag (onNext(ERROR_MESSAGE) -> onComplete()). RSocket Protocol `ERROR` must be treated as unexpected interruption of the subscription and MUST not contain any GraphQL data in the payload. |
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.
This doesn't seem right to me.
Compare to https://graphql.org/learn/serving-over-http/#response and https://spec.graphql.org/June2018/#sec-Errors
The spec does say "Event streams may complete in response to an error or simply because no more events will occur." so I'm happy if you know it's correct.
Isn't it valid that a stream has different errors per response, and continues?
Or is this a more serious error like a 501 in HTTP? Maybe this just needs some distinction like request level errors?
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.
There is a distinction between a "request error" and a "partial response".
A request error happens before a GraphQL request is accepted for execution by the GraphQL engine (e.g. parse error, query syntax error, security error, etc.) in which case the whole request fails. I think this should result in an ERROR frame.
Once the GraphQL engine starts execution, the response is considered valid but potentially partial. That is, there may be failures for individual fields (e.g. couldn't fetch the user's LinkedIn profile) which is reflected with a null value + a field specific error in the response. This is called a partial response. A subscription may have such partial responses but those do not mean the subscription ends.
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.
LGTM
|
||
## Handling GraphQL operation | ||
|
||
A GraphQL operation can be handled if it is agreed during the RSocket `SETUP` phase and specified in the data-mime type `application/graphql` or if composite metadata enabled, specified in the REQUEST PAYLOAD data mime-type `application/graphql` via [Stream Data MIME Types Metadata Extension](/PerStreamDataMimeTypesDefinition.md). |
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.
Nitpick:
A GraphQL operation can be handled if it is agreed during the RSocket `SETUP` phase and specified in the data-mime type `application/graphql` or if composite metadata enabled, specified in the REQUEST PAYLOAD data mime-type `application/graphql` via [Stream Data MIME Types Metadata Extension](/PerStreamDataMimeTypesDefinition.md). | |
A GraphQL operation can be handled, if it is agreed upon during the RSocket `SETUP` phase by specifying the data mime-type as `application/graphql` or if composite metadata is enabled and the data mime-type in the REQUEST PAYLOAD is specified as `application/graphql` via [Stream Data MIME Types Metadata Extension](/PerStreamDataMimeTypesDefinition.md). |
|
||
## Handling GraphQL operation | ||
|
||
A GraphQL operation can be handled if it is agreed during the RSocket `SETUP` phase and specified in the data-mime type `application/graphql` or if composite metadata enabled, specified in the REQUEST PAYLOAD data mime-type `application/graphql` via [Stream Data MIME Types Metadata Extension](/PerStreamDataMimeTypesDefinition.md). |
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.
The spec draft is the place to look, for GraphQL over HTTP. The general practice today is to use application/json
or also application/graphql+json
although the latter is not all that common and is not set in stone. I see the latest draft has changed that to application/graphql-response+json
.
I gather that the intent with application/graphql
is to set up expectations for the use of GraphQL over RSocket but the data-mime
type is really about the format to use and not about choosing a higher level protocol (like sub-protocol in WebSocket). I think clients will simply need to know that a particular RSocket endpoint is for GraphQL when connecting, and the data-mime
type is about agreeing on the format of payloads (e.g. application/json
).
|
||
### Single result operation | ||
|
||
To handle `query` or `mutation` GraphQL operation a `REQUESTER` MUST issue a `REQUEST_RESPONSE` payload. |
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.
To handle `query` or `mutation` GraphQL operation a `REQUESTER` MUST issue a `REQUEST_RESPONSE` payload. | |
To send a GraphQL request with a `query` or `mutation` operation, a `REQUESTER` MUST use an RSocket `REQUEST_RESPONSE` interaction. |
GraphQL operation lifecycle is bound to the RSocket REQUEST RESPONSE operation semantic and must follow it as specified by RSocket protocol. | ||
|
||
### Streaming operation | ||
To handle `subscription` GraphQL operation a `REQUESTER` MUST issue a `REQUEST_STREAM` payload. |
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.
To handle `subscription` GraphQL operation a `REQUESTER` MUST issue a `REQUEST_STREAM` payload. | |
To send a GraphQL request with a `subscription` operation, a `REQUESTER` MUST use a `REQUEST_STREAM` interaction. |
|
||
### Handling Graphql errors | ||
|
||
GraphQL errors must be encoded as a normal RSocket `PAYLOAD` with `NEXT` semantic followed by `PAYLOAD` with `COMPLETE` flag (onNext(ERROR_MESSAGE) -> onComplete()). RSocket Protocol `ERROR` must be treated as unexpected interruption of the subscription and MUST not contain any GraphQL data in the payload. |
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.
There is a distinction between a "request error" and a "partial response".
A request error happens before a GraphQL request is accepted for execution by the GraphQL engine (e.g. parse error, query syntax error, security error, etc.) in which case the whole request fails. I think this should result in an ERROR frame.
Once the GraphQL engine starts execution, the response is considered valid but potentially partial. That is, there may be failures for individual fields (e.g. couldn't fetch the user's LinkedIn profile) which is reflected with a null value + a field specific error in the response. This is called a partial response. A subscription may have such partial responses but those do not mean the subscription ends.
### Handling unexpected | ||
|
||
1. If `REQUEST_STREAM` request does not contain `subscription` GraphQL operation, such request must be rejected with an `ERROR` having `INVALID` as an error code. | ||
2. If `REQUEST_RESPONSE` request does not contain `query` or `mutation` GraphQL operation, such request must be rejected with an `ERROR` having `INVALID` as an error code. |
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.
These are not really possible to validate upfront. When a GraphQL request is received, it is not yet parsed. Once it's handed to the GraphQL engine, it does the parsing and decided how to process.
Once the GraphQL engine produces a response, e.g. graphql.ExecutionResult
, we can check if the "data" in that is a Publisher
, and only then can we validate something like this.
There maybe other ways to hook this, e.g. through a graphq.execution.Instrumentation
but generally I don't know if we really need this validation.
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.
There maybe other ways to hook this, e.g. through a graphql.execution.Instrumentation but generally I don't know if we really need this validation.
Is this specifically a GraphQL Java construct? If so I would hesitant to include anything in this sub-spec that is only reasonably achievable by a single Language or existing libraries for a specific language.
Adds a separate dedicated extension spec that describes integration with GraphQL protocol
Motivation:
GraphQL is a popular API protocol that does not has not direct binding to a specific transport. Thus, it is going to be valuable to add an addition that clearly explains how such protocol should be handled when it is run over RSocket