This is an automated email from the ASF dual-hosted git repository.
radu pushed a commit to branch feature/SLING-9655
in repository
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-graphql-core.git
The following commit(s) were added to refs/heads/feature/SLING-9655 by this
push:
new 1e4eaf9 SLING-9655 - Caching support for the GraphQL core
1e4eaf9 is described below
commit 1e4eaf9e2ad66225ca051976ba03ce40b1111719
Author: Radu Cotescu <[email protected]>
AuthorDate: Thu Aug 20 19:10:44 2020 +0200
SLING-9655 - Caching support for the GraphQL core
* exposed GraphQLCacheProvider as a very thin API for supporting
persisted queries
* implemented the HTTP API for persisted queries (needs some IT)
---
.../graphql/api/cache/GraphQLCacheProvider.java | 54 ++++++++++++++++++++++
.../sling/graphql/api/cache/package-info.java} | 16 ++-----
...Provider.java => GraphQLCacheProviderImpl.java} | 40 ++++++++++------
.../sling/graphql/core/servlet/GraphQLServlet.java | 24 +++++++---
...Test.java => GraphQLCacheProviderImplTest.java} | 6 +--
5 files changed, 104 insertions(+), 36 deletions(-)
diff --git
a/src/main/java/org/apache/sling/graphql/api/cache/GraphQLCacheProvider.java
b/src/main/java/org/apache/sling/graphql/api/cache/GraphQLCacheProvider.java
new file mode 100644
index 0000000..bab13e0
--- /dev/null
+++ b/src/main/java/org/apache/sling/graphql/api/cache/GraphQLCacheProvider.java
@@ -0,0 +1,54 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+package org.apache.sling.graphql.api.cache;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * A {@code GraphQLCacheProvider} is responsible for caching GraphQL queries,
in order to provide support for persisted queries for the
+ * {@link org.apache.sling.graphql.core.servlet.GraphQLServlet}.
+ */
+@ProviderType
+public interface GraphQLCacheProvider {
+
+ /**
+ * Attempts to retrieve a previously persisted query from the cache.
+ *
+ * @param hash the query's SHA-256 hash
+ * @param resourceType the resource type of the {@link
org.apache.sling.graphql.core.servlet.GraphQLServlet} which will execute the
+ * query, since multiple servlets can be registered
+ * @param selectorString the selector string with which the {@link
org.apache.sling.graphql.core.servlet.GraphQLServlet} is registered
+ * @return the query, if found, {@code null} otherwise
+ * @see #cacheQuery(String, String, String)
+ */
+ @Nullable String getQuery(@NotNull String hash, @NotNull String
resourceType, @Nullable String selectorString);
+
+ /**
+ * Stores the {@code query} into the cache, potentially overriding a
previous value.
+ *
+ * @param query the GraphQL query
+ * @param resourceType the resource type of the {@link
org.apache.sling.graphql.core.servlet.GraphQLServlet} which will execute the
+ * query, since multiple servlets can be registered
+ * @param selectorString the selector string with which the {@link
org.apache.sling.graphql.core.servlet.GraphQLServlet} is registered
+ * @return the query's SHA-256 hash, which will be passed to the GraphQL
client for query retrieval
+ */
+ @NotNull String cacheQuery(@NotNull String query, @NotNull String
resourceType, @Nullable String selectorString);
+}
diff --git
a/src/test/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderTest.java
b/src/main/java/org/apache/sling/graphql/api/cache/package-info.java
similarity index 70%
copy from
src/test/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderTest.java
copy to src/main/java/org/apache/sling/graphql/api/cache/package-info.java
index 66184b6..25816db 100644
---
a/src/test/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderTest.java
+++ b/src/main/java/org/apache/sling/graphql/api/cache/package-info.java
@@ -16,17 +16,7 @@
~ specific language governing permissions and limitations
~ under the License.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-package org.apache.sling.graphql.core.cache;
+@Version("0.0.1")
+package org.apache.sling.graphql.api.cache;
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-public class GraphQLCacheProviderTest {
-
- @Test
- public void getHash() throws Exception {
- GraphQLCacheProvider provider = new GraphQLCacheProvider();
-
assertEquals("b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9",
provider.getHash("hello world"));
- }
-}
+import org.osgi.annotation.versioning.Version;
diff --git
a/src/main/java/org/apache/sling/graphql/core/cache/GraphQLCacheProvider.java
b/src/main/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderImpl.java
similarity index 75%
rename from
src/main/java/org/apache/sling/graphql/core/cache/GraphQLCacheProvider.java
rename to
src/main/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderImpl.java
index 20afddf..dcfb4ae 100644
---
a/src/main/java/org/apache/sling/graphql/core/cache/GraphQLCacheProvider.java
+++
b/src/main/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderImpl.java
@@ -29,6 +29,8 @@ import javax.cache.configuration.MutableConfiguration;
import javax.cache.spi.CachingProvider;
import org.apache.commons.lang3.StringUtils;
+import org.apache.sling.graphql.api.cache.GraphQLCacheProvider;
+import org.apache.sling.graphql.core.engine.SlingGraphQLException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.osgi.framework.BundleContext;
@@ -43,9 +45,9 @@ import org.slf4j.LoggerFactory;
@Component(
immediate = true
)
-public class GraphQLCacheProvider {
+public class GraphQLCacheProviderImpl implements GraphQLCacheProvider {
- private static final Logger LOGGER =
LoggerFactory.getLogger(GraphQLCacheProvider.class);
+ private static final Logger LOGGER =
LoggerFactory.getLogger(GraphQLCacheProviderImpl.class);
@Reference
private CachingProvider cachingProvider;
@@ -54,19 +56,24 @@ public class GraphQLCacheProvider {
private ServiceRegistration<GraphQLCacheProvider> registration;
+ @Override
@Nullable
public String getQuery(@NotNull String hash, @NotNull String resourceType,
@Nullable String selectorString) {
return persistedQueriesCache.get(getCacheKey(hash, resourceType,
selectorString));
}
- public void cacheQuery(@NotNull String query, @NotNull String
resourceType, @Nullable String selectorString) {
- String key = getCacheKey("123", resourceType, selectorString);
+ @Override
+ @NotNull
+ public String cacheQuery(@NotNull String query, @NotNull String
resourceType, @Nullable String selectorString) {
+ String hash = getHash(query);
+ String key = getCacheKey(hash, resourceType, selectorString);
persistedQueriesCache.put(key, query);
+ return hash;
}
@Activate
- public void activate(BundleContext bundleContext) {
+ private void activate(BundleContext bundleContext) {
if (cachingProvider != null) {
try {
CacheManager cacheManager = cachingProvider.getCacheManager();
@@ -82,7 +89,7 @@ public class GraphQLCacheProvider {
}
@Deactivate
- public void deactivate(BundleContext bundleContext) {
+ private void deactivate() {
if (registration != null) {
registration.unregister();
}
@@ -99,16 +106,21 @@ public class GraphQLCacheProvider {
return key.toString();
}
- @NotNull String getHash(@NotNull String query) throws
NoSuchAlgorithmException {
- MessageDigest digest = MessageDigest.getInstance("SHA-256");
- byte[] hash = digest.digest(query.getBytes(StandardCharsets.UTF_8));
+ @NotNull String getHash(@NotNull String query) {
StringBuilder buffer = new StringBuilder();
- for (int i = 0; i < hash.length; i++) {
- String hex = Integer.toHexString(0xff & hash[i]);
- if (hex.length() == 1) {
- buffer.append('0');
+ try {
+ MessageDigest digest = MessageDigest.getInstance("SHA-256");
+ byte[] hash =
digest.digest(query.getBytes(StandardCharsets.UTF_8));
+
+ for (byte b : hash) {
+ String hex = Integer.toHexString(0xff & b);
+ if (hex.length() == 1) {
+ buffer.append('0');
+ }
+ buffer.append(hex);
}
- buffer.append(hex);
+ } catch (NoSuchAlgorithmException e) {
+ throw new SlingGraphQLException("Failed hashing query - " +
e.getMessage());
}
return buffer.toString();
}
diff --git
a/src/main/java/org/apache/sling/graphql/core/servlet/GraphQLServlet.java
b/src/main/java/org/apache/sling/graphql/core/servlet/GraphQLServlet.java
index 0daf0ef..25f7928 100644
--- a/src/main/java/org/apache/sling/graphql/core/servlet/GraphQLServlet.java
+++ b/src/main/java/org/apache/sling/graphql/core/servlet/GraphQLServlet.java
@@ -34,7 +34,7 @@ import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
-import org.apache.sling.graphql.core.cache.GraphQLCacheProvider;
+import org.apache.sling.graphql.api.cache.GraphQLCacheProvider;
import org.apache.sling.graphql.core.engine.GraphQLResourceQuery;
import org.apache.sling.graphql.core.engine.SlingDataFetcherSelector;
import org.apache.sling.graphql.core.json.JsonSerializer;
@@ -81,8 +81,6 @@ public class GraphQLServlet extends SlingAllMethodsServlet {
private static final String SUFFIX_PERSISTED = "/persisted";
private static final Pattern PATTERN_GET_PERSISTED_QUERY =
Pattern.compile("^" + SUFFIX_PERSISTED + "/([a-f0-9]{64})$");
- private Config config;
-
@ObjectClassDefinition(
name = "Apache Sling GraphQL Servlet",
description = "Servlet that implements GraphQL endpoints")
@@ -145,11 +143,9 @@ public class GraphQLServlet extends SlingAllMethodsServlet
{
} else {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
"Cannot find persisted query " + queryHash);
}
- return;
}
} else {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
- return;
}
} else {
execute(request.getResource(), request, response);
@@ -165,7 +161,9 @@ public class GraphQLServlet extends SlingAllMethodsServlet {
return;
}
String query = IOUtils.toString(request.getInputStream(),
StandardCharsets.UTF_8);
- cacheProvider.cacheQuery(query,
request.getResource().getResourceType(),
request.getRequestPathInfo().getSelectorString());
+ String hash = cacheProvider.cacheQuery(query,
request.getResource().getResourceType(),
+ request.getRequestPathInfo().getSelectorString());
+ response.addHeader("Location", getLocationHeaderValue(request,
hash));
response.setStatus(HttpServletResponse.SC_CREATED);
} else {
execute(request.getResource(), request, response);
@@ -210,4 +208,18 @@ public class GraphQLServlet extends SlingAllMethodsServlet
{
}
}
+ @NotNull
+ private String getLocationHeaderValue(@NotNull SlingHttpServletRequest
request, @NotNull String hash) {
+ StringBuilder location = new StringBuilder();
+ location.append(request.getScheme()).append("://");
+ location.append(request.getServerName());
+ int localPort = request.getLocalPort();
+ if (localPort != 80 && localPort != 443) {
+ location.append(":").append(localPort);
+ }
+
location.append(request.getContextPath()).append(request.getPathInfo()).append("/").append(hash);
+ return location.toString();
+ }
+
+
}
diff --git
a/src/test/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderTest.java
b/src/test/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderImplTest.java
similarity index 88%
rename from
src/test/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderTest.java
rename to
src/test/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderImplTest.java
index 66184b6..19c0d3a 100644
---
a/src/test/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderTest.java
+++
b/src/test/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderImplTest.java
@@ -20,13 +20,13 @@ package org.apache.sling.graphql.core.cache;
import org.junit.Test;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
-public class GraphQLCacheProviderTest {
+public class GraphQLCacheProviderImplTest {
@Test
public void getHash() throws Exception {
- GraphQLCacheProvider provider = new GraphQLCacheProvider();
+ GraphQLCacheProviderImpl provider = new GraphQLCacheProviderImpl();
assertEquals("b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9",
provider.getHash("hello world"));
}
}