Retrieve parent resolver context into sub-query resolver
See original GitHub issueTL;DR
The use case I’m facing is that I want access to some data computed on the parent resolver in the child resolver.
Description
If we have a query like this:
query {
library (name: "Borders Library") {
id
books (genre: "horror") {
name
code
}
}
The computation of this single query is resolved from an outside-inside fashion. Where the parent library
object type is resolved first, then the books
child object types are resolved at last.
In this child books
resolver, for instance, we might want to sub-set our books based on the library name and book genre.
As the computation flows from outside to inside, it feels pretty natural that it might exist a way to record some notion of state/context in the parent resolver, in a way that it could be accessible from the child resolver to help with the computations.
As far as I know, there’s no way to accomplish this in the current state of the framework. I know it would be fragile to implement some ad-hoc logic for this purpose as in a multi-user case it’s hard to pass context from one block of code to another, where this will most likely fall into a multiple producer-consumer problem.
Proposed solution
There’s one place I think this would fit well, and it’s on the info: Info
object passed to every resolver.
There could be some dict-like or something where you could put stuff in the parent resolver, that might be accessible from the child resolver’s info
parameter.
What have I tried so far
One resolver to rule them all
The most simple solution I can think of is to move all inputs into the parent query like this:
query {
library (name: "Borders Library", book_genre: "horror") {
id
books {
name
code
}
}
And then I can use the parent resolver to compute and populate all fields in one single resolver. But, I feel this solution is no so elegant.
Hacky resolving
By using the info object I can access the raw query, so I could implement the previous solution without moving the books inputs into the parent. In other words, I can retrieve those parameters from the parent resolver from the raw query, and solve everything in one resolver, but making the user think they are different inputs.
### Context object I was thinking of implementing a singleton object to publish some data that the resolvers could access. But the more I think about it, the more complex it sounds because there might be multiple producers and multiple readers. I can’t think of a simple way to coordinate this without unexpected edge cases.
Questions
I want to know if there’s any abstraction that might help me with this use case.
Also as there are no abstractions yet, maybe my approach is a code-smell symptom so feel free to discuss with me any alternatives.
Issue Analytics
- State:
- Created 2 years ago
- Comments:5 (3 by maintainers)
Ah yeah there is a bug open for that: https://github.com/strawberry-graphql/strawberry/issues/843
@Vichoko what might help you is
strawberry.Private
which lets you attach extra information to types without it being exposed in the schema (documentation is coming #450 ).So your query might be implemented like this:
By using
strawberry.Private
you can avoid having to store anything on thecontext
object. As you rightly point out it could lead to some weird bugs.Another thing to note:
strawberry.Private
can annotate any type so you could pass the whole DB instance to theLibrary
type and make use of it in thebooks
resolver. Thats what I do when integrating with Django models and it works well.Hope that helps!