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

Invoke didEncounterErrors for known errors during pre-parse. #3614

Merged

Conversation

abernix
Copy link
Member

@abernix abernix commented Dec 16, 2019

Roughly, these "pre-parse" errors come in two forms: When the query was entirely omitted, or APQ (automated persisted query) errors.

Arguably, there may be other forms of pre-parse errors, but those would be entirely unexpected (or based on external factors) and potentially out of scope of the didEncounterErrors life-cycle hook. Such errors would still be caught by runHttpQuery.ts, but we wouldn't have a guarantee that any plugins have been initialized. This is unlikely to improve until we re-work the entirety of the request pipeline in Apollo Server 3.x.

While these errors were in-fact causing errors at runtime that were being delivered to the client, those errors were not being delivered to the plugin's didEncounterErrors hooks, causing reduced visibility by reporting tools which utilize that life-cycle hook.

This commit changes the parent class of InvaidGraphQLRequestError from Error to GraphQLError in order to allow such an error to be received by didEncounterErrors, which requires GraphQLErrors. The GraphQLError itself is still an instanceof Error, so any existing code that leverages such a condition should still work as expected, and I suspect that most other conditions that could be checked on either an Error or GraphQLError should also still remain the same. Despite any absolute certainty here, I'd call this a net-win for reporting errors more reliably to the hook on which they're expected to be received!

…vements).

Previously, a number of APQ errors did not have tests for errors which could
arise at runtime.  These include:

- When the APQ `version` is not a version that we support.  (Currently, the
  only supported `version` is `1`.
- When the APQ `version` is entirely omitted.  (It must be `1`.)
- When the provided APQ `sha256Hash` doesn't match the provided `query`
  during APQ registration.

I'm adding these tests which assert the existing logic without making any
changes to the logic itself prior to making a number of changes to said
logic which will ensure that these (again, existing) errors are _also_
propagated to the `didEncounterErrors` hook (They currently are NOT!).
Roughly, these "pre-parse" errors come in two forms: When the query
was entirely omitted, or APQ (automated persisted query) errors.

Arguably, there is a third form of pre-parse errors, but it would be
unexpected and potentially out of scope of the `didEncounterErrors`
life-cycle hook.  Such an error would still be caught by `runHttpQuery.ts`,
but we wouldn't have a guarantee that our plugins have been initialized.
This is unlikely to improve until we re-work the entirety of the request
pipeline in Apollo Server 3.x.

While these errors were in-fact causing errors at runtime that were being
delivered to the client, those errors were not being delivered to the
plugin's `didEncounterErrors` hooks, causing reduced visibility by reporting
tools which utilize that life-cycle hook.

This commit changes the parent class of `InvaidGraphQLRequestError` from
`Error` to `GraphQLError` in order to allow such an error to be received by
`didEncounterErrors`, which requires `GraphQLError`s.  The `GraphQLError`
itself is still an `instanceof Error`, so any existing code that leverages
such a condition should still work as expected, and I suspect that most
other conditions that could be checked on either an `Error` or
`GraphQLError` should also still remain the same.  Despite any uncertain
here, I'd call this a net-win for reporting errors more reliably to the hook
on which they're expected to be received.

// Only the first request should have resulted in an error, not the
// second.
expect(didEncounterErrors).toHaveBeenCalledTimes(1);
Copy link
Member

Choose a reason for hiding this comment

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

This expectation is duplicated immediately above

Copy link
Member Author

Choose a reason for hiding this comment

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

Intentionally! Added comment to clarify: 21aa570.

Let me know if it makes sense?

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm, in retrospect, you're right that this additional assertion may be confusing and unnecssary. Maybe it would make more sense if I moved the first expecttation to be along-side the expect(didEncounterErrors).toBeCalledWith( on line 1381?

Copy link
Member Author

Choose a reason for hiding this comment

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

See 66c32f8

Copy link
Member

@trevor-scheer trevor-scheer left a comment

Choose a reason for hiding this comment

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

This LGTM! The additions to existing test cases (and new ones) are excellent! Thanks for taking the time to flesh those out further 👍

@@ -93,7 +93,7 @@ export interface GraphQLRequestContext<TContext = Record<string, any>> {

export type ValidationRule = (context: ValidationContext) => ASTVisitor;

export class InvalidGraphQLRequestError extends Error {}
export class InvalidGraphQLRequestError extends GraphQLError {}
Copy link
Member Author

Choose a reason for hiding this comment

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

This changes the parent class of InvaidGraphQLRequestError from Error to GraphQLError in order to allow such an error to be received by didEncounterErrors, which requires GraphQLErrors.

The GraphQLError itself is still an instanceof Error, so any existing code that leverages such a condition should still work as expected, and I suspect that most other conditions that could be checked on either an Error or GraphQLError should also still remain the same. Despite any uncertain here, I'd call this a net-win for reporting errors more reliably to the hook on which they're expected to be received.

@abernix abernix changed the title Invoke didEncounterErrors for known errors during pre-parse phases. Invoke didEncounterErrors for known errors during pre-parse. Dec 17, 2019
@abernix abernix merged commit dcbbc34 into master Dec 17, 2019
@abernix abernix deleted the abernix/deliver-pre-parse-errors-to-didEncounterErrors branch December 17, 2019 11:58
@abernix abernix added this to the Release 2.9.14 milestone Dec 17, 2019
abernix added a commit that referenced this pull request Dec 26, 2019
…rting.

The fix in #3614 changed behavior which was not surfacing errors to the
extensions and request pipeline plugins when those errors occurred during
APQ negotiation.

However, it failed to consider - nor were there any tests - which ensured
that the `apollo-engine-reporting`'s mechanism didn't receive an error
earlier in the request pipeline than previously allowed.

This applies a fix which special-cases the APQ error in this case, and
avoids reporting it to Apollo Graph Manager (which is the same behavior as
before).
abernix added a commit that referenced this pull request Dec 26, 2019
To preserve the same behavior as before #3614.
abernix added a commit that referenced this pull request Dec 27, 2019
…rting.

The fix in #3614 changed behavior which was not surfacing errors to the
extensions and request pipeline plugins when those errors occurred during
APQ negotiation.

However, it failed to consider - nor were there any tests - which ensured
that the `apollo-engine-reporting`'s mechanism didn't receive an error
earlier in the request pipeline than previously allowed.

This applies a fix which special-cases the APQ error in this case, and
avoids reporting it to Apollo Graph Manager (which is the same behavior as
before).
abernix added a commit that referenced this pull request Dec 27, 2019
To preserve the same behavior as before #3614.
abernix added a commit that referenced this pull request Dec 27, 2019
The fix in #3614 changed behavior which was not surfacing errors to the
extensions and request pipeline plugins when those errors occurred during
APQ negotiation.

However, it failed to consider - nor were there any tests - which ensured
that the `apollo-engine-reporting`'s mechanism didn't receive an error
earlier in the request pipeline than previously allowed.

This applies a fix which special-cases the APQ error in this case, and
avoids reporting it to Apollo Graph Manager (which is the same behavior as
before).  We also introduce a test for exercising this regression, though it's
certainly a test which makes sure that the A-E-R functionality works, not
something that tests that errors are not thrown before the expected time
in a more general "extensions"-based sense.
abernix added a commit that referenced this pull request Apr 14, 2020
Previously, prior to the new plugin API, the Apollo Engine Reporting
mechanism was implemented using `graphql-extensions`, the API for which
didn't invoke `requestDidStart` until _after_ APQ had been negotiated.

The new plugin API starts its `requestDidStart` _before_ APQ validation and
various other assertions which weren't included in the `requestDidStart`
life-cycle, even if they perhaps should be in terms of error reporting.

The new plugin API is able to properly capture such errors within its
`didEncounterErrors` lifecycle hook (thanks to
#3614, which
intentionally captures these failures so plugin authors can accurately react
to them), however, for behavioral consistency reasons, we will still
special-case those errors and maintain the legacy behavior to avoid a
breaking change.  We can reconsider this in a future version of Apollo
Engine Reporting (AS3, perhaps!).

Ref: #3614
Ref: #3627
Ref: #3638
abernix added a commit that referenced this pull request Apr 15, 2020
Previously, prior to the new plugin API, the Apollo Engine Reporting
mechanism was implemented using `graphql-extensions`, the API for which
didn't invoke `requestDidStart` until _after_ APQ had been negotiated.

The new plugin API starts its `requestDidStart` _before_ APQ validation and
various other assertions which weren't included in the `requestDidStart`
life-cycle, even if they perhaps should be in terms of error reporting.

The new plugin API is able to properly capture such errors within its
`didEncounterErrors` lifecycle hook (thanks to
#3614, which
intentionally captures these failures so plugin authors can accurately react
to them), however, for behavioral consistency reasons, we will still
special-case those errors and maintain the legacy behavior to avoid a
breaking change.  We can reconsider this in a future version of Apollo
Engine Reporting (AS3, perhaps!).

Ref: #3614
Ref: #3627
Ref: #3638
abernix added a commit that referenced this pull request Apr 15, 2020
This fixes the failing tests which correctly surfaced on the last commit.

Previously, prior to the new plugin API, the Apollo Engine Reporting
mechanism was implemented using `graphql-extensions`, the API for which
didn't invoke `requestDidStart` until _after_ APQ had been negotiated.

The new plugin API starts its `requestDidStart` _before_ APQ validation and
various other assertions which weren't included in the `requestDidStart`
life-cycle, even if they perhaps should be in terms of error reporting.

The new plugin API is able to properly capture such errors within its
`didEncounterErrors` lifecycle hook (thanks to
#3614, which
intentionally captures these failures so plugin authors can accurately react
to them), however, for behavioral consistency reasons, we will still
special-case those errors and maintain the legacy behavior to avoid a
breaking change.  We can reconsider this in a future version of Apollo
Engine Reporting (AS3, perhaps!).

Ref: #3614
Ref: #3627
Ref: #3638
abernix added a commit that referenced this pull request Apr 15, 2020
This fixes the failing tests which correctly surfaced on the last commit.

Previously, prior to the new plugin API, the Apollo Engine Reporting
mechanism was implemented using `graphql-extensions`, the API for which
didn't invoke `requestDidStart` until _after_ APQ had been negotiated.

The new plugin API starts its `requestDidStart` _before_ APQ validation and
various other assertions which weren't included in the `requestDidStart`
life-cycle, even if they perhaps should be in terms of error reporting.

The new plugin API is able to properly capture such errors within its
`didEncounterErrors` lifecycle hook (thanks to
#3614, which
intentionally captures these failures so plugin authors can accurately react
to them), however, for behavioral consistency reasons, we will still
special-case those errors and maintain the legacy behavior to avoid a
breaking change.  We can reconsider this in a future version of Apollo
Engine Reporting (AS3, perhaps!).

Ref: #3614
Ref: #3627
Ref: #3638
abernix added a commit that referenced this pull request Apr 15, 2020
This fixes the failing tests which correctly surfaced on the last commit.

Previously, prior to the new plugin API, the Apollo Engine Reporting
mechanism was implemented using `graphql-extensions`, the API for which
didn't invoke `requestDidStart` until _after_ APQ had been negotiated.

The new plugin API starts its `requestDidStart` _before_ APQ validation and
various other assertions which weren't included in the `requestDidStart`
life-cycle, even if they perhaps should be in terms of error reporting.

The new plugin API is able to properly capture such errors within its
`didEncounterErrors` lifecycle hook (thanks to
#3614, which
intentionally captures these failures so plugin authors can accurately react
to them), however, for behavioral consistency reasons, we will still
special-case those errors and maintain the legacy behavior to avoid a
breaking change.  We can reconsider this in a future version of Apollo
Engine Reporting (AS3, perhaps!).

Ref: #3614
Ref: #3627
Ref: #3638
abernix added a commit that referenced this pull request Apr 15, 2020
This fixes the failing tests which correctly surfaced on the last commit.

Previously, prior to the new plugin API, the Apollo Engine Reporting
mechanism was implemented using `graphql-extensions`, the API for which
didn't invoke `requestDidStart` until _after_ APQ had been negotiated.

The new plugin API starts its `requestDidStart` _before_ APQ validation and
various other assertions which weren't included in the `requestDidStart`
life-cycle, even if they perhaps should be in terms of error reporting.

The new plugin API is able to properly capture such errors within its
`didEncounterErrors` lifecycle hook (thanks to
#3614, which
intentionally captures these failures so plugin authors can accurately react
to them), however, for behavioral consistency reasons, we will still
special-case those errors and maintain the legacy behavior to avoid a
breaking change.  We can reconsider this in a future version of Apollo
Engine Reporting (AS3, perhaps!).

Ref: #3614
Ref: #3627
Ref: #3638
abernix added a commit that referenced this pull request Apr 16, 2020
This fixes the failing tests which correctly surfaced on the last commit.

Previously, prior to the new plugin API, the Apollo Engine Reporting
mechanism was implemented using `graphql-extensions`, the API for which
didn't invoke `requestDidStart` until _after_ APQ had been negotiated.

The new plugin API starts its `requestDidStart` _before_ APQ validation and
various other assertions which weren't included in the `requestDidStart`
life-cycle, even if they perhaps should be in terms of error reporting.

The new plugin API is able to properly capture such errors within its
`didEncounterErrors` lifecycle hook (thanks to
#3614, which
intentionally captures these failures so plugin authors can accurately react
to them), however, for behavioral consistency reasons, we will still
special-case those errors and maintain the legacy behavior to avoid a
breaking change.  We can reconsider this in a future version of Apollo
Engine Reporting (AS3, perhaps!).

Ref: #3614
Ref: #3627
Ref: #3638
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 21, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants