-
Notifications
You must be signed in to change notification settings - Fork 40
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
fix: Determine if query is introspection query #1255
fix: Determine if query is introspection query #1255
Conversation
Codecov Report
@@ Coverage Diff @@
## develop #1255 +/- ##
===========================================
+ Coverage 70.12% 70.20% +0.08%
===========================================
Files 183 184 +1
Lines 17373 17394 +21
===========================================
+ Hits 12182 12212 +30
+ Misses 4253 4247 -6
+ Partials 938 935 -3
|
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.
LGTM. I assume this will help our support of GraphQL clients.
@@ -37,7 +35,7 @@ func (db *db) execRequest(ctx context.Context, request string, txn datastore.Txn | |||
return res | |||
} | |||
|
|||
pub, subRequest, err := db.checkForClientSubsciptions(parsedRequest) | |||
pub, subRequest, err := db.checkForClientSubscriptions(parsedRequest) |
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.
praise: Thanks for catching this typo!
@@ -39,7 +39,7 @@ func (db *db) checkForClientSubsciptions(r *request.Request) ( | |||
return pub, subRequest, nil | |||
} | |||
|
|||
return nil, nil, client.NewErrUnexpectedType[request.ObjectSubscription]("SubcriptionSelection", s) | |||
return nil, nil, client.NewErrUnexpectedType[request.ObjectSubscription]("SubscriptionSelection", s) |
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.
praise: Again for catching the typo. That's on me... Subscription is my most error prone word haha!
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.
The code looks good, but I think the solution needs discussion as I think it is breaking the GQL spec in a different way IMO that will just need to be redone sometime soon anyway.
for _, selection := range astOpDef.SelectionSet.Selections { | ||
switch node := selection.(type) { | ||
case *ast.Field: | ||
if node.Name.Value == "__schema" || node.Name.Value == "__type" { |
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.
discussion: I think we need to rethink the whole introspection flow, I believe these are valid GQL elements within a 'normal' query (like __typename, which we do currently support).
In the short-term it might still be work checking the name (or whichever prop it is) equals "IntrospectionQuery" - checking for __schema
/__type
could incorrectly flag normal queries as introspection only and cause them to miss the main query code blocks (i.e. planner)
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.
I think those values are specifically for introspection: https://graphql.org/learn/introspection
They wouldn't be used on a normal query.
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.
They are valid within a normal query though, pretty sure you are free to use them within any part of any query
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.
A normal query with sub introspection queries?
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.
I might be wrong actually - they are root only. They can however be used alongside normal query/mutations within the same request (top-level) only, which we dont yet support and this solution doesnt cause problems for that.
@orpheuslummis had a chat with me a month or so about __schema/__type when looking at the gql client problem - he might know an example?
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.
By my read of the spec and of the graphql ecosystem.
This looks valid.
query {
users {
name
}
__type (name: "users") {
name
}
}
While this doesn't look valid.
query {
users {
name
__type (name: "users") {
name
}
}
}
I don't have an example of the later.
The first is compliant and required. Implementing the later could be perhaps be compliant and useful, but is not necessary for compliance (in my understanding.
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.
supporting introspection queries along with normal ones is not supported yet.
I think we should merge this one as is, because it's a good step forward and IMO should be in 0.5.0.
And create another task to support different types of queries.
What do you think @AndrewSisley?
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.
I agree in that we shouldn't try to support multiple request operations in a single request. We didn't support it prior to this PR so I see no reason to accommodate our now.
Should be done in another pr, but it's fairly low priority ATM.
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.
supporting introspection queries along with normal ones is not supported yet.
No, but I was concerned that we are putting effort into a solution that doesnt help us in the long term, by continuing to treat introspection elements as a 'special other', when in reality they can/might be embedded anywhere within a request block.
Looking for __schema/__type elements is better than string contains, but it is applying more effort into what I think might be the wrong direction (treating introspection as a special 'other' that doesn't get fed into the planner).
Sounds like this concern is not shared (or at least not thought of as a blocker) though, so crack on and merge once everything else is sorted :)
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.
I don't see this hindering or blocking the ability to do multiple operations per request. If anything, Islams approach to actually using the AST here opens the door to "splitting" the AST into planner and introspection requests, executing them independently, and merging the final results.
I can't necessarily think of a reason why you would ever want/need to run both a introspection and a regular query tho 🙃.
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.
Issue regarding duplicating ast parsing which is (relatively) expensive.
db/request.go
Outdated
@@ -22,8 +21,7 @@ import ( | |||
// execRequest executes a request against the database. | |||
func (db *db) execRequest(ctx context.Context, request string, txn datastore.Txn) *client.RequestResult { | |||
res := &client.RequestResult{} | |||
// check if its Introspection request | |||
if strings.Contains(request, "IntrospectionQuery") { | |||
if db.parser.IsIntrospection(request) { |
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.
todo: One notable problem currently is you are duplicating the buildAST
call if it isn't an introspection request. Which is a somewhat expensive operation in the grand scheme of the request execution.
Can we find a way to call it once, perhaps exposing the BuildAST
and calling it within execRequest
and passing the built/parsed AST to all the other places we currently pass the raw request to.
Alternatively Parse
could return both the built AST and the parsed request. Not sure which is better.
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.
I was going to flag this, benched it, and changed my mind - the code in buildAST
only took 17 microseconds on first run locally of the query in TestQueryOneToOne
. It is a bit ugly, but IMO it isnt really worth worrying over just yet (this is quite localized code too)?
It is quite hard to give a concrete answer to this, but at what kind of cost would you (John) currently draw the line on performance stuff?
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.
I agree with John. I wanted myself to extract this method but held back because I wasn't sure I should change the interface.
cedb3f4
to
f95afa4
Compare
Parse query content query to determine introspection Remove hard-coded IntrospectionQuery from tests
Parse query content query to determine introspection Remove hard-coded IntrospectionQuery from tests
Relevant issue(s)
Resolves #911
Description
This PR removes hard-coded string search for "IntrospectionQuery" and replaces it with a method that checks it's content.
It also adjusts all the tests.
Tasks
How has this been tested?
Integration tests
Specify the platform(s) on which this was tested: