Skip to content
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

No way to return an error once the WebSocket connection is established #648

Open
lstrihic opened this issue Sep 20, 2024 · 6 comments
Open

Comments

@lstrihic
Copy link

lstrihic commented Sep 20, 2024

There is no way to return an error once a connection is established.

func (r *Resolver) OnMessage(ctx context.Context, args struct {
	ChatID string
}) (chan *MessageResolver, error) {
	ch := make(chan *MessageResolver)
	msgCh, errCh := r.Service.Subscribe(args.ChatID)
	go func() {
		defer close(ch)
		for {
			select{
			case <-ctx.Done():
				return
			case <-errCh:
				// TODO: how to send error back to client
				return
			case msg, ok := <-msgCh:
				if !ok {
					return
				}
				ch <- &MessageResolver{
					Message: msg,
				}
			}
		}
	}()
	return ch, nil
}

@kamalkech
Copy link

@lstrihic can u share full code example to see how can enable and use ws for graphql-go subscription, thank u

@lstrihic
Copy link
Author

Basically the full example is in the description not sure what else you want me to provide. (updated description code a bit)
We need a way to handle the error when I receive it from an errCh.

I hope this helps.

@kamalkech
Copy link

there is no full example on description

@pavelnikolov
Copy link
Member

I believe that in such cases you have to include some error message or state inside of your message schema. For example, one of the members of the MessageResolver could be an Err field. And then your code would look like this:

func (r *Resolver) OnMessage(ctx context.Context, args struct {
	ChatID string
}) (chan *MessageResolver, error) {
	ch := make(chan *MessageResolver)
	msgCh, errCh := r.Service.Subscribe(args.ChatID)
	go func() {
		defer close(ch)
		for {
			select{
			case <-ctx.Done():
				return
			case err := <-errCh:
				// TODO: how to send error back to client
				ch <- &MessageResolver{
					Err: err,           // treat errors as part of your data
					Message: nil, // this is redundant, but added for clarity
				}
				return
			case msg, ok := <-msgCh:
				if !ok {
					return
				}
				ch <- &MessageResolver{
					Message: msg,
				}
			}
		}
	}()
	return ch, nil
}

Feel free to reopen if you believe that this is an issue with the library.

@lstrihic
Copy link
Author

lstrihic commented Sep 26, 2024

@pavelnikolov yes, you are right, I can do that, but that is not the way to do it. To me it seems like a walk around solution.

Error should be returned by the library, and it should be structured like this:

{
  "data": {
    "onMessage": null
  },
  "errors": [
    {
      "message": "pubsub is not available",
      "path": [
        "onMessage",
        "error"
      ]
    }
  ]
}

So I wanna be able to somehow tell the library that there is an error and a library should return the error.
Maybe something like graphql.AddError(ctx, err).

@pavelnikolov
Copy link
Member

In that case, feel free to reopen the ticket and I'll look into it. By the way PRs are more than welcome. The resolver would return an error exactly in the format you provided if the error occurred initially. After that it's just messages in this simple implementation.

@pavelnikolov pavelnikolov reopened this Sep 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants