-
Notifications
You must be signed in to change notification settings - Fork 17
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 subscriptions yielding errors #170
Comments
FYI, worth noting that GraphQL executable schema (IIRC, but could be just yoga) allows returning an So this doesn't technically only affect subscriptions but also other resolvers. Would be nice if grats could permit any Error type to be returned and ignores it |
It is a
|
I think I found it. Here it is: Not really well documented afaik |
Interesting. It does sound like a thing that would be nice to be able to do. Am I following correctly that the goal here is to get the iterable itself to not error, but allow an individual item within the iterable to be in an error state? I think Grats will limit itself to only having built in support for things which work out of the box with I wonder if it's possible in graphql-js to yield a promise that rejects and get the behavior you want? Related: graphql-js' handling of AsyncIterators: https://github.com/graphql/graphql-js/blob/16.x.x/src/execution/mapAsyncIterator.ts#L7-L57 |
Yeah I suspect there may be a use case for yielding an error and then carrying on yielding successful results. I wouldn't rule that out at least. The issue here isn't about what graphql-js is capable of, but the typing of the iterator. I think /**
* gqlSubscriptionField
*/
function myField(): AsyncIterable<MyType | GraphQLFormattedError> {
yield myType;
yield new GraphQLFormattedError('Something bad happened');
} The easiest way imho would be to parse the union type declaration in the return type and extract |
My hope was that there was some other way to structure this code such that the error is thrown instead of returned while still achieving the same observable behavior from the perspective of the GraphQL consumer. Can we confirm that there is no way to structure this code such that we don't have to return the error and can instead throw it (as we do with all other errors in graphql-js)? Also, I'm a little unclear from the above discussion: Is the handling of yielded errors something graphql-js does, or a feature of graphql-tools makeExecutableSchema? If the latter, then I don't think Grats can safely ignore the error in the example you gave, since the user may be using graphql-js |
I can't find much documentation for this, but judging from this test, it seems that calling However, calling I will investigate if the above is handled in |
I just did a very basic test using Here is some test code: // server.ts
import { buildSchema } from 'graphql';
import { useServer } from 'graphql-ws/lib/use/ws';
import { WebSocketServer } from 'ws';
const schema = buildSchema(`
type Query {
hello: String
}
type Subscription {
greetings: String
}
`);
const roots = {
query: {
hello: () => 'Hello World!',
},
subscription: {
greetings: async function* greetings() {
yield new Error('foo');
yield { greetings: 'Hello!' };
},
},
};
const server = new WebSocketServer({
port: 4000,
path: '/graphql',
});
useServer({ schema, roots }, server);
console.log('Listening to port 4000'); // sub.ts
import { createClient } from 'graphql-ws';
const client = createClient({
url: 'ws://localhost:4000/graphql',
});
(async () => {
const subscription = client.iterate({
query: 'subscription { greetings }',
});
for await (const event of subscription) {
console.log(JSON.stringify({ event }));
}
})().catch((err) => {
console.error('Error', err);
}); npx tsx --watch server.ts
npx tsx sub.ts
{"event":{"data":{"greetings":null}}}
{"event":{"data":{"greetings":"Hello!"}}} I suspect that this is just not well-defined in the GraphQL spec. I can't find any good documentation on it. Also, calling |
Yeah, I expect this to be up to the implementor (graphql-js in our case).
So maybe this is a feature request (or at least a documentation request)
for graphql-js? Specifically, maybe there’s some way they could enable
throwing an error which can be interpreted as just that one payload
erroring and does not tear down the entire subscription?
Jordan Eldredge
jordaneldredge.com
@captbaritone <http://twitter.com/captbaritone>
…On Fri, Jan 31, 2025 at 9:38 AM Fela Maslen ***@***.***> wrote:
I just did a very basic test using graphql (without yoga or any other
libraries), and yield new Error() does not seem to send errors through to
the response. As far as I can tell, this seems to be a gap in the GraphQL
spec when it comes to subscriptions. Maybe it's left open to interpretation
by implementations?
Here is some test code:
// server.tsimport { buildSchema } from 'graphql';import { useServer } from 'graphql-ws/lib/use/ws';import { WebSocketServer } from 'ws';
const schema = buildSchema(` type Query { hello: String } type Subscription { greetings: String }`);
const roots = {
query: {
hello: () => 'Hello World!',
},
subscription: {
greetings: async function* greetings() {
yield new Error('foo');
yield { greetings: 'Hello!' };
},
},};
const server = new WebSocketServer({
port: 4000,
path: '/graphql',});
useServer({ schema, roots }, server);
console.log('Listening to port 4000');
// sub.tsimport { createClient } from 'graphql-ws';
const client = createClient({
url: 'ws://localhost:4000/graphql',});
(async () => {
const subscription = client.iterate({
query: 'subscription { greetings }',
});
for await (const event of subscription) {
console.log(JSON.stringify({ event }));
}})().catch((err) => {
console.error('Error', err);});
npx tsx --watch server.ts
npx tsx sub.ts
{"event":{"data":{"greetings":null}}}
{"event":{"data":{"greetings":"Hello!"}}}
I suspect that this is just not well-defined in the GraphQL spec. I can't
find any good documentation on it. Also, calling throw new Error() inside
the subscription iterator there actually blows up the whole subscription,
it doesn't send across an error to the client.
—
Reply to this email directly, view it on GitHub
<#170 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AABHXL6GNGULTDGXHBVRSJ32NOYKRAVCNFSM6AAAAABVSIXYE6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDMMRXHA4DCOBUGY>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
Let's say I want to write a subscription, which can yield a known type, or an error. I would expect to be able to do something like this:
This actually works, except it does not pass type check of course.
Adding
| GraphQLFormattedError
to theAsyncIterable
generic type preventsgrats
from generating the schema.Is there an expected pattern here? I'm wondering whether I'm missing something from the docs, or if we need to figure out an implementation for this.
The text was updated successfully, but these errors were encountered: