Skip to content

Commit 2dd53b4

Browse files
committed
Priming the cache
1 parent 2c05025 commit 2dd53b4

7 files changed

Lines changed: 76 additions & 45 deletions

File tree

src/main/java/com/graphql/example/proxy/ForwardOnlyFixedPagedDataSet.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ public boolean hasNextPage() {
122122
*
123123
* @return a connection according to the 'after' and 'first' arguments
124124
*/
125-
public static Connection<Object> getConnection(DataFetchingEnvironment env, int defaultFirstN, Function<Integer, PagedResult> pageOfDataRetriever) {
125+
public static <T> Connection<T> getConnection(DataFetchingEnvironment env, int defaultFirstN, Function<Integer, PagedResult<T>> pageOfDataRetriever) {
126126

127127
int firstN = getArg(env, "first", defaultFirstN);
128128
if (firstN < 0) {
@@ -135,15 +135,15 @@ public static Connection<Object> getConnection(DataFetchingEnvironment env, int
135135
PageAndOffset desiredPageAndOffset = PageAndOffset.fromCursor(afterCursor);
136136
int startPage = desiredPageAndOffset.getPage();
137137

138-
List<Edge<Object>> edges = new ArrayList<>();
138+
List<Edge<T>> edges = new ArrayList<>();
139139
boolean addToEdges = false;
140140
boolean hasNextPage = true;
141141
int fullOffset = 0;
142142
int howManyNeeded = firstN + (afterPresent ? 1 : 0); // if after is present we slice it away later
143143
while (edges.size() < howManyNeeded) {
144144

145-
PagedResult pagedResult = pageOfDataRetriever.apply(startPage);
146-
for (Object obj : pagedResult.getResults()) {
145+
PagedResult<T> pagedResult = pageOfDataRetriever.apply(startPage);
146+
for (T obj : pagedResult.getResults()) {
147147
ConnectionCursor edgeCursor = new PageAndOffset(startPage, fullOffset).toConnectionCursor();
148148
if (fullOffset == desiredPageAndOffset.getOffset()) {
149149
addToEdges = true;
@@ -169,7 +169,7 @@ public static Connection<Object> getConnection(DataFetchingEnvironment env, int
169169
if (afterPresent) {
170170
sliceIndex = 1;
171171
}
172-
List<Edge<Object>> slicedEdges = edges.subList(sliceIndex, Math.min(edges.size(), sliceIndex + firstN));
172+
List<Edge<T>> slicedEdges = edges.subList(sliceIndex, Math.min(edges.size(), sliceIndex + firstN));
173173
if (slicedEdges.isEmpty()) {
174174
return emptyConnection();
175175
}

src/main/java/com/graphql/example/proxy/IceAndFireApiProxy.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ private GraphQLSchema buildSchema(IceAndFireDataFetchers iceAndFireDataFetchers)
146146
.type(newTypeWiring("Query")
147147
.dataFetcher("books", iceAndFireDataFetchers.books())
148148
.dataFetcher("characters", iceAndFireDataFetchers.characters())
149+
.dataFetcher("houses", iceAndFireDataFetchers.houses())
149150
)
150151
.type(newTypeWiring("Book")
151152
.dataFetcher("characters", iceAndFireDataFetchers.urlConnection())

src/main/java/com/graphql/example/proxy/IceAndFireDataFetchers.java

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import org.dataloader.BatchLoader;
1010
import org.dataloader.DataLoader;
1111
import org.dataloader.impl.PromisedValues;
12+
import org.slf4j.Logger;
13+
import org.slf4j.LoggerFactory;
1214

1315
import java.util.ArrayList;
1416
import java.util.Collections;
@@ -17,11 +19,13 @@
1719
import java.util.concurrent.CompletableFuture;
1820
import java.util.concurrent.CompletionStage;
1921

20-
import static com.graphql.example.util.QueryParameters.QueryParameter.qp;
22+
import static com.graphql.example.util.HttpQueryParameter.qp;
2123
import static java.util.stream.Collectors.toList;
2224

2325
class IceAndFireDataFetchers {
2426

27+
private static final Logger log = LoggerFactory.getLogger(IceAndFireDataFetchers.class);
28+
2529
public static final int PAGE_SIZE = 50; // this is what they allow
2630

2731
private BatchLoader<String, Object> urlBatchLoader = urls -> {
@@ -128,16 +132,41 @@ DataFetcher urlObject() {
128132
DataFetcher books() {
129133
return env ->
130134
CompletableFuture.supplyAsync(() ->
131-
ForwardOnlyFixedPagedDataSet.getConnection(env, PAGE_SIZE, pageNumber -> HttpClient.readResource("books",
132-
qp("page", pageNumber), qp("pageSize", PAGE_SIZE))));
135+
ForwardOnlyFixedPagedDataSet.getConnection(env, PAGE_SIZE,
136+
pageNumber -> readPagedObjects("books", pageNumber)));
137+
}
138+
139+
DataFetcher houses() {
140+
return env ->
141+
CompletableFuture.supplyAsync(() ->
142+
ForwardOnlyFixedPagedDataSet.getConnection(env, PAGE_SIZE,
143+
pageNumber -> readPagedObjects("houses", pageNumber)));
133144
}
134145

135146
DataFetcher characters() {
136147
return env ->
137148
CompletableFuture.supplyAsync(() ->
138-
ForwardOnlyFixedPagedDataSet.getConnection(env, PAGE_SIZE, pageNumber ->
139-
HttpClient.readResource("characters", qp("pageNumber", pageNumber),
140-
qp("pageSize", PAGE_SIZE))));
149+
ForwardOnlyFixedPagedDataSet.getConnection(env, PAGE_SIZE,
150+
pageNumber -> readPagedObjects("characters", pageNumber)));
151+
}
152+
153+
private ForwardOnlyFixedPagedDataSet.PagedResult<Map<String, Object>> readPagedObjects(String resource, int pageNumber) {
154+
log.info("Fetching {} page: {}", resource, pageNumber);
155+
ForwardOnlyFixedPagedDataSet.PagedResult<Map<String, Object>> pagedResult =
156+
HttpClient.readResource(resource, qp("pageNumber", pageNumber), qp("pageSize", PAGE_SIZE));
157+
158+
log.info("\tread {} {}", pagedResult.getResults().size(), resource);
159+
160+
pagedResult.getResults().forEach(resourceObj -> {
161+
//
162+
// this is mutative since relay requires ids yet the REST API does not have them
163+
addGlobalIds(resourceObj);
164+
String url = (String) resourceObj.get("url");
165+
//
166+
// prime the dataloader with each entry so caching should work when we ask for it again
167+
resourceDataLoader.prime(url, resourceObj);
168+
});
169+
return pagedResult;
141170
}
142171

143172
private static <T> T mapGet(Map<String, Object> source, String fieldName) {

src/main/java/com/graphql/example/util/HttpClient.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@ public Object getData() {
3838
}
3939
}
4040

41-
public static <T> ForwardOnlyFixedPagedDataSet.PagedResult<T> readResource(String resource, QueryParameters.QueryParameter... params) {
41+
public static <T> ForwardOnlyFixedPagedDataSet.PagedResult<T> readResource(String resource, HttpQueryParameter... params) {
4242
HttpUrl.Builder urlBuilder = new HttpUrl.Builder();
4343
urlBuilder.scheme("https").host("www.anapioficeandfire.com").addPathSegment("api").addPathSegment(resource);
4444
if (params != null) {
45-
for (QueryParameters.QueryParameter param : params) {
45+
for (HttpQueryParameter param : params) {
4646
urlBuilder.addQueryParameter(param.getName(), param.getValue());
4747
}
4848
}
@@ -90,7 +90,6 @@ private static DataAndResponse read(Request request) throws IOException {
9090
Response response = httpClient.newCall(request).execute();
9191
ResponseBody body = response.body();
9292
long ms = response.receivedResponseAtMillis() - response.sentRequestAtMillis();
93-
log.info("Reading {}...", request.url());
9493

9594
String jsonString = "";
9695
Object obj = null;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.graphql.example.util;
2+
3+
public class HttpQueryParameter {
4+
final String name;
5+
final String value;
6+
7+
public HttpQueryParameter(String name, String value) {
8+
this.name = name;
9+
this.value = value;
10+
}
11+
12+
public static HttpQueryParameter qp(String name, Object value) {
13+
return new HttpQueryParameter(name, value.toString());
14+
}
15+
16+
public String getName() {
17+
return name;
18+
}
19+
20+
public String getValue() {
21+
return value;
22+
}
23+
}

src/main/java/com/graphql/example/util/QueryParameters.java

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -22,28 +22,6 @@
2222
*/
2323
public class QueryParameters {
2424

25-
public static class QueryParameter {
26-
final String name;
27-
final String value;
28-
29-
public QueryParameter(String name, String value) {
30-
this.name = name;
31-
this.value = value;
32-
}
33-
34-
public static QueryParameter qp(String name, Object value) {
35-
return new QueryParameter(name, value.toString());
36-
}
37-
38-
public String getName() {
39-
return name;
40-
}
41-
42-
public String getValue() {
43-
return value;
44-
}
45-
}
46-
4725
String query;
4826
String operationName;
4927
Map<String, Object> variables = Collections.emptyMap();

src/main/resources/gameOfThrones.graphqls

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ type House {
1818
founder: Character # The Character resource URL that founded this house.
1919
diedOut: String # The year that this house died out.
2020
ancestralWeapons: [String] # An array of names of the noteworthy weapons that this house owns.
21-
cadetBranches(first : Int = 10, after : String, last : Int, before : String): HouseConnection # An array of House resource URLs that was founded from this house.
22-
swornMembers(first : Int = 10, after : String, last : Int, before : String): CharacterConnection # An array of Character resource URLs that are sworn to this house.
21+
cadetBranches(first : Int = 10, after : String): HouseConnection # An array of House resource URLs that was founded from this house.
22+
swornMembers(first : Int = 10, after : String): CharacterConnection # An array of Character resource URLs that are sworn to this house.
2323
}
2424

2525

@@ -50,9 +50,9 @@ type Character {
5050
tvSeries : [String] # An array of names of the seasons of Game of Thrones that this character has been in.
5151
playedBy : [String] # An array of actor names that has played this character in the TV show Game Of Thrones.
5252

53-
allegiances(first : Int = 10, after : String, last : Int, before : String): HouseConnection # An array of House resource URLs that this character is loyal to.
54-
books(first : Int = 10, after : String, last : Int, before : String): BookConnection # An array of Book resource URLs that this character has been in.
55-
povBooks(first : Int = 10, after : String, last : Int, before : String): BookConnection # An array of Book resource URLs that this character has had a POV-chapter in.
53+
allegiances(first : Int = 10, after : String): HouseConnection # An array of House resource URLs that this character is loyal to.
54+
books(first : Int = 10, after : String): BookConnection # An array of Book resource URLs that this character has been in.
55+
povBooks(first : Int = 10, after : String): BookConnection # An array of Book resource URLs that this character has had a POV-chapter in.
5656
}
5757

5858
type CharacterConnection {
@@ -77,8 +77,8 @@ type Book {
7777
country: String # The country that this book was published in
7878
mediaType: String # The type of media this book was released in.
7979
released: String # The date (ISO 8601) when this book was released.
80-
characters(first : Int = 10, after : String, last : Int, before : String): CharacterConnection # An array of Character resource URLs that has been in this book.
81-
povCharacters(first : Int = 10, after : String, last : Int, before : String): CharacterConnection # An array of Character resource URLs that has had a POV-chapter in this book.
80+
characters(first : Int = 10, after : String): CharacterConnection # An array of Character resource URLs that has been in this book.
81+
povCharacters(first : Int = 10, after : String): CharacterConnection # An array of Character resource URLs that has had a POV-chapter in this book.
8282
}
8383

8484
type BookConnection {
@@ -114,6 +114,7 @@ type PageInfo {
114114
# top level types last
115115
#
116116
type Query {
117-
books(first : Int = 10, after : String, last : Int, before : String) : BookConnection
118-
characters(first : Int = 10, after : String, last : Int, before : String) : CharacterConnection
117+
books(first : Int = 10, after : String) : BookConnection
118+
characters(first : Int = 10, after : String) : CharacterConnection
119+
houses(first : Int = 10, after : String) : HouseConnection
119120
}

0 commit comments

Comments
 (0)