Skip to content

Commit 074ed04

Browse files
authoredNov 19, 2020
Merge pull request #247 from donbeave/master
Added ability to cache the whole graphql response
2 parents 88a7614 + 2902ee7 commit 074ed04

13 files changed

+482
-17
lines changed
 

‎.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ target/
1010
.project
1111
.settings
1212
bin
13+
.DS_Store

‎graphql-java-servlet/src/main/java/graphql/kickstart/servlet/AbstractGraphQLHttpServlet.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import graphql.kickstart.execution.GraphQLQueryInvoker;
88
import graphql.kickstart.execution.GraphQLRequest;
99
import graphql.kickstart.execution.input.GraphQLSingleInvocationInput;
10+
import graphql.kickstart.servlet.cache.CachingHttpRequestHandlerImpl;
1011
import graphql.schema.GraphQLFieldDefinition;
1112
import graphql.kickstart.servlet.core.GraphQLMBean;
1213
import graphql.kickstart.servlet.core.GraphQLServletListener;
@@ -83,7 +84,11 @@ protected GraphQLConfiguration getConfiguration() {
8384
public void init() {
8485
if (configuration == null) {
8586
this.configuration = getConfiguration();
86-
this.requestHandler = HttpRequestHandlerFactory.create(configuration);
87+
if (configuration.getResponseCacheManager() != null) {
88+
this.requestHandler = new CachingHttpRequestHandlerImpl(configuration);
89+
} else {
90+
this.requestHandler = HttpRequestHandlerFactory.create(configuration);
91+
}
8792
}
8893
}
8994

‎graphql-java-servlet/src/main/java/graphql/kickstart/servlet/BatchedQueryResponseWriter.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@
22

33
import graphql.ExecutionResult;
44
import graphql.kickstart.execution.GraphQLObjectMapper;
5+
import lombok.RequiredArgsConstructor;
6+
import lombok.extern.slf4j.Slf4j;
7+
8+
import javax.servlet.http.HttpServletRequest;
9+
import javax.servlet.http.HttpServletResponse;
510
import java.io.IOException;
611
import java.nio.charset.StandardCharsets;
712
import java.util.Iterator;
813
import java.util.List;
9-
import javax.servlet.http.HttpServletRequest;
10-
import javax.servlet.http.HttpServletResponse;
11-
import lombok.RequiredArgsConstructor;
1214

15+
@Slf4j
1316
@RequiredArgsConstructor
1417
class BatchedQueryResponseWriter implements QueryResponseWriter {
1518

@@ -34,6 +37,7 @@ public void write(HttpServletRequest request, HttpServletResponse response) thro
3437

3538
String responseContent = responseBuilder.toString();
3639
byte[] contentBytes = responseContent.getBytes(StandardCharsets.UTF_8);
40+
3741
response.setContentLength(contentBytes.length);
3842
response.getOutputStream().write(contentBytes);
3943
}

‎graphql-java-servlet/src/main/java/graphql/kickstart/servlet/GraphQLConfiguration.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import graphql.kickstart.execution.GraphQLObjectMapper;
55
import graphql.kickstart.execution.GraphQLQueryInvoker;
66
import graphql.kickstart.execution.context.ContextSetting;
7+
import graphql.kickstart.servlet.cache.GraphQLResponseCacheManager;
78
import graphql.kickstart.servlet.config.DefaultGraphQLSchemaServletProvider;
89
import graphql.kickstart.servlet.config.GraphQLSchemaServletProvider;
910
import graphql.kickstart.servlet.context.GraphQLServletContextBuilder;
@@ -36,12 +37,13 @@ public class GraphQLConfiguration {
3637
@Getter
3738
private final long asyncTimeout;
3839
private final ContextSetting contextSetting;
40+
private final GraphQLResponseCacheManager responseCacheManager;
3941

4042
private GraphQLConfiguration(GraphQLInvocationInputFactory invocationInputFactory,
4143
GraphQLQueryInvoker queryInvoker,
4244
GraphQLObjectMapper objectMapper, List<GraphQLServletListener> listeners, boolean asyncServletModeEnabled,
4345
Executor asyncExecutor, long subscriptionTimeout, long asyncTimeout, ContextSetting contextSetting,
44-
Supplier<BatchInputPreProcessor> batchInputPreProcessor) {
46+
Supplier<BatchInputPreProcessor> batchInputPreProcessor, GraphQLResponseCacheManager responseCacheManager) {
4547
this.invocationInputFactory = invocationInputFactory;
4648
this.queryInvoker = queryInvoker;
4749
this.graphQLInvoker = queryInvoker.toGraphQLInvoker();
@@ -53,6 +55,7 @@ private GraphQLConfiguration(GraphQLInvocationInputFactory invocationInputFactor
5355
this.asyncTimeout = asyncTimeout;
5456
this.contextSetting = contextSetting;
5557
this.batchInputPreProcessor = batchInputPreProcessor;
58+
this.responseCacheManager = responseCacheManager;
5659
}
5760

5861
public static GraphQLConfiguration.Builder with(GraphQLSchema schema) {
@@ -113,6 +116,10 @@ public BatchInputPreProcessor getBatchInputPreProcessor() {
113116
return batchInputPreProcessor.get();
114117
}
115118

119+
public GraphQLResponseCacheManager getResponseCacheManager() {
120+
return responseCacheManager;
121+
}
122+
116123
public static class Builder {
117124

118125
private GraphQLInvocationInputFactory.Builder invocationInputFactoryBuilder;
@@ -126,6 +133,7 @@ public static class Builder {
126133
private long asyncTimeout = 30;
127134
private ContextSetting contextSetting = ContextSetting.PER_QUERY_WITH_INSTRUMENTATION;
128135
private Supplier<BatchInputPreProcessor> batchInputPreProcessorSupplier = NoOpBatchInputPreProcessor::new;
136+
private GraphQLResponseCacheManager responseCacheManager;
129137

130138
private Builder(GraphQLInvocationInputFactory.Builder invocationInputFactoryBuilder) {
131139
this.invocationInputFactoryBuilder = invocationInputFactoryBuilder;
@@ -209,6 +217,11 @@ public Builder with(Supplier<BatchInputPreProcessor> batchInputPreProcessor) {
209217
return this;
210218
}
211219

220+
public Builder with(GraphQLResponseCacheManager responseCache) {
221+
this.responseCacheManager = responseCache;
222+
return this;
223+
}
224+
212225
public GraphQLConfiguration build() {
213226
return new GraphQLConfiguration(
214227
this.invocationInputFactory != null ? this.invocationInputFactory : invocationInputFactoryBuilder.build(),
@@ -220,7 +233,8 @@ public GraphQLConfiguration build() {
220233
subscriptionTimeout,
221234
asyncTimeout,
222235
contextSetting,
223-
batchInputPreProcessorSupplier
236+
batchInputPreProcessorSupplier,
237+
responseCacheManager
224238
);
225239
}
226240

‎graphql-java-servlet/src/main/java/graphql/kickstart/servlet/HttpRequestHandlerImpl.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@
1414
import lombok.extern.slf4j.Slf4j;
1515

1616
@Slf4j
17-
class HttpRequestHandlerImpl implements HttpRequestHandler {
17+
public class HttpRequestHandlerImpl implements HttpRequestHandler {
1818

1919
private final GraphQLConfiguration configuration;
2020
private final GraphQLInvoker graphQLInvoker;
2121

22-
HttpRequestHandlerImpl(GraphQLConfiguration configuration) {
22+
public HttpRequestHandlerImpl(GraphQLConfiguration configuration) {
2323
this.configuration = configuration;
2424
graphQLInvoker = configuration.getGraphQLInvoker();
2525
}
@@ -46,15 +46,19 @@ public void handle(HttpServletRequest request, HttpServletResponse response) thr
4646
}
4747
}
4848

49-
private void execute(GraphQLInvocationInput invocationInput, HttpServletRequest request,
49+
protected void execute(GraphQLInvocationInput invocationInput, HttpServletRequest request,
5050
HttpServletResponse response) throws IOException {
5151
GraphQLQueryResult queryResult = invoke(invocationInput, request, response);
5252

53-
QueryResponseWriter queryResponseWriter = QueryResponseWriter.createWriter(queryResult, configuration.getObjectMapper(),
54-
configuration.getSubscriptionTimeout());
53+
QueryResponseWriter queryResponseWriter = createWriter(invocationInput, queryResult);
5554
queryResponseWriter.write(request, response);
5655
}
5756

57+
protected QueryResponseWriter createWriter(GraphQLInvocationInput invocationInput, GraphQLQueryResult queryResult) {
58+
return QueryResponseWriter.createWriter(queryResult, configuration.getObjectMapper(),
59+
configuration.getSubscriptionTimeout());
60+
}
61+
5862
private GraphQLQueryResult invoke(GraphQLInvocationInput invocationInput, HttpServletRequest request,
5963
HttpServletResponse response) {
6064
if (invocationInput instanceof GraphQLSingleInvocationInput) {

‎graphql-java-servlet/src/main/java/graphql/kickstart/servlet/QueryResponseWriter.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
package graphql.kickstart.servlet;
22

3-
import graphql.kickstart.execution.GraphQLQueryResult;
43
import graphql.kickstart.execution.GraphQLObjectMapper;
5-
import java.io.IOException;
6-
import java.util.Objects;
4+
import graphql.kickstart.execution.GraphQLQueryResult;
5+
76
import javax.servlet.http.HttpServletRequest;
87
import javax.servlet.http.HttpServletResponse;
8+
import java.io.IOException;
9+
import java.util.Objects;
910

10-
interface QueryResponseWriter {
11+
public interface QueryResponseWriter {
1112

1213
static QueryResponseWriter createWriter(
1314
GraphQLQueryResult result,

‎graphql-java-servlet/src/main/java/graphql/kickstart/servlet/SingleQueryResponseWriter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
import graphql.kickstart.execution.GraphQLObjectMapper;
55
import lombok.RequiredArgsConstructor;
66

7-
import java.io.IOException;
8-
import java.nio.charset.StandardCharsets;
97
import javax.servlet.http.HttpServletRequest;
108
import javax.servlet.http.HttpServletResponse;
9+
import java.io.IOException;
10+
import java.nio.charset.StandardCharsets;
1111

1212
@RequiredArgsConstructor
1313
class SingleQueryResponseWriter implements QueryResponseWriter {
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
package graphql.kickstart.servlet.cache;
2+
3+
import lombok.extern.slf4j.Slf4j;
4+
5+
import javax.servlet.ServletOutputStream;
6+
import javax.servlet.WriteListener;
7+
import javax.servlet.http.HttpServletResponse;
8+
import javax.servlet.http.HttpServletResponseWrapper;
9+
import java.io.ByteArrayOutputStream;
10+
import java.io.IOException;
11+
import java.io.OutputStream;
12+
import java.io.OutputStreamWriter;
13+
import java.io.PrintWriter;
14+
15+
@Slf4j
16+
public class BufferedHttpServletResponse extends HttpServletResponseWrapper {
17+
18+
private static final class BufferedOutputStream extends ServletOutputStream {
19+
20+
private final OutputStream delegate;
21+
private final ByteArrayOutputStream buf = new ByteArrayOutputStream();
22+
23+
public BufferedOutputStream(OutputStream delegate) {
24+
this.delegate = delegate;
25+
}
26+
27+
public void write(int b) throws IOException {
28+
buf.write(b);
29+
delegate.write(b);
30+
}
31+
32+
@Override
33+
public void flush() throws IOException {
34+
buf.flush();
35+
delegate.flush();
36+
}
37+
38+
@Override
39+
public void close() throws IOException {
40+
buf.close();
41+
delegate.close();
42+
}
43+
44+
@Override
45+
public boolean isReady() {
46+
return true;
47+
}
48+
49+
@Override
50+
public void setWriteListener(WriteListener writeListener) {
51+
}
52+
53+
public byte[] toByteArray() {
54+
return buf.toByteArray();
55+
}
56+
57+
}
58+
59+
private BufferedOutputStream copier;
60+
61+
private ServletOutputStream outputStream;
62+
private PrintWriter writer;
63+
private String errorMessage;
64+
65+
public BufferedHttpServletResponse(HttpServletResponse response) {
66+
super(response);
67+
}
68+
69+
@Override
70+
public void sendError(int sc, String msg) throws IOException {
71+
errorMessage = msg;
72+
super.sendError(sc, msg);
73+
}
74+
75+
@Override
76+
public void sendError(int sc) throws IOException {
77+
sendError(sc, null);
78+
}
79+
80+
@Override
81+
public ServletOutputStream getOutputStream() throws IOException {
82+
if (writer != null) {
83+
throw new IllegalStateException("getWriter() has already been called on this response.");
84+
}
85+
86+
if (outputStream == null) {
87+
outputStream = getResponse().getOutputStream();
88+
copier = new BufferedOutputStream(outputStream);
89+
}
90+
91+
return copier;
92+
}
93+
94+
@Override
95+
public PrintWriter getWriter() throws IOException {
96+
if (outputStream != null) {
97+
throw new IllegalStateException("getOutputStream() has already been called on this response.");
98+
}
99+
100+
if (writer == null) {
101+
copier = new BufferedOutputStream(getResponse().getOutputStream());
102+
writer = new PrintWriter(new OutputStreamWriter(copier, getResponse().getCharacterEncoding()), true);
103+
}
104+
105+
return writer;
106+
}
107+
108+
@Override
109+
public void flushBuffer() throws IOException {
110+
if (writer != null) {
111+
writer.flush();
112+
} else if (copier != null) {
113+
copier.flush();
114+
}
115+
}
116+
117+
@Override
118+
public boolean isCommitted() {
119+
return false;
120+
}
121+
122+
public void close() throws IOException {
123+
if (writer != null) {
124+
writer.close();
125+
} else if (copier != null) {
126+
copier.close();
127+
}
128+
}
129+
130+
public String getErrorMessage() {
131+
return errorMessage;
132+
}
133+
134+
public byte[] getContentAsByteArray() {
135+
if (copier != null) {
136+
return copier.toByteArray();
137+
} else {
138+
return new byte[0];
139+
}
140+
}
141+
142+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package graphql.kickstart.servlet.cache;
2+
3+
import graphql.kickstart.execution.input.GraphQLInvocationInput;
4+
import graphql.kickstart.servlet.HttpRequestHandler;
5+
import lombok.extern.slf4j.Slf4j;
6+
7+
import javax.servlet.http.HttpServletRequest;
8+
import javax.servlet.http.HttpServletResponse;
9+
import java.io.IOException;
10+
import java.nio.charset.StandardCharsets;
11+
12+
@Slf4j
13+
public final class CacheReader {
14+
15+
private CacheReader() {
16+
}
17+
18+
/**
19+
* Response from cache if possible, if nothing in cache will not produce any response
20+
*
21+
* @return {@literal true} if response was fulfilled from cache, {@literal false} is cache not found or an error
22+
* occurred while reading value from cache
23+
* @throws IOException if can not read value from the cache
24+
*/
25+
public static boolean responseFromCache(GraphQLInvocationInput invocationInput,
26+
HttpServletRequest request,
27+
HttpServletResponse response,
28+
GraphQLResponseCacheManager cacheManager) throws IOException {
29+
CachedResponse cachedResponse = null;
30+
try {
31+
cachedResponse = cacheManager.get(request, invocationInput);
32+
} catch (Throwable t) {
33+
log.warn("Ignore read from cache, unexpected error happened", t);
34+
}
35+
36+
if (cachedResponse != null) {
37+
write(response, cachedResponse);
38+
return true;
39+
}
40+
41+
return false;
42+
}
43+
44+
private static void write(HttpServletResponse response, CachedResponse cachedResponse)
45+
throws IOException {
46+
if (cachedResponse.isError()) {
47+
response.sendError(cachedResponse.getErrorStatusCode(), cachedResponse.getErrorMessage());
48+
} else {
49+
response.setContentType(HttpRequestHandler.APPLICATION_JSON_UTF8);
50+
response.setStatus(HttpRequestHandler.STATUS_OK);
51+
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
52+
response.setContentLength(cachedResponse.getContentBytes().length);
53+
response.getOutputStream().write(cachedResponse.getContentBytes());
54+
}
55+
}
56+
57+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package graphql.kickstart.servlet.cache;
2+
3+
import java.io.Serializable;
4+
import java.util.Objects;
5+
6+
public class CachedResponse implements Serializable {
7+
8+
private static final long serialVersionUID = 5894555791705575139L;
9+
10+
private final byte[] contentBytes;
11+
12+
private final boolean error;
13+
private final Integer errorStatusCode;
14+
private final String errorMessage;
15+
16+
private CachedResponse(byte[] contentBytes, boolean error, Integer errorStatusCode, String errorMessage) {
17+
this.contentBytes = contentBytes;
18+
this.error = error;
19+
this.errorStatusCode = errorStatusCode;
20+
this.errorMessage = errorMessage;
21+
}
22+
23+
/**
24+
* Constructor for success response
25+
*
26+
* @param contentBytes bytes array of graphql json response
27+
*/
28+
public static CachedResponse ofContent(byte[] contentBytes) {
29+
Objects.requireNonNull(contentBytes, "contentBytes can not be null");
30+
31+
return new CachedResponse(contentBytes, false, null, null);
32+
}
33+
34+
/**
35+
* Constructor for error response
36+
*
37+
* @param errorStatusCode the status code for the error response
38+
* @param errorMessage the error message for the error response
39+
*/
40+
public static CachedResponse ofError(int errorStatusCode, String errorMessage) {
41+
return new CachedResponse(null, true, errorStatusCode, errorMessage);
42+
}
43+
44+
/**
45+
* @return {@literal true} when this request was failed
46+
*/
47+
public boolean isError() {
48+
return error;
49+
}
50+
51+
/**
52+
* @return the response body for success requests, {@literal null} when {@link #isError()} is {@literal true}
53+
*/
54+
public byte[] getContentBytes() {
55+
return contentBytes;
56+
}
57+
58+
/**
59+
* @return the response error code
60+
*/
61+
public Integer getErrorStatusCode() {
62+
return errorStatusCode;
63+
}
64+
65+
/**
66+
* @return the response error message
67+
*/
68+
public String getErrorMessage() {
69+
return errorMessage;
70+
}
71+
72+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package graphql.kickstart.servlet.cache;
2+
3+
import graphql.kickstart.execution.GraphQLQueryResult;
4+
import graphql.kickstart.execution.input.GraphQLInvocationInput;
5+
import graphql.kickstart.servlet.GraphQLConfiguration;
6+
import graphql.kickstart.servlet.HttpRequestHandlerImpl;
7+
import graphql.kickstart.servlet.QueryResponseWriter;
8+
import lombok.extern.slf4j.Slf4j;
9+
10+
import javax.servlet.http.HttpServletRequest;
11+
import javax.servlet.http.HttpServletResponse;
12+
import java.io.IOException;
13+
import java.util.Objects;
14+
15+
@Slf4j
16+
public class CachingHttpRequestHandlerImpl extends HttpRequestHandlerImpl {
17+
18+
private final GraphQLConfiguration configuration;
19+
20+
public CachingHttpRequestHandlerImpl(GraphQLConfiguration configuration) {
21+
super(configuration);
22+
Objects.requireNonNull(configuration.getResponseCacheManager(), "Response Cache Manager cannot be null");
23+
this.configuration = configuration;
24+
}
25+
26+
@Override
27+
protected void execute(GraphQLInvocationInput invocationInput, HttpServletRequest request,
28+
HttpServletResponse response) throws IOException {
29+
// try to return value from cache if cache exists, otherwise processed the query
30+
boolean returnedFromCache;
31+
32+
try {
33+
returnedFromCache = !CacheReader.responseFromCache(
34+
invocationInput, request, response, configuration.getResponseCacheManager()
35+
);
36+
} catch (IOException e) {
37+
response.setStatus(STATUS_BAD_REQUEST);
38+
log.warn("unexpected error happened during response from cache", e);
39+
return;
40+
}
41+
42+
if (!returnedFromCache) {
43+
super.execute(invocationInput, request, response);
44+
}
45+
}
46+
47+
protected QueryResponseWriter createWriter(GraphQLInvocationInput invocationInput, GraphQLQueryResult queryResult) {
48+
return CachingQueryResponseWriter.createCacheWriter(
49+
queryResult,
50+
configuration.getObjectMapper(),
51+
configuration.getSubscriptionTimeout(),
52+
invocationInput,
53+
configuration.getResponseCacheManager()
54+
);
55+
}
56+
57+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package graphql.kickstart.servlet.cache;
2+
3+
import graphql.kickstart.execution.GraphQLObjectMapper;
4+
import graphql.kickstart.execution.GraphQLQueryResult;
5+
import graphql.kickstart.execution.input.GraphQLInvocationInput;
6+
import graphql.kickstart.servlet.QueryResponseWriter;
7+
import lombok.extern.slf4j.Slf4j;
8+
9+
import javax.servlet.http.HttpServletRequest;
10+
import javax.servlet.http.HttpServletResponse;
11+
import java.io.IOException;
12+
13+
@Slf4j
14+
public class CachingQueryResponseWriter implements QueryResponseWriter {
15+
16+
static QueryResponseWriter createCacheWriter(
17+
GraphQLQueryResult result,
18+
GraphQLObjectMapper graphQLObjectMapper,
19+
long subscriptionTimeout,
20+
GraphQLInvocationInput invocationInput,
21+
GraphQLResponseCacheManager responseCache
22+
) {
23+
QueryResponseWriter writer = QueryResponseWriter.createWriter(result, graphQLObjectMapper, subscriptionTimeout);
24+
if (responseCache != null) {
25+
return new CachingQueryResponseWriter(writer, responseCache, invocationInput, result.isError());
26+
}
27+
return writer;
28+
}
29+
30+
private final QueryResponseWriter delegate;
31+
private final GraphQLResponseCacheManager responseCache;
32+
private final GraphQLInvocationInput invocationInput;
33+
private final boolean error;
34+
35+
public CachingQueryResponseWriter(QueryResponseWriter delegate, GraphQLResponseCacheManager responseCache,
36+
GraphQLInvocationInput invocationInput, boolean error) {
37+
this.delegate = delegate;
38+
this.responseCache = responseCache;
39+
this.invocationInput = invocationInput;
40+
this.error = error;
41+
}
42+
43+
@Override
44+
public void write(HttpServletRequest request, HttpServletResponse response) throws IOException {
45+
if (responseCache.isCacheable(request, invocationInput)) {
46+
BufferedHttpServletResponse cachingResponseWrapper = new BufferedHttpServletResponse(response);
47+
48+
delegate.write(request, cachingResponseWrapper);
49+
50+
try {
51+
if (error) {
52+
int errorStatusCode = cachingResponseWrapper.getStatus();
53+
String errorMessage = cachingResponseWrapper.getErrorMessage();
54+
55+
responseCache.put(request, invocationInput, CachedResponse.ofError(errorStatusCode, errorMessage));
56+
} else {
57+
byte[] contentBytes = cachingResponseWrapper.getContentAsByteArray();
58+
59+
responseCache.put(request, invocationInput, CachedResponse.ofContent(contentBytes));
60+
}
61+
} catch (Throwable t) {
62+
log.warn("Ignore read from cache, unexpected error happened", t);
63+
}
64+
65+
cachingResponseWrapper.flushBuffer();
66+
cachingResponseWrapper.close();
67+
} else {
68+
delegate.write(request, response);
69+
}
70+
}
71+
72+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package graphql.kickstart.servlet.cache;
2+
3+
import graphql.kickstart.execution.input.GraphQLInvocationInput;
4+
5+
import javax.servlet.http.HttpServletRequest;
6+
import java.util.Optional;
7+
8+
public interface GraphQLResponseCacheManager {
9+
10+
/**
11+
* Retrieve the cache by input data. If this query was not cached before, will return empty {@link Optional}.
12+
*
13+
* @param request the http request
14+
* @param invocationInput input data
15+
* @return cached response if something available in cache or {@literal null} if nothing cached
16+
*/
17+
CachedResponse get(HttpServletRequest request, GraphQLInvocationInput invocationInput);
18+
19+
/**
20+
* Decide to cache or not this response. It depends on the implementation.
21+
*
22+
* @param request the http request
23+
* @param invocationInput input data
24+
*/
25+
boolean isCacheable(HttpServletRequest request, GraphQLInvocationInput invocationInput);
26+
27+
/**
28+
* Cache this response. It depends on the implementation.
29+
*
30+
* @param request the http request
31+
* @param invocationInput input data
32+
* @param cachedResponse response to cache
33+
*/
34+
void put(HttpServletRequest request, GraphQLInvocationInput invocationInput, CachedResponse cachedResponse);
35+
36+
}

0 commit comments

Comments
 (0)
Please sign in to comment.