-
Notifications
You must be signed in to change notification settings - Fork 362
Example of DataLoaders. #396
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
Conversation
Codecov Report
@@ Coverage Diff @@
## master #396 +/- ##
=========================================
Coverage 97.62% 97.62%
Complexity 324 324
=========================================
Files 104 104
Lines 1223 1223
Branches 198 198
=========================================
Hits 1194 1194
Misses 9 9
Partials 20 20
Continue to review full report at Codecov.
|
Thanks for providing the example! I've added default support to Would you mind updating the example to use latest code? |
I guess we need to create DataLoaderRegistry per request, to avoid passing cached values between requests? I'm not sure how to do it with #400. Maybe we need to autowire some factory, that creates dataLoaderRegistry, I saw a similar way in SPQR lib: DataLoaderRegistryFactory |
Interesting! So data loader registry should be created per request? I've added support for this in #410 by creating factory that allows developers to create new data loader registry instance per query execution. Unsure how useful it is as within |
👍 Plus one to this:
In graphql-java land, I can see how this is a helpful caching mechanism since you don't have a class that is run when you execute a resolver/data fetcher. But with our library you will be executing a function that can be in any scope and fetching data from a downstream service can be cached in any way you want. This feature will be something we can support through the factory but we will defer handling of everything else to the server devs. |
Could you give me some direction on how it can be implemented? |
If you have this class and function as your schema object class Query {
fun getUserById(id: Int): User? {
val result = getUserFromSource(id)
return result
}
} the |
If I understand correctly, we can use it to load from cache/service/etc by id, one by one, but if we want to batch our request, we need to gather all needed ids, and then execute our query. |
Yep. It all drills down to how you gather those IDs -> you need to know all of them to batch regardless whether you use data loader or not. |
|
||
@Component("CompanyDataFetcher") | ||
@Scope("prototype") | ||
class CompanyDataFetcher : DataFetcher<CompletableFuture<Company>>, BeanFactoryAware { |
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.
@smyrick hey. Am I understand that correctly that this thing will be called anytime somebody queries the company
field company
lateinit var Company
on Employee and ONLY the Employee, and not other classes?
Or I have to branch here or whatever?
Maybe some drawing or ASCII or draw.io graph will help me understand the connection between beans and the whole resolve cycle as I'm unsure :)
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.
@RIP21 The DataFetcher is the name of the "resolver" for graphql-java. You can see the docs here: https://www.graphql-java.com/documentation/v16/data-fetching/
This is a data fetcher for the entire Company
class. GraphQL Kotlin normally would handle creating the different data fetchers for you, but in this case the user wanted have a DataLoader
which is a separate GraphQL specific caching mechanism. The DataFetcher
is invoked when ever there is a field that returns a Company
and, using DataLoader
s, they are cache the company info for each employee so they don't have to make multiple calls to get the the duplicate company data for all the employees
📝 Description
I've asked about using dataLoaders in the related issue, so here is my example of its possible implementation, using an extension of a query handler. What do you think?
Note that I also made ExecutionResult.toGraphQLResponse() function public in this PR.
🔗 Related Issues
#381