|
| 1 | +--- |
| 2 | +id: data-loader-registry-factory |
| 3 | +title: DataLoaderRegistryFactory |
| 4 | +--- |
| 5 | + |
| 6 | +[Data loaders](https://github.com/graphql/dataloader) are a popular caching pattern from the JavaScript GraphQL implementation. |
| 7 | +`graphql-java` provides [support for this pattern](https://www.graphql-java.com/documentation/v16/batching/) using the `DataLoader` and `DataLoaderRegistry`. |
| 8 | + |
| 9 | +Since `graphql-kotlin` allows you to abstract the schema generation and data fetching code, you may not even need data loaders if instead you have some persistant cache on your server. |
| 10 | + |
| 11 | +```kotlin |
| 12 | +class User(val id: ID) { |
| 13 | + |
| 14 | + // The friendService and userService, which have nothing to do with GraphQL, |
| 15 | + // should be concerned with caching and batch calls instead of your schema classes |
| 16 | + fun getFriends(): List<User> { |
| 17 | + val friends: List<ID> = friendService.getFriends(id) |
| 18 | + return userService.getUsers(friends) |
| 19 | + } |
| 20 | + |
| 21 | +} |
| 22 | +``` |
| 23 | + |
| 24 | +If you still want to use data loaders though, they are supported through the common interfaces. |
| 25 | + |
| 26 | +## `DataLoaderRegistryFactory` |
| 27 | + |
| 28 | +Data loaders should be created per-request as the caching pattern may not work for serving multiple users requesting data simultaneously. |
| 29 | +The [GraphQLRequestHandler](./graphql-request-handler.md) accepts an optional `DataLoaderRegistryFactory` interface that will be called on every request to get a `DataLoaderRegistry`. |
| 30 | + |
| 31 | +```kotlin |
| 32 | +interface DataLoaderRegistryFactory { |
| 33 | + fun generate(): DataLoaderRegistry |
| 34 | +} |
| 35 | +``` |
| 36 | + |
| 37 | +The `DataLoaderRegistry` is a map of a unique keys to a `DataLoader` object that handles the cache for an output type in your graph. |
| 38 | +A `DataLoader` caches the types by some unique value, usually by the type id. |
| 39 | + |
| 40 | +```kotlin |
| 41 | +class MyCustomDataLoaderRegistryFactory : DataLoaderRegistryFactory { |
| 42 | + |
| 43 | + private val userLoader = DataLoader<ID, User> { id -> |
| 44 | + CompletableFuture.supplyAsync { userService.getUser(id) } |
| 45 | + } |
| 46 | + |
| 47 | + override fun generate(): DataLoaderRegistry { |
| 48 | + val registry = DataLoaderRegistry() |
| 49 | + registry.register("userLoader", userLoader) |
| 50 | + return registry |
| 51 | + } |
| 52 | +} |
| 53 | +``` |
| 54 | + |
| 55 | +> NOTE: Because the execution of data loaders is handled by `graphql-java`, which runs using `CompletionStage`, currently we do not support `suspend` functions. |
| 56 | +> See issue [#986](https://github.com/ExpediaGroup/graphql-kotlin/issues/986). |
0 commit comments