How to use the GraphQL Java Dataloader? #58
-
I am looking at how to use the java dataloader: https://github.com/graphql-java/java-dataloader in my spring-boot-graphql app. Does graphql-java-tools provide support or does the spring-boot app provide this support? I am trying to find some documentation to glue this all together.... any help would be really appreciated! |
Beta Was this translation helpful? Give feedback.
Replies: 74 comments 3 replies
-
Right now the data loader isn't supported by this library or graphql-spring-boot, but there's been some interest and I'm looking at how I could add support for it. |
Beta Was this translation helpful? Give feedback.
-
It would be awesome. When do you think this feature can be ready? Thank you. |
Beta Was this translation helpful? Give feedback.
-
@LeeWong I'd have to look at how DataLoader is implemented in graphql-java, and I haven't had time to do that yet. If you had experience I'd love to hear how you'd like to be able to use it with this library. |
Beta Was this translation helpful? Give feedback.
-
@apottere @soudmaijer I think we should have the ability to create new |
Beta Was this translation helpful? Give feedback.
-
@apottere As you already know dataloader is now included as a dependency for graphql-java v5.0.0. I am really curious what approach you are planning for integrating the dataloader. I was investigating a bit how this could/should work... I create an experiment, see this gist: https://gist.github.com/soudmaijer/3fc6d32a2dad10960556a5e6ce0a5aca#file-graphqljavatoolsdataloader-kt-L21 I was first thinking about just creating a request scoped bean instance of my DataLoader class. The main issue is that after processing all simular items at a certain level in the graph, the DataLoader.dispatch() method must be invoked to fetch the real data. In plain GraphQL java this is handled by the DataLoaderDispatcherInstrumentation. Also see: http://graphql-java.readthedocs.io/en/v5/batching.html What are your ideas? |
Beta Was this translation helpful? Give feedback.
-
Any update on this? |
Beta Was this translation helpful? Give feedback.
-
Any update on this? |
Beta Was this translation helpful? Give feedback.
-
I have a working example for you.
Op 25 nov. 2017 09:47 schreef "Peace Michaels" <[email protected]>:
… Any update on this?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<https://github.com/graphql-java/graphql-java-tools/issues/58#issuecomment-346927539>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AANyty2WNw4i70hNv2jTrtn5AnvZo-xWks5s59Q6gaJpZM4PMDVt>
.
|
Beta Was this translation helpful? Give feedback.
-
I don't have an update on this yet, working on subscription support then I'll focus on this. |
Beta Was this translation helpful? Give feedback.
-
You can just provide @Bean
DataLoaderRegistry dataLoaderRegistry(List<DataLoader<?, ?>> loaderList) {
DataLoaderRegistry registry = new DataLoaderRegistry();
for (DataLoader<?, ?> loader : loaderList) {
registry.register(loader.getClass().getSimpleName(), loader);
}
return registry;
}
@Bean
Instrumentation instrumentation(DataLoaderRegistry dataLoaderRegistry) {
return new DataLoaderDispatcherInstrumentation(dataLoaderRegistry);
} create your DataLoaders, extending base DataLoader, and use DataLoaders in resolvers. @Component
public class ProjectToVolumeDataLoader extends DataLoader<Integer, List<Volume>> {
public ProjectToVolumeDataLoader() {
this(null);
}
public ProjectToVolumeDataLoader(DataLoaderOptions options) {
super(keys -> CompletableFuture.supplyAsync(() -> {
List<List<Volume>> result = new ArrayList<>(keys.size());
... do some magic to fill result (using db, using slow device, etc) ...
... result must be in same order as keys ...
return result;
}), options);
}
} @Component
public class ProjectResolver implements GraphQLResolver<Project> {
private final ProjectToVolumeDataLoader projectToVolumeDataLoader;
public ProjectResolver(ProjectToVolumeDataLoader projectToVolumeDataLoader) {
this.projectToVolumeDataLoader = projectToVolumeDataLoader;
}
public CompletableFuture<List<Volume>> getVolumes(Project project) {
return projectToVolumeDataLoader.load(project.getProjectId());
}
} |
Beta Was this translation helpful? Give feedback.
-
Am I correct in assuming there isn't still a good way to have request scoped DataLoaders? I am using graphql-spring-boot and after some debugging through some resolvers I ended up feeling somewhat lost. |
Beta Was this translation helpful? Give feedback.
-
@tototoben I'm not sure what you consider 'a good way to have request scoped DataLoaders', but I'm successfully using DataLoader like this with graphql-spring-boot (manually translated from Kotlin to Java, so please forgive any syntax errors):
By the way, I had to manually override the version of java-dataloader to 2.0.2, because performance was pretty bad with 2.0.1, which comes with graphql-java 6.0, which comes with graphql-java-tools 4.3.0 (I believe because of a synchronisation issue in java-dataloader). |
Beta Was this translation helpful? Give feedback.
-
@breun Coming back to this after two months of no GraphQL contact took some time to get in the know with the issue again, but my problem was with caching. The issue boils down to what is talked about in the java dataloader docs as far as I can see: Am I missing something here or is this a valid issue? |
Beta Was this translation helpful? Give feedback.
-
Ah ok, we disable the DataLoader cache, because the default behaviour of the java-dataloader cache is indeed to cache without expiring (until application restart) and that's way too long for us (data can change you know). You can plug in your own cache implementation based on Guava or Kaffeine according to https://github.com/graphql-java/java-dataloader#custom-caches, but indeed it is not clear to me how to have a cache per request. So far I haven't had a need for caching (services called by our GraphQL applications may do their own caching), and since upgrading java-dataloader to 2.0.2 we can serve thousands of requests per second with just a couple of nodes. |
Beta Was this translation helpful? Give feedback.
-
Looking at it now, yeah, just disabling the cache seems like a reasonable solution, thanks! |
Beta Was this translation helpful? Give feedback.
-
@dinhani |
Beta Was this translation helpful? Give feedback.
-
Hey! Does anybody have ideas how to use data loaders in a proper request-scoped way with |
Beta Was this translation helpful? Give feedback.
-
You mean |
Beta Was this translation helpful? Give feedback.
-
since currently it is impossible to use batched DataLoaders to solve N+1 query problem in graphql-java-tools, is there a way to integrate custom DataFetcher objects (which would be batched and use DataLoader) into SchemaParser provided by graphql-java-tools? |
Beta Was this translation helpful? Give feedback.
-
@oliemansm Thanks a lot! That is exactly what I was looking for. |
Beta Was this translation helpful? Give feedback.
-
bad news, it seems - at least for now - DataLoaderDispatcherInstrumentation has no constructor which takes a DataLoaderRegistry instance. thx! |
Beta Was this translation helpful? Give feedback.
-
@bonobonohu graphql-java has had this instrumentation registered by default for quite a while now, no need to add it yourself |
Beta Was this translation helpful? Give feedback.
-
Is there any update on how to add custom |
Beta Was this translation helpful? Give feedback.
-
okay, thanks, it seems i was on a completely bad track then! now i found this solution: |
Beta Was this translation helpful? Give feedback.
-
@bonobonohu request scoped dataloader works for me as well. Just don't understand why you are saying that caching should be disabled? Per request scope eliminates caching problems, right? |
Beta Was this translation helpful? Give feedback.
-
You can pass data loader registry when building Builder executionInput = ExecutionInput.newExecutionInput()
.dataLoaderRegistry(myRegistry)
.query(query)
.context(context); This works as expected in GraphQL Java Tools. I would advise to make sure caching is either disabled or the whole registry is recreated for each request otherwise you might see invalid data being returned from the data loader. Please open a new issue if you have more questions. |
Beta Was this translation helpful? Give feedback.
-
@vojtapol - it's very hard to figure out what you mean with your reference to the |
Beta Was this translation helpful? Give feedback.
-
@Bwvolleyball The |
Beta Was this translation helpful? Give feedback.
-
For what it is worth, I pushed a full working example to my github repo. This is working with plain spring boot 2.2.5 (no graphql kickstart needed): |
Beta Was this translation helpful? Give feedback.
-
Instrumentation bean does not accept dataLoadRegistry..Any Alternatives ? |
Beta Was this translation helpful? Give feedback.
You can pass data loader registry when building
ExecutionInput
:This works as expected in GraphQL Java Tools. I would advise to make sure caching is either disabled or the whole registry is recreated for each request otherwise you might see invalid data being returned from the data loader.
Please open a new issue if you have more questions.