-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Invoke didEncounterErrors
for known errors during pre-parse.
#3614
Conversation
Previously a missing test.
…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); |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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 expect
tation to be along-side the expect(didEncounterErrors).toBeCalledWith(
on line 1381?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See 66c32f8
There was a problem hiding this 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 {} |
There was a problem hiding this comment.
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 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.
didEncounterErrors
for known errors during pre-parse phases.didEncounterErrors
for known errors during pre-parse.
…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).
To preserve the same behavior as before #3614.
…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).
To preserve the same behavior as before #3614.
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.
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
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
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
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
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
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
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
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 byrunHttpQuery.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
fromError
toGraphQLError
in order to allow such an error to be received bydidEncounterErrors
, which requiresGraphQLError
s. TheGraphQLError
itself is still aninstanceof 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 anError
orGraphQLError
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!