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

Optimize nested resolvers #79

Open
AvivRubys opened this issue Aug 7, 2019 · 3 comments
Open

Optimize nested resolvers #79

AvivRubys opened this issue Aug 7, 2019 · 3 comments

Comments

@AvivRubys
Copy link
Contributor

AvivRubys commented Aug 7, 2019

Agogos has enough schema information to be able to avoid requesting data it does not need in the case of nested resolvers.

For example, consider this schema:

type User {
  name: String!
  comments: [String] @http(url: "comment-service/:name")
}

type Query {
  getUser(name: String!): User @http(url: "user-service")
}

And this query:

{
  getUser(name: "elad.aviv") {
    comments
  }
}

In this case, agogos would call user-service and comment-service, even though it doesn't need any data from user-service.
Agogos has enough information to avoid this, either through Dataloader and more granular resolvers as described here, or resolver-level analysis that can verify which fields are requested and if they have their own resolvers, avoid the top-level request.

@Yshayy
Copy link
Contributor

Yshayy commented Aug 8, 2019

It's interesting if the evaluator can put a fake obj placeholder with partial data (can be based args, such as id), and only it there's a need for obj/parent field that is missing it'll query it.

@AvivRubys
Copy link
Contributor Author

AvivRubys commented Aug 8, 2019

It's interesting if the evaluator can put a fake obj placeholder with partial data (can be based args, such as id), and only it there's a need for obj/parent field that is missing it'll query it.

I think that's the only way this can work. Otherwise, @http or other resolvers would not be able to find the parameters they need.
I have a POC of this working, it marks all fields with @http directives on them and then when @http runs, iterates on the subfields and checks if they're marked. If they all are, it skips resolving and returns the args as the result.
The problem is that it will only work if the argument names correspond to entity fields, which is too implicit.
We could add another directive that maps the arguments to fields. So usually it'll be implicit, but you could make something like this:

type Query {
  getUser(username: String!): User
    @http(url: "user-service/:username")
    @provideField(arg: "username", field: "name")`
}

It's kind of verbose and I'm not sure how it would behave with different orderings of directives but we can probably make it work.

Edit: After sleeping on it, I realized this can still fail if comments would have required an additional field to work. If we could somehow run resolvers in reverse, so each of them could express their dependencies, this would work. Either that or possibly analyzing each resolver's field dependencies? But this starts to feel like a whole lot of very fragile machinery.

@AvivRubys
Copy link
Contributor Author

More on this: graphql/graphql-js#623

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants