oliyh / re-graph

A graphql client for clojurescript and clojure

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Error not bubbling to Callback

Wolfgang51 opened this issue · comments

Recently I've been trying to implement Error Handling with some of the re-graph queries I've implemented. However, for some reason, if there is an error with the call (ex. Query isn't named correctly) the error doesn't bubble to the callback for the query. That being said, the console window does show an error. Any ideas on why this may be?

Cljs code

;; query fn
(defn query-get-foo
  [callback]
  (re-frame/dispatch
    [::re-graph/query
     "query GetFoo {
         get_foo{
           buzz
         }
      }"
     {}
     callback]))

(defn on-get-foo-handler
  "Gets response from GetContent and stores in db"
  [db [_ {:keys [data errors] :as payload}]]
  (println (str "errors::" errors))
  (assoc-in db [:query :foo] (:get_foo data)))

;; callback function
(re-frame/reg-event-db
  ::on-get-foo
  on-get-foo-handler)

(defn fetch-handler
  [_ [_ query-fn]]
  (js/setTimeout
    (fn []
      query-fn)
    200)
  {})

(re-frame/reg-event-fx
  ::fetch
  fetch-handler)

(re-frame/dispatch [::events/fetch (data/query-get-foo [::events/on-get-foo])])

Console Error

GraphQL error for :re-graph.internals/default - ce4678z2: Cannot query field `get_fo' on type `QueryRoot'.

Hi,

The general idea is that these are structural errors - errors in your code - and that they are handled with these console errors for you to fix before deployment. For runtime errors, like a parameter being unexpected etc, the query should return a successful status code but populate the errors key in the map that is sent to your callback for you to handle.

I think it not unreasonable that you should be able to provide an error callback to handle these separately but I'm not sure that this is an error you should be handling at runtime as it doesn't seem like there is any corrective action that could be taken.

For that reason I am keen to hear your use case, could you elaborate on what you would do with these errors if you could catch them?

Cheers

Thanks for getting back on this, the use case we are thinking is if Client queries our backend graphql api for a query is no longer supported (maybe that query doesn't exist anymore) that we have a way to handle it. Another case could be that a piece of the query (a field within an object) isn't available. As you said, it might be better to handle these issues separately. With that, I am curious what type of errors might be in the error key of the map within the callback?

Here is an example of errors via websocket and via http - they are quite different. I have purposefully broken the query to see what the errors look like:

https://worldcup-live.glitch.me/graphiql?query=query%20%7B%0A%20%20scocre(matchId%3A%2032)%7B%0A%20%20%20%20timestamp%0A%20%20%20%20match%7B%0A%20%20%20%20%20%20home%20%7B%0A%20%20%20%20%20%20%20%20name%0A%20%20%20%20%20%20%20%20score%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20away%20%7B%0A%20%20%20%20%20%20%20%20name%0A%20%20%20%20%20%20%20%20score%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D&operationName=undefined

If you run it as a query you get a 400 status code and the following body.

{
  "errors": [
    {
      "message": "Cannot query field \"scocre\" on type \"Query\".",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ]
    }
  ]
}

There are some more examples here: https://blog.apollographql.com/full-stack-error-handling-with-graphql-apollo-5c12da407210

If you run it as a subscription you get two messages back on the websocket:

{"type":"error","id":1,"payload":{"name":"TypeError","message":"Cannot read property 'matchId' of undefined"}}
{"type":"error","id":2,"payload":{"message":"This subscription is not defined by the schema."}}

Neither of which match the HTTP message, but I guess that's down to implementation on the server (subscriptions are very poorly defined in the GraphQL spec).

The important thing I guess is that the payload structure is more or less the same - they both have a message key. For that reason it seems reasonable to pipe these as errors back into the callback handler.

I've made this change and pushed it to Clojars as 0.19-SNAPSHOT, try it out and let me know what you think.

Thanks!

By the way I think I was wrong in my assumption:

The general idea is that these are structural errors - errors in your code - and that they are handled with these console errors for you to fix before deployment. For runtime errors, like a parameter being unexpected etc, the query should return a successful status code but populate the errors key in the map that is sent to your callback for you to handle.

I think all errors - whether syntactic errors in the query, or runtime errors on the server, or anything else - are treated the same and should end up in an errors key to be handled by the client. I think I was thrown by the difference between the websocket transport and the http transport.