Skip to content

Commit 6c3388d

Browse files
committed
A registry and a dispatcher for graphql
1 parent ae5d3dc commit 6c3388d

File tree

5 files changed

+180
-0
lines changed

5 files changed

+180
-0
lines changed

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ compileJava {
4949
}
5050

5151
dependencies {
52+
compile "com.graphql-java:graphql-java:4.0"
5253
testCompile "junit:junit:$junitVersion"
5354
testCompile 'org.awaitility:awaitility:2.0.0'
5455
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package org.dataloader;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
import java.util.concurrent.CopyOnWriteArrayList;
6+
7+
/**
8+
* This allows data loaders to be registered together into a single place so
9+
* they can be dispatched as one.
10+
*/
11+
public class DataLoaderRegistry {
12+
private final List<DataLoader<?, ?>> dataLoaders = new CopyOnWriteArrayList<>();
13+
14+
/**
15+
* @return the currently registered data loaders
16+
*/
17+
public List<DataLoader<?, ?>> getDataLoaders() {
18+
return new ArrayList<>(dataLoaders);
19+
}
20+
21+
/**
22+
* This will register a new dataloader
23+
*
24+
* @param dataLoader the data loader to register
25+
*
26+
* @return this registry
27+
*/
28+
public DataLoaderRegistry register(DataLoader<?, ?> dataLoader) {
29+
if (!dataLoaders.contains(dataLoader)) {
30+
dataLoaders.add(dataLoader);
31+
}
32+
return this;
33+
}
34+
35+
/**
36+
* This will unregister a new dataloader
37+
*
38+
* @param dataLoader the data loader to unregister
39+
*
40+
* @return this registry
41+
*/
42+
public DataLoaderRegistry unregister(DataLoader<?, ?> dataLoader) {
43+
dataLoaders.remove(dataLoader);
44+
return this;
45+
}
46+
47+
/**
48+
* This will called {@link org.dataloader.DataLoader#dispatch()} on each of the registered
49+
* {@link org.dataloader.DataLoader}s
50+
*/
51+
public void dispatchAll() {
52+
dataLoaders.forEach(DataLoader::dispatch);
53+
}
54+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package org.dataloader.graphql;
2+
3+
import graphql.ExecutionResult;
4+
import graphql.execution.instrumentation.InstrumentationContext;
5+
import graphql.execution.instrumentation.NoOpInstrumentation;
6+
import graphql.execution.instrumentation.parameters.InstrumentationExecutionStrategyParameters;
7+
import org.dataloader.DataLoaderRegistry;
8+
9+
import java.util.concurrent.CompletableFuture;
10+
11+
/**
12+
* This graphql {@link graphql.execution.instrumentation.Instrumentation} will dispatch
13+
* all the contained {@link org.dataloader.DataLoader}s when each level of the graphql
14+
* query is executed.
15+
*/
16+
public class DataLoaderDispatcherInstrumentation extends NoOpInstrumentation {
17+
18+
private final DataLoaderRegistry dataLoaderRegistry;
19+
20+
public DataLoaderDispatcherInstrumentation(DataLoaderRegistry dataLoaderRegistry) {
21+
this.dataLoaderRegistry = dataLoaderRegistry;
22+
}
23+
24+
@Override
25+
public InstrumentationContext<CompletableFuture<ExecutionResult>> beginExecutionStrategy(InstrumentationExecutionStrategyParameters parameters) {
26+
return (result, t) -> dataLoaderRegistry.dispatchAll();
27+
}
28+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package org.dataloader;
2+
3+
import org.hamcrest.Matchers;
4+
import org.junit.Test;
5+
6+
import java.util.concurrent.CompletableFuture;
7+
8+
import static java.util.Arrays.asList;
9+
import static org.junit.Assert.assertThat;
10+
11+
public class DataLoaderRegistryTest {
12+
final BatchLoader<Object, Object> identityBatchLoader = CompletableFuture::completedFuture;
13+
14+
@Test
15+
public void registration_works() throws Exception {
16+
DataLoader<Object, Object> dlA = new DataLoader<>(identityBatchLoader);
17+
DataLoader<Object, Object> dlB = new DataLoader<>(identityBatchLoader);
18+
DataLoader<Object, Object> dlC = new DataLoader<>(identityBatchLoader);
19+
20+
DataLoaderRegistry registry = new DataLoaderRegistry();
21+
22+
registry.register(dlA).register(dlB).register(dlC);
23+
24+
assertThat(registry.getDataLoaders(), Matchers.equalTo(asList(dlA, dlB, dlC)));
25+
26+
// the same dl twice is one add
27+
28+
29+
registry = new DataLoaderRegistry();
30+
31+
registry.register(dlA).register(dlB).register(dlC).register(dlA).register(dlB);
32+
33+
assertThat(registry.getDataLoaders(), Matchers.equalTo(asList(dlA, dlB, dlC)));
34+
35+
36+
// and unregister
37+
registry.unregister(dlC);
38+
39+
assertThat(registry.getDataLoaders(), Matchers.equalTo(asList(dlA, dlB)));
40+
}
41+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package org.dataloader.graphql;
2+
3+
import graphql.ExecutionResult;
4+
import graphql.execution.instrumentation.InstrumentationContext;
5+
import org.dataloader.BatchLoader;
6+
import org.dataloader.DataLoader;
7+
import org.dataloader.DataLoaderRegistry;
8+
import org.junit.Test;
9+
10+
import java.util.ArrayList;
11+
import java.util.List;
12+
import java.util.concurrent.CompletableFuture;
13+
import java.util.concurrent.atomic.AtomicInteger;
14+
15+
import static java.util.Arrays.asList;
16+
import static java.util.Collections.singletonList;
17+
import static org.hamcrest.Matchers.equalTo;
18+
import static org.junit.Assert.assertThat;
19+
20+
public class DataLoaderDispatcherInstrumentationTest {
21+
22+
@Test
23+
public void basic_invocation() throws Exception {
24+
25+
AtomicInteger invocationCount = new AtomicInteger();
26+
final List<Object> loadedKeys = new ArrayList<>();
27+
final BatchLoader<Object, Object> identityBatchLoader = keys -> {
28+
invocationCount.incrementAndGet();
29+
loadedKeys.add(keys);
30+
return CompletableFuture.completedFuture(keys);
31+
};
32+
33+
DataLoader<Object, Object> dlA = new DataLoader<>(identityBatchLoader);
34+
DataLoader<Object, Object> dlB = new DataLoader<>(identityBatchLoader);
35+
DataLoader<Object, Object> dlC = new DataLoader<>(identityBatchLoader);
36+
DataLoaderRegistry registry = new DataLoaderRegistry()
37+
.register(dlA)
38+
.register(dlB)
39+
.register(dlC);
40+
41+
DataLoaderDispatcherInstrumentation dispatcher = new DataLoaderDispatcherInstrumentation(registry);
42+
InstrumentationContext<CompletableFuture<ExecutionResult>> context = dispatcher.beginExecutionStrategy(null);
43+
44+
// cause some activity
45+
dlA.load("A");
46+
dlB.load("B");
47+
dlC.load("C");
48+
49+
context.onEnd(null, null);
50+
51+
assertThat(invocationCount.get(), equalTo(3));
52+
53+
// will be [[A],[B],[C]]
54+
assertThat(loadedKeys, equalTo(asList(singletonList("A"), singletonList("B"), singletonList("C"))));
55+
}
56+
}

0 commit comments

Comments
 (0)