-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a helper class for making asynchronous data fetchers (#798)
* Ignore files generated by Eclipse * Add a helper class for making asynchronous data fetchers * Add the ability to set the executor an async data fetcher will run in * Reinstate original documentation and add further section for new method * Make the fields of AsynchronousDataFetcher final
- Loading branch information
1 parent
0255331
commit c59c31a
Showing
4 changed files
with
114 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,69 @@ | |||
package graphql.schema; | |||
|
|||
import static graphql.Assert.assertNotNull; | |||
|
|||
import java.util.concurrent.CompletableFuture; | |||
import java.util.concurrent.Executor; | |||
import java.util.concurrent.ForkJoinPool; | |||
|
|||
import graphql.PublicApi; | |||
|
|||
/** | |||
* A modifier type that indicates the underlying data fetcher is run asynchronously | |||
*/ | |||
@PublicApi | |||
public class AsynchronousDataFetcher<T> implements DataFetcher<CompletableFuture<T>> { | |||
|
|||
/** | |||
* A factory method for creating asynchronous data fetchers so that when used with | |||
* static imports allows more readable code such as: | |||
* <p> | |||
* {@code .dataFetcher(async(fooDataFetcher))} | |||
* <p> | |||
* By default this will run in the {@link ForkJoinPool#commonPool()}. You can set | |||
* your own {@link Executor} with {@link #asyncWithExecutor(DataFetcher, Executor)} | |||
* | |||
* @param wrappedDataFetcher the data fetcher to run asynchronously | |||
* | |||
* @return a {@link DataFetcher} that will run the wrappedDataFetcher asynchronously | |||
*/ | |||
public static <T> AsynchronousDataFetcher<T> async(DataFetcher<T> wrappedDataFetcher) { | |||
return new AsynchronousDataFetcher<>(wrappedDataFetcher); | |||
} | |||
|
|||
/** | |||
* A factory method for creating asynchronous data fetchers and setting the | |||
* {@link Executor} they run in so that when used with static imports allows | |||
* more readable code such as: | |||
* <p> | |||
* {@code .dataFetcher(asyncWithExecutor(fooDataFetcher, fooPool))} | |||
* | |||
* @param wrappedDataFetcher the data fetcher to run asynchronously | |||
* @param executor to run the asynchronous data fetcher in | |||
* | |||
* @return a {@link DataFetcher} that will run the wrappedDataFetcher asynchronously in | |||
* the given {@link Executor} | |||
*/ | |||
public static <T> AsynchronousDataFetcher<T> asyncWithExecutor(DataFetcher<T> wrappedDataFetcher, | |||
Executor executor) { | |||
return new AsynchronousDataFetcher<>(wrappedDataFetcher, executor); | |||
} | |||
|
|||
private final DataFetcher<T> wrappedDataFetcher; | |||
private final Executor executor; | |||
|
|||
public AsynchronousDataFetcher(DataFetcher<T> wrappedDataFetcher) { | |||
this(wrappedDataFetcher, ForkJoinPool.commonPool()); | |||
} | |||
|
|||
public AsynchronousDataFetcher(DataFetcher<T> wrappedDataFetcher, Executor executor) { | |||
this.wrappedDataFetcher = assertNotNull(wrappedDataFetcher, "wrappedDataFetcher can't be null"); | |||
this.executor = assertNotNull(executor, "executor can't be null"); | |||
} | |||
|
|||
@Override | |||
public CompletableFuture<T> get(DataFetchingEnvironment environment) { | |||
return CompletableFuture.supplyAsync(() -> wrappedDataFetcher.get(environment), executor); | |||
} | |||
|
|||
} |
32 changes: 32 additions & 0 deletions
32
src/test/groovy/graphql/schema/AsynchronousDataFetcherTest.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,32 @@ | |||
package graphql.schema | |||
|
|||
import graphql.GraphQL | |||
import graphql.StarWarsData | |||
import graphql.TestUtil | |||
import graphql.execution.FieldCollector | |||
import graphql.language.AstPrinter | |||
import graphql.language.Field | |||
import graphql.schema.idl.MapEnumValuesProvider | |||
import graphql.schema.idl.RuntimeWiring | |||
import spock.lang.Specification | |||
|
|||
import java.util.concurrent.CompletableFuture | |||
import java.util.stream.Collectors | |||
|
|||
import static graphql.schema.idl.TypeRuntimeWiring.newTypeWiring | |||
|
|||
|
|||
class AsynchronousDataFetcherTest extends Specification { | |||
|
|||
def "A data fetcher can be made asynchronous with AsynchronousDataFetcher#async"() { | |||
given: | |||
DataFetchingEnvironment environment = Mock(DataFetchingEnvironment) | |||
|
|||
when: | |||
DataFetcher asyncDataFetcher = AsynchronousDataFetcher.async({ env -> "value" }) | |||
|
|||
then: | |||
asyncDataFetcher.get(environment) instanceof CompletableFuture | |||
asyncDataFetcher.get(environment).get() == "value" | |||
} | |||
} |