Skip to content

Commit

Permalink
perf(GraphQL): Part-1: Pagination for root user query is applied at r…
Browse files Browse the repository at this point in the history
…oot auth query (GRAPHQL-854) (#7100)

This PR moves the pagination parameters for root user query to root auth query. This greatly optimizes the number of nodes that need to be processed by child auth queries.
  • Loading branch information
abhimanyusinghgaur committed Dec 10, 2020
1 parent 7f16bf1 commit 5042370
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 11 deletions.
20 changes: 10 additions & 10 deletions graphql/resolve/auth_query_test.yaml
Expand Up @@ -702,11 +702,11 @@
USER: "user1"
dgquery: |-
query {
queryUserSecret(func: uid(UserSecretRoot), orderasc: UserSecret.aSecret, first: 1) {
queryUserSecret(func: uid(UserSecretRoot), orderasc: UserSecret.aSecret) {
id : uid
ownedBy : UserSecret.ownedBy
}
UserSecretRoot as var(func: uid(UserSecret1)) @filter(uid(UserSecretAuth2))
UserSecretRoot as var(func: uid(UserSecret1), first: 1) @filter(uid(UserSecretAuth2))
UserSecret1 as var(func: type(UserSecret)) @filter(eq(UserSecret.ownedBy, "user2"))
UserSecretAuth2 as var(func: uid(UserSecret1)) @filter(eq(UserSecret.ownedBy, "user1")) @cascade
}
Expand Down Expand Up @@ -843,11 +843,11 @@
USER: "user1"
dgquery: |-
query {
queryMovie(func: uid(MovieRoot), orderasc: Movie.content, first: 10, offset: 10) {
queryMovie(func: uid(MovieRoot), orderasc: Movie.content) {
content : Movie.content
dgraph.uid : uid
}
MovieRoot as var(func: uid(Movie1)) @filter((NOT (uid(MovieAuth2)) AND (uid(MovieAuth3) OR uid(MovieAuth4))))
MovieRoot as var(func: uid(Movie1), first: 10, offset: 10) @filter((NOT (uid(MovieAuth2)) AND (uid(MovieAuth3) OR uid(MovieAuth4))))
Movie1 as var(func: type(Movie)) @filter(eq(Movie.content, "A. N. Author"))
MovieAuth2 as var(func: uid(Movie1)) @filter(eq(Movie.hidden, true)) @cascade
MovieAuth3 as var(func: uid(Movie1)) @cascade {
Expand Down Expand Up @@ -878,7 +878,7 @@
USER: "user1"
dgquery: |-
query {
queryMovie(func: uid(MovieRoot), orderasc: Movie.content, first: 10, offset: 10) @cascade {
queryMovie(func: uid(MovieRoot), orderasc: Movie.content) @cascade {
content : Movie.content
regionsAvailable : Movie.regionsAvailable @filter(uid(Region2)) (orderasc: Region.name, first: 10, offset: 10) {
name : Region.name
Expand All @@ -887,7 +887,7 @@
}
dgraph.uid : uid
}
MovieRoot as var(func: uid(Movie3)) @filter((NOT (uid(MovieAuth4)) AND (uid(MovieAuth5) OR uid(MovieAuth6))))
MovieRoot as var(func: uid(Movie3), first: 10, offset: 10) @filter((NOT (uid(MovieAuth4)) AND (uid(MovieAuth5) OR uid(MovieAuth6))))
Movie3 as var(func: type(Movie)) @filter(eq(Movie.content, "MovieXYZ"))
MovieAuth4 as var(func: uid(Movie3)) @filter(eq(Movie.hidden, true)) @cascade
MovieAuth5 as var(func: uid(Movie3)) @cascade {
Expand Down Expand Up @@ -931,7 +931,7 @@
USER: "user1"
dgquery: |-
query {
queryMovie(func: uid(MovieRoot), orderasc: Movie.content, first: 10, offset: 10) {
queryMovie(func: uid(MovieRoot), orderasc: Movie.content) {
content : Movie.content
regionsAvailable : Movie.regionsAvailable @filter(uid(Region7)) (orderasc: Region.name, first: 10, offset: 10) @cascade {
name : Region.name
Expand All @@ -951,7 +951,7 @@
}
dgraph.uid : uid
}
MovieRoot as var(func: uid(Movie8)) @filter((NOT (uid(MovieAuth9)) AND (uid(MovieAuth10) OR uid(MovieAuth11))))
MovieRoot as var(func: uid(Movie8), first: 10, offset: 10) @filter((NOT (uid(MovieAuth9)) AND (uid(MovieAuth10) OR uid(MovieAuth11))))
Movie8 as var(func: type(Movie)) @filter(eq(Movie.content, "MovieXYZ"))
MovieAuth9 as var(func: uid(Movie8)) @filter(eq(Movie.hidden, true)) @cascade
MovieAuth10 as var(func: uid(Movie8)) @cascade {
Expand Down Expand Up @@ -1526,12 +1526,12 @@
USER: "Random"
dgquery: |-
query {
queryPost(func: uid(PostRoot), orderdesc: Post.text, first: 10, offset: 5) {
queryPost(func: uid(PostRoot), orderdesc: Post.text) {
dgraph.type
text : Post.text
dgraph.uid : uid
}
PostRoot as var(func: uid(Post1)) @filter(((uid(QuestionAuth2) AND uid(QuestionAuth3)) OR uid(FbPostAuth4) OR uid(AnswerAuth5)))
PostRoot as var(func: uid(Post1), first: 10, offset: 5) @filter(((uid(QuestionAuth2) AND uid(QuestionAuth3)) OR uid(FbPostAuth4) OR uid(AnswerAuth5)))
Post1 as var(func: type(Post)) @filter(eq(Post.text, "A Post"))
Question1 as var(func: type(Question))
QuestionAuth2 as var(func: uid(Question1)) @filter(eq(Question.answered, true)) @cascade {
Expand Down
2 changes: 2 additions & 0 deletions graphql/resolve/query_rewriter.go
Expand Up @@ -730,9 +730,11 @@ func (authRw *authRewriter) addAuthQueries(
Args: []gql.Arg{{Value: authRw.varName}},
},
Filter: filter,
Args: dgQuery[0].Args,
}

dgQuery[0].Filter = nil
dgQuery[0].Args = nil

// The user query starts from the var query generated above and is filtered
// by the the filter generated from auth processing, so now we build
Expand Down
13 changes: 12 additions & 1 deletion query/query.go
Expand Up @@ -1992,7 +1992,18 @@ func ProcessGraph(ctx context.Context, sg, parent *SubGraph, rch chan error) {
if len(sg.Attr) > 0 {
suffix += "." + sg.Attr
}
span := otrace.FromContext(ctx)
// queries like `Users as var(func: ...)` have Alias = var and don't have an attr. Instead, they
// would have Var = Users. So, if there are a lot of such queries in a single request,
// then it is easier to identify them in traces if we also use Var to construct the span name.
if len(sg.Params.Var) > 0 {
suffix += "." + sg.Params.Var
}
// starting a span for every sub-graph that is processed creates an execution tree in jaeger UI,
// which makes it very easier to understand the flow of request execution.
ctx, span := otrace.StartSpan(ctx, "query.ProcessGraph."+suffix)
defer span.End()

// span timer doesn't show up in jaeger UI directly. Instead, it is part of logs for each span.
stop := x.SpanTimer(span, "query.ProcessGraph"+suffix)
defer stop()

Expand Down

0 comments on commit 5042370

Please sign in to comment.