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 f735eb9  SLING-9655 - Caching support for the GraphQL core
f735eb9 is described below

commit f735eb9f5dfad51f13fe9f48c4ef5547a88d0af9
Author: Radu Cotescu <[email protected]>
AuthorDate: Mon Aug 24 18:10:40 2020 +0200

    SLING-9655 - Caching support for the GraphQL core
    
    * switched the default GraphQLCacheProvider implementation
    to an in-memory LRU cache
---
 ...erImpl.java => SimpleGraphQLCacheProvider.java} | 123 +++++++++++++--------
 .../sling/graphql/core/servlet/GraphQLServlet.java |   1 -
 ...st.java => SimpleGraphQLCacheProviderTest.java} |  19 +++-
 .../graphql/core/it/GraphQLCoreTestSupport.java    |   4 -
 .../sling/graphql/core/it/GraphQLServletIT.java    |   1 -
 5 files changed, 91 insertions(+), 57 deletions(-)

diff --git 
a/src/main/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderImpl.java
 
b/src/main/java/org/apache/sling/graphql/core/cache/SimpleGraphQLCacheProvider.java
similarity index 52%
rename from 
src/main/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderImpl.java
rename to 
src/main/java/org/apache/sling/graphql/core/cache/SimpleGraphQLCacheProvider.java
index dcfb4ae..e68977d 100644
--- 
a/src/main/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderImpl.java
+++ 
b/src/main/java/org/apache/sling/graphql/core/cache/SimpleGraphQLCacheProvider.java
@@ -21,79 +21,92 @@ package org.apache.sling.graphql.core.cache;
 import java.nio.charset.StandardCharsets;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
-import java.util.Hashtable;
-
-import javax.cache.Cache;
-import javax.cache.CacheManager;
-import javax.cache.configuration.MutableConfiguration;
-import javax.cache.spi.CachingProvider;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 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;
-import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.Deactivate;
-import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.AttributeType;
+import org.osgi.service.metatype.annotations.Designate;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-@Component(
-        immediate = true
-)
-public class GraphQLCacheProviderImpl implements GraphQLCacheProvider {
+@Component()
+@Designate(ocd = SimpleGraphQLCacheProvider.Config.class)
+public class SimpleGraphQLCacheProvider implements GraphQLCacheProvider {
+
+    @ObjectClassDefinition(
+            name = "Apache Sling GraphQL Simple Cache Provider",
+            description = "The Apache Sling GraphQL Simple Cache Provider 
provides an in-memory size bound cache for persisted GraphQL " +
+                    "queries."
+    )
+    public @interface Config {
+
+        @AttributeDefinition(
+                name = "Capacity",
+                description = "The number of persisted queries to cache.",
+                type = AttributeType.INTEGER,
+                min = "0"
+        )
+        int capacity() default DEFAULT_CACHE_SIZE;
+    }
 
-    private static final Logger LOGGER = 
LoggerFactory.getLogger(GraphQLCacheProviderImpl.class);
+    private static final int DEFAULT_CACHE_SIZE = 1024;
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(SimpleGraphQLCacheProvider.class);
 
-    @Reference
-    private CachingProvider cachingProvider;
+    private InMemoryLRUCache persistedQueriesCache;
+    private ReadWriteLock readWriteLock;
+    private Lock readLock;
+    private Lock writeLock;
 
-    private Cache<String, String> persistedQueriesCache;
+    @Activate
+    public SimpleGraphQLCacheProvider(Config config) {
+        readWriteLock = new ReentrantReadWriteLock();
+        readLock = readWriteLock.readLock();
+        writeLock = readWriteLock.writeLock();
+        int cacheSize = config.capacity();
+        if (cacheSize < 0) {
+            cacheSize = 0;
+            LOGGER.debug("Cache capacity set to {}. Defaulting to 0.", 
config.capacity());
+        }
+        persistedQueriesCache = new InMemoryLRUCache(cacheSize);
+        LOGGER.debug("Initialized the in-memory cache for a maximum of {} 
queries.", config.capacity());
+    }
 
-    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));
+        readLock.lock();
+        try {
+            return persistedQueriesCache.get(getCacheKey(hash, resourceType, 
selectorString));
+        } finally {
+            readLock.unlock();
+        }
     }
 
     @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
-    private void activate(BundleContext bundleContext) {
-        if (cachingProvider != null) {
-            try {
-                CacheManager cacheManager = cachingProvider.getCacheManager();
-                persistedQueriesCache = cacheManager
-                        
.createCache(bundleContext.getBundle().getSymbolicName() + "_persistedQueries", 
new MutableConfiguration<>());
-                registration = 
bundleContext.registerService(GraphQLCacheProvider.class, this, new 
Hashtable<>());
-            } catch (Exception e) {
-                LOGGER.error("Unable to configure a cache for persisted 
queries.", e);
-            }
-        } else {
-            LOGGER.error("Cannot activate the " + 
GraphQLCacheProvider.class.getName() + " without a cachingProvider.");
-        }
-    }
-
-    @Deactivate
-    private void deactivate() {
-        if (registration != null) {
-            registration.unregister();
+        writeLock.lock();
+        try {
+            String hash = getHash(query);
+            String key = getCacheKey(hash, resourceType, selectorString);
+            persistedQueriesCache.put(key, query);
+            return hash;
+        } finally {
+            writeLock.unlock();
         }
-        cachingProvider.close();
     }
 
     @NotNull
@@ -125,4 +138,18 @@ public class GraphQLCacheProviderImpl implements 
GraphQLCacheProvider {
         return buffer.toString();
     }
 
+    private static class InMemoryLRUCache extends LinkedHashMap<String, 
String> {
+
+        private final int capacity;
+
+        public InMemoryLRUCache(int capacity) {
+            this.capacity = capacity;
+        }
+
+        @Override
+        protected boolean removeEldestEntry(Map.Entry eldest) {
+            return size() > capacity;
+        }
+    }
+
 }
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 a54b0e4..537875e 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
@@ -21,7 +21,6 @@
 package org.apache.sling.graphql.core.servlet;
 
 import java.io.IOException;
-import java.nio.charset.StandardCharsets;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
diff --git 
a/src/test/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderImplTest.java
 
b/src/test/java/org/apache/sling/graphql/core/cache/SimpleGraphQLCacheProviderTest.java
similarity index 71%
rename from 
src/test/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderImplTest.java
rename to 
src/test/java/org/apache/sling/graphql/core/cache/SimpleGraphQLCacheProviderTest.java
index 19c0d3a..8da286a 100644
--- 
a/src/test/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderImplTest.java
+++ 
b/src/test/java/org/apache/sling/graphql/core/cache/SimpleGraphQLCacheProviderTest.java
@@ -18,15 +18,28 @@
  
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 package org.apache.sling.graphql.core.cache;
 
+import java.lang.annotation.Annotation;
+
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
 
-public class GraphQLCacheProviderImplTest {
+public class SimpleGraphQLCacheProviderTest {
 
     @Test
-    public void getHash() throws Exception {
-        GraphQLCacheProviderImpl provider = new GraphQLCacheProviderImpl();
+    public void getHash() {
+        SimpleGraphQLCacheProvider provider = new 
SimpleGraphQLCacheProvider(new SimpleGraphQLCacheProvider.Config() {
+            @Override
+            public Class<? extends Annotation> annotationType() {
+                return null;
+            }
+
+            @Override
+            public int capacity() {
+                return 0;
+            }
+        });
+
         
assertEquals("b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9",
 provider.getHash("hello world"));
     }
 }
diff --git 
a/src/test/java/org/apache/sling/graphql/core/it/GraphQLCoreTestSupport.java 
b/src/test/java/org/apache/sling/graphql/core/it/GraphQLCoreTestSupport.java
index 604f218..60d10f0 100644
--- a/src/test/java/org/apache/sling/graphql/core/it/GraphQLCoreTestSupport.java
+++ b/src/test/java/org/apache/sling/graphql/core/it/GraphQLCoreTestSupport.java
@@ -94,10 +94,6 @@ public abstract class GraphQLCoreTestSupport extends 
TestSupport {
                 .asOption(),
             
mavenBundle().groupId("org.apache.sling").artifactId("org.apache.sling.servlet-helpers").versionAsInProject(),
             
mavenBundle().groupId("com.cedarsoftware").artifactId("json-io").versionAsInProject(),
-            
mavenBundle().groupId("javax.cache").artifactId("cache-api").versionAsInProject(),
-            
mavenBundle().groupId("com.typesafe").artifactId("config").versionAsInProject(),
-            
mavenBundle().groupId("com.github.ben-manes.caffeine").artifactId("caffeine").versionAsInProject(),
-            
mavenBundle().groupId("com.github.ben-manes.caffeine").artifactId("jcache").versionAsInProject(),
             slingResourcePresence(),
             jsonPath(),
             junitBundles()
diff --git 
a/src/test/java/org/apache/sling/graphql/core/it/GraphQLServletIT.java 
b/src/test/java/org/apache/sling/graphql/core/it/GraphQLServletIT.java
index 9f2d45e..e110f45 100644
--- a/src/test/java/org/apache/sling/graphql/core/it/GraphQLServletIT.java
+++ b/src/test/java/org/apache/sling/graphql/core/it/GraphQLServletIT.java
@@ -26,7 +26,6 @@ import org.apache.sling.graphql.api.SchemaProvider;
 import org.apache.sling.graphql.core.mocks.ReplacingSchemaProvider;
 import org.apache.sling.resource.presence.ResourcePresence;
 import org.apache.sling.servlethelpers.MockSlingHttpServletResponse;
-import org.apache.sling.servlethelpers.internalrequests.SlingInternalRequest;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.Configuration;

Reply via email to