keycloak-aplcache

fix caching

1/29/2018 7:26:51 PM

Details

diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/ClientAdapter.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/ClientAdapter.java
index 3176506..4c28ad6 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/ClientAdapter.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/ClientAdapter.java
@@ -23,6 +23,7 @@ import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleContainerModel;
 import org.keycloak.models.RoleModel;
+import org.keycloak.models.cache.CachedObject;
 import org.keycloak.models.cache.infinispan.entities.CachedClient;
 
 import java.security.MessageDigest;
@@ -36,7 +37,7 @@ import java.util.Set;
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public class ClientAdapter implements ClientModel {
+public class ClientAdapter implements ClientModel, CachedObject {
     protected RealmCacheSession cacheSession;
     protected RealmModel cachedRealm;
 
@@ -70,6 +71,11 @@ public class ClientAdapter implements ClientModel {
     }
 
     @Override
+    public long getCacheTimestamp() {
+        return cached.getCacheTimestamp();
+    }
+
+    @Override
     public void updateClient() {
         if (updated != null) updated.updateClient();
     }
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java
index 17cacc8..dd62377 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java
@@ -1336,8 +1336,14 @@ public class RealmAdapter implements CachedRealmModel {
 
     public void executeEvictions(ComponentModel model) {
         if (model == null) return;
-        // test that this is a realm component
-        if (model.getParentId() != null && !model.getParentId().equals(getId())) return;
+        // If not realm component, check to see if it is a user storage provider child component (i.e. LDAP mapper)
+        if (model.getParentId() != null && !model.getParentId().equals(getId())) {
+            ComponentModel parent = getComponent(model.getParentId());
+            if (parent != null && UserStorageProvider.class.getName().equals(parent.getProviderType())) {
+                session.userCache().evict(this);
+            }
+            return;
+        }
 
         // invalidate entire user cache if we're dealing with user storage SPI
         if (UserStorageProvider.class.getName().equals(model.getProviderType())) {
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/storage/ClientStorageTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/storage/ClientStorageTest.java
index c8c2f52..eb231db 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/storage/ClientStorageTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/federation/storage/ClientStorageTest.java
@@ -228,49 +228,6 @@ public class ClientStorageTest extends AbstractTestRealmKeycloakTest {
         events.clear();
     }
 
-    /*
-
-    @Test
-    public void testDailyEviction() {
-
-        // set eviction to 1 hour from now
-        Calendar eviction = Calendar.getInstance();
-        eviction.add(Calendar.HOUR, 1);
-        ComponentRepresentation propProviderRW = testRealmResource().components().component(propProviderRWId).toRepresentation();
-        propProviderRW.getConfig().putSingle(CACHE_POLICY, CacheableStorageProviderModel.CachePolicy.EVICT_DAILY.name());
-        propProviderRW.getConfig().putSingle(EVICTION_HOUR, Integer.toString(eviction.get(HOUR_OF_DAY)));
-        propProviderRW.getConfig().putSingle(EVICTION_MINUTE, Integer.toString(eviction.get(MINUTE)));
-        testRealmResource().components().component(propProviderRWId).update(propProviderRW);
-
-        // now
-        testingClient.server().run(session -> {
-            RealmModel realm = session.realms().getRealmByName("test");
-            UserModel user = session.users().getUserByUsername("thor", realm);
-        });
-
-        // run twice to make sure its in cache.
-        testingClient.server().run(session -> {
-            RealmModel realm = session.realms().getRealmByName("test");
-            UserModel user = session.users().getUserByUsername("thor", realm);
-            System.out.println("User class: " + user.getClass());
-            Assert.assertTrue(user instanceof CachedUserModel); // should still be cached
-        });
-
-        setTimeOffset(2 * 60 * 60); // 2 hours in future
-
-        testingClient.server().run(session -> {
-            RealmModel realm = session.realms().getRealmByName("test");
-            UserModel user = session.users().getUserByUsername("thor", realm);
-            System.out.println("User class: " + user.getClass());
-            Assert.assertFalse(user instanceof CachedUserModel); // should be evicted
-        });
-
-    }
-
-
-        */
-
-
     @Test
     public void testDailyEviction() {
         testIsCached();
diff --git a/testsuite/integration-deprecated/src/test/java/org/keycloak/testsuite/federation/storage/UserStorageTest.java b/testsuite/integration-deprecated/src/test/java/org/keycloak/testsuite/federation/storage/UserStorageTest.java
index 48228a2..d446985 100644
--- a/testsuite/integration-deprecated/src/test/java/org/keycloak/testsuite/federation/storage/UserStorageTest.java
+++ b/testsuite/integration-deprecated/src/test/java/org/keycloak/testsuite/federation/storage/UserStorageTest.java
@@ -167,16 +167,36 @@ public class UserStorageTest {
         KeycloakSession session = keycloakRule.startSession();
         RealmModel realm = session.realms().getRealmByName("test");
         CachedUserModel thor = (CachedUserModel)session.users().getUserByUsername("thor", realm);
-        long thorTimestamp = thor.getCacheTimestamp();
+        long lastTimestamp = thor.getCacheTimestamp();
         realm.updateComponent(model);
         keycloakRule.stopSession(session, true);
 
+        session = keycloakRule.startSession();
+        realm = session.realms().getRealmByName("test");
+        thor = (CachedUserModel)session.users().getUserByUsername("thor", realm);
+        lastTimestamp = thor.getCacheTimestamp();
+        realm.updateComponent(model);
+        keycloakRule.stopSession(session, true);
+
+        // test is cached
+        session = keycloakRule.startSession();
+        realm = session.realms().getRealmByName("test");
+        thor = (CachedUserModel)session.users().getUserByUsername("thor", realm);
+        // thor should be evicted because we changed the model
+        Assert.assertTrue(thor.getCacheTimestamp() > lastTimestamp);
+        lastTimestamp = thor.getCacheTimestamp();
+        keycloakRule.stopSession(session, true);
+
+
         Time.setOffset(60 * 2 * 60); // 2 hours
 
         session = keycloakRule.startSession();
         realm = session.realms().getRealmByName("test");
         UserModel thor2 = session.users().getUserByUsername("thor", realm);
-        Assert.assertFalse(thor2 instanceof CachedUserModel);
+        // thor should be evicted because we put it 2 hours in the future
+        if (thor2 instanceof CachedUserModel) {
+            Assert.assertTrue(((CachedUserModel)thor2).getCacheTimestamp() > lastTimestamp);
+        }
         model.getConfig().remove("cachePolicy");
         model.getConfig().remove("evictionHour");
         model.getConfig().remove("evictionMinute");
@@ -199,24 +219,46 @@ public class UserStorageTest {
 
         KeycloakSession session = keycloakRule.startSession();
         RealmModel realm = session.realms().getRealmByName("test");
-        CachedUserModel thor = (CachedUserModel)session.users().getUserByUsername("thor", realm);
         realm.updateComponent(model);
         keycloakRule.stopSession(session, true);
 
+        session = keycloakRule.startSession();
+        realm = session.realms().getRealmByName("test");
+        CachedUserModel thor = (CachedUserModel)session.users().getUserByUsername("thor", realm);
+        long lastTimestamp = thor.getCacheTimestamp();
+        keycloakRule.stopSession(session, true);
+
+        session = keycloakRule.startSession();
+        realm = session.realms().getRealmByName("test");
+        thor = (CachedUserModel)session.users().getUserByUsername("thor", realm);
+        lastTimestamp = thor.getCacheTimestamp();
+        keycloakRule.stopSession(session, true);
+
+        session = keycloakRule.startSession();
+        realm = session.realms().getRealmByName("test");
+        thor = (CachedUserModel)session.users().getUserByUsername("thor", realm);
+        lastTimestamp = thor.getCacheTimestamp();
+        keycloakRule.stopSession(session, true);
+
         Time.setOffset(60 * 60 * 24 * 2); // 2 days in future, should be cached still
 
         session = keycloakRule.startSession();
         realm = session.realms().getRealmByName("test");
         // test still
-        UserModel thor2 = session.users().getUserByUsername("thor", realm);
-        Assert.assertTrue(thor2 instanceof CachedUserModel);
+        thor = (CachedUserModel)session.users().getUserByUsername("thor", realm);
+        Assert.assertEquals(thor.getCacheTimestamp(), lastTimestamp);
+        lastTimestamp = thor.getCacheTimestamp();
         keycloakRule.stopSession(session, true);
+
         Time.setOffset(Time.getOffset() + 60 * 60 * 24 * 3); // 3 days into future, cache will be invalidated
 
         session = keycloakRule.startSession();
         realm = session.realms().getRealmByName("test");
-        thor2 = session.users().getUserByUsername("thor", realm);
-        Assert.assertFalse(thor2 instanceof CachedUserModel);
+        UserModel thor2 = session.users().getUserByUsername("thor", realm);
+        // thor should be evicted because we put it 2 hours in the future
+        if (thor2 instanceof CachedUserModel) {
+            Assert.assertTrue(((CachedUserModel)thor2).getCacheTimestamp() > lastTimestamp);
+        }
         model.getConfig().remove("cachePolicy");
         model.getConfig().remove("evictionHour");
         model.getConfig().remove("evictionMinute");
@@ -233,24 +275,44 @@ public class UserStorageTest {
 
         KeycloakSession session = keycloakRule.startSession();
         RealmModel realm = session.realms().getRealmByName("test");
-        CachedUserModel thor = (CachedUserModel)session.users().getUserByUsername("thor", realm);
         realm.updateComponent(model);
         keycloakRule.stopSession(session, true);
 
+        session = keycloakRule.startSession();
+        realm = session.realms().getRealmByName("test");
+        CachedUserModel thor = (CachedUserModel)session.users().getUserByUsername("thor", realm);
+        long lastTimestamp = thor.getCacheTimestamp();
+        keycloakRule.stopSession(session, true);
+
+
+        session = keycloakRule.startSession();
+        realm = session.realms().getRealmByName("test");
+        thor = (CachedUserModel)session.users().getUserByUsername("thor", realm);
+        lastTimestamp = thor.getCacheTimestamp();
+        keycloakRule.stopSession(session, true);
+
+
         Time.setOffset(60 * 5); // 5 minutes in future, should be cached still
+        session = keycloakRule.startSession();
+        realm = session.realms().getRealmByName("test");
+        thor = (CachedUserModel)session.users().getUserByUsername("thor", realm);
+        Assert.assertEquals(thor.getCacheTimestamp(), lastTimestamp);
+        lastTimestamp = thor.getCacheTimestamp();
+        keycloakRule.stopSession(session, true);
+
+        Time.setOffset(60 * 20); // 20 minutes into future, cache will be invalidated
 
         session = keycloakRule.startSession();
         realm = session.realms().getRealmByName("test");
-        // test still
         UserModel thor2 = session.users().getUserByUsername("thor", realm);
-        Assert.assertTrue(thor2 instanceof CachedUserModel);
+        // thor should be evicted because we put it 2 hours in the future
+        if (thor2 instanceof CachedUserModel) {
+            Assert.assertTrue(((CachedUserModel)thor2).getCacheTimestamp() > lastTimestamp);
+        }
         keycloakRule.stopSession(session, true);
-        Time.setOffset(60 * 20); // 20 minutes into future, cache will be invalidated
 
         session = keycloakRule.startSession();
         realm = session.realms().getRealmByName("test");
-        thor2 = session.users().getUserByUsername("thor", realm);
-        Assert.assertFalse(thor2 instanceof CachedUserModel);
         model.getConfig().remove("cachePolicy");
         model.getConfig().remove("maxLifespan");
         realm.updateComponent(model);