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

Errors thrown from resolvers have the execution path #396

Merged
merged 10 commits into from
Jun 10, 2016
Merged

Errors thrown from resolvers have the execution path #396

merged 10 commits into from
Jun 10, 2016

Conversation

Slava
Copy link
Contributor

@Slava Slava commented Jun 1, 2016

I tried my best to make changes as least disruptive as possible.

The execution path is different from the location on errors, it is the path on the actual data, rather than the query, so you can tell precisely which element's resolver caused the error.

This information is also propagated in the info argument to resolvers for an opportunity of better instrumentation for tools like Apollo.

@ghost ghost added the CLA Signed label Jun 1, 2016
This path is also passed in the `info` object to resolvers.
This information is useful for ease of debugging and more detailed logging.
@coveralls
Copy link

Coverage Status

Coverage increased (+0.01%) to 98.297% when pulling 710f92c on meteor:master into 359ec76 on graphql:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.01%) to 98.299% when pulling a5ef8c7 on meteor:master into 359ec76 on graphql:master.

@helfer
Copy link
Contributor

helfer commented Jun 1, 2016

@leebyron If you have some time, could you take a quick look at this PR and give us feedback? This is something that would be really useful for Apollo and other projects for a couple of reasons:

  1. It provides better error messages to developers
  2. It lets GraphQL clients do smarter things with errors, such as discarding part of the result and not updating the store.
  3. It lets UI frameworks display errors in the context where they make the most sense.
  4. It's a step towards sending normalized partial responses. Also helpful for streaming.
  5. It's also a step towards doing logging and profiling that knows about causal relationships (which resolver had to wait for which other resolver).

@stealthybox
Copy link

I just wanted to say a huge thank you to @helfer and the meteor team for pushing this functionality in response to my questions on Slack.
The work on this is incredible, and Errors are much clearer now.

I would like to highlight that this PR is not just restricted to error handling.
@Slava mentioned that the executionPath is included in info for all resolvers.
The ability to leverage the executionPath in resolve functions allows for communication of that path to the client.
This is a powerful construct that allows is the center of memoization, query-minification, and subscription in projects like Falcor.

I have been playing with builds of this fork for the past few days now -- the functionality appears to work as expected with nested Type and Field level resolve functions when querying with redundant fields and relations.

This PR totally gets my thumbs up.
I'm super excited about it.

@JeffRMoore
Copy link
Contributor

I really like the idea of giving path information to the resolve function. It feels like the right abstraction to me for describing location (vs AST).

However, it seems like a lot of work and memory allocation, creating a path array for every value in the result.

Worth it?

@Slava
Copy link
Contributor Author

Slava commented Jun 3, 2016

@JeffRMoore I think it is a fair question to ask, I was considering two possible implementations:

  • copy the whole path whenever there is a need to extend the list (implemented in this PR)
  • have an implementation of a persistent single-linked list (that looks like a tree, essentially)

I decided to go with a simpler implementation that behaves just like a regular JS array to begin with. Since we are talking about this information being useful in a context of instrumentation and profiling, it seems like it makes sense to sacrifice a couple of object allocations per request for better tooling to reveal a much bigger sink of time?

@Slava Slava mentioned this pull request Jun 9, 2016
@leebyron
Copy link
Contributor

Sorry for the delay - this looks really good. We need this for some of the future proposals as well.

Major feedback is that we shouldn't need to introduce another kind of Error. The path should just be added to GraphQLError when necessary.

I'll add a few inline comments as well.

@@ -483,6 +483,7 @@ export type GraphQLResolveInfo = {
rootValue: mixed,
operation: OperationDefinition,
variableValues: { [variableName: string]: mixed },
executionPath: Array<string | number>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be more accurately called responsePath since it describes the path the value occurs in the response, rather than the charted path in the executor. Though I think simply path is descriptive enough.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.01%) to 98.297% when pulling eba89d4 on meteor:master into 359ec76 on graphql:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.01%) to 98.297% when pulling eba89d4 on meteor:master into 359ec76 on graphql:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.01%) to 98.297% when pulling 6301f5a on meteor:master into 359ec76 on graphql:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.01%) to 98.296% when pulling 7a5be6a on meteor:master into 359ec76 on graphql:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.01%) to 98.3% when pulling b33d1a1 on meteor:master into 359ec76 on graphql:master.

@Slava
Copy link
Contributor Author

Slava commented Jun 10, 2016

@leebyron I have updated the PR responding to all your comments. Let me know if there is anything else I can do to improve this PR. If everything is clear, we can squash everything into 1 change.

};

// Get the resolve function, regardless of if its result is normal
// or abrupt (error).
const result = resolveOrError(resolveFn, source, args, context, info);

return completeValueCatchingError(
const completed = completeValueCatchingError(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can continue to return directly.

@leebyron
Copy link
Contributor

This is looking really nice, thanks for your quick follow-ups!

@Slava
Copy link
Contributor Author

Slava commented Jun 10, 2016

updated

@coveralls
Copy link

Coverage Status

Coverage increased (+0.01%) to 98.3% when pulling 3641873 on meteor:master into 359ec76 on graphql:master.

@helfer
Copy link
Contributor

helfer commented Jun 10, 2016

@leebyron Could we turn off the coveralls comments? They're really breaking up the flow. I believe there's a repo setting in coveralls for that. We've done it for all the Apollo repos.

@leebyron
Copy link
Contributor

Good idea, @helfer, just did that for this repo, will do it for the others soon.

@leebyron leebyron merged commit 6223245 into graphql:master Jun 10, 2016
@leebyron
Copy link
Contributor

This is great work, @Slava!

sogko added a commit to sogko/graphql-js that referenced this pull request Jan 27, 2017
Merge commit '826cba3b76e87dbd25a01db5150f89624adaab32' into sogko/master

* commit '826cba3b76e87dbd25a01db5150f89624adaab32':
  0.6.1
  Fix tests for node v0.10, widen test matrix
  Fix test assertions for validation test when using custom TypeInfo (graphql#395)
  Removes depencency on babel-runtime.
  Upgrade to Flow v0.28.
  More specific return types from methods in Schema
  Only type Scalar config rather than Scalar type, improve schema builder types
  Introduce formal definition of "Thunk" to aid in fixing more issues uncovered by Flow v0.28
  Additional flow issues corrected in anticipation of Flow v0.28
  Fix some flow issues in anticipation of Flow v0.28
  export type InputObjectConfigFieldMapThunk (graphql#411)
  Variable naming follow-up to path generation
  Errors thrown from resolvers have the execution path (graphql#396)
  Update all dependencies, include flow-specific lint handling
  Revert "Update babel-cli and flow-bin package references" (graphql#403)
  move babel config to the babelrc (graphql#399)
  Update babel-cli and flow-bin package references (graphql#388)
  Fix typo (graphql#387)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants