From 2acf3bfc6f2c3663f85ac1c14455f393839c8b2d Mon Sep 17 00:00:00 2001
From: "thorben.betten" <thorben.betten@open-xchange.com>
Date: Fri, 7 Mar 2025 15:02:36 +0100
Subject: [PATCH] Prefer a local cache for too frequently queried user data -
 /appsuite/platform/core#215

(cherry picked from commit 16b2c51f9154bc475a11eb657fb054d5b56e0c64)
---
 .../impl/LocalCachingContextStorage.java      | 18 +++++++++------
 .../ldap/LocalCachingUserStorage.java         | 23 +++++++++++--------
 2 files changed, 24 insertions(+), 17 deletions(-)

diff --git a/com.openexchange.server/src/com/openexchange/groupware/contexts/impl/LocalCachingContextStorage.java b/com.openexchange.server/src/com/openexchange/groupware/contexts/impl/LocalCachingContextStorage.java
index b93d81e36142..ed268bdf0c25 100644
--- a/com.openexchange.server/src/com/openexchange/groupware/contexts/impl/LocalCachingContextStorage.java
+++ b/com.openexchange.server/src/com/openexchange/groupware/contexts/impl/LocalCachingContextStorage.java
@@ -215,7 +215,7 @@ public class LocalCachingContextStorage extends ContextStorage {
         Integer contextId = contextIdCache.getIfPresent(loginInfo);
         if (contextId == null) {
             try {
-                contextId = contextIdCache.get(loginInfo, this::loadContextByLoginInfo);
+                contextId = contextIdCache.get(loginInfo, l0ginInfo -> loadContextByLoginInfo(l0ginInfo, false));
             } catch (OXRuntimeException e) { // NOSONARLINT
                 throw e.getException();
             }
@@ -227,10 +227,11 @@ public class LocalCachingContextStorage extends ContextStorage {
      * Loads the context by given login info.
      *
      * @param loginInfo The login info to load by
+     * @param populateContextCache <code>true</code> to populate context cache; otherwise <code>false</code>
      * @return The identifier of the associated context or {@link ContextStorage#NOT_FOUND} if there is none
      * @throws OXRuntimeException If retrieval fails
      */
-    private Integer loadContextByLoginInfo(String loginInfo) {
+    private Integer loadContextByLoginInfo(String loginInfo, boolean populateContextCache) {
         try {
             ContextExtended context = persistentImpl.getContext(loginInfo);
             if (null == context) {
@@ -238,7 +239,9 @@ public class LocalCachingContextStorage extends ContextStorage {
             }
             triggerUpdate(context, UpdateBehavior.NONE);
             Integer contextId = I(context.getContextId());
-            contextCache.put(contextId, context);
+            if (populateContextCache) {
+                contextCache.put(contextId, context);
+            }
             return contextId;
         } catch (OXException e) {
             throw new OXRuntimeException(e);
@@ -250,7 +253,7 @@ public class LocalCachingContextStorage extends ContextStorage {
         ContextExtended context = contextCache.getIfPresent(I(contextId));
         if (context == null) {
             try {
-                context = contextCache.get(I(contextId), cid -> loadContextById(cid.intValue(), updateBehavior));
+                context = contextCache.get(I(contextId), cid -> loadContextById(cid.intValue(), updateBehavior, false));
             } catch (OXRuntimeException e) { // NOSONARLINT
                 throw e.getException();
             }
@@ -262,15 +265,16 @@ public class LocalCachingContextStorage extends ContextStorage {
      * Loads the context by given identifier.
      *
      * @param contextId The context identifier
-     * @param updateBehavior The update behavior to obey
+     * @param updateBehavior The update behavior to obey contextIdCache
+     * @param populateContextIdCache <code>true</code> to populate login-info-2-context-identifier cache; otherwise <code>false</code>
      * @return The context
      * @throws OXRuntimeException If retrieval fails
      */
-    private ContextExtended loadContextById(int contextId, UpdateBehavior updateBehavior) {
+    private ContextExtended loadContextById(int contextId, UpdateBehavior updateBehavior, boolean populateContextIdCache) {
         try {
             ContextExtended context = persistentImpl.loadContext(contextId);
             triggerUpdate(context, updateBehavior);
-            String[] loginInfo = context.getLoginInfo();
+            String[] loginInfo = populateContextIdCache ? context.getLoginInfo() : null;
             if (loginInfo != null) {
                 Integer iContextId = I(contextId);
                 for (String li : loginInfo) {
diff --git a/com.openexchange.server/src/com/openexchange/groupware/ldap/LocalCachingUserStorage.java b/com.openexchange.server/src/com/openexchange/groupware/ldap/LocalCachingUserStorage.java
index e7464a1838f2..24d33ca91efe 100644
--- a/com.openexchange.server/src/com/openexchange/groupware/ldap/LocalCachingUserStorage.java
+++ b/com.openexchange.server/src/com/openexchange/groupware/ldap/LocalCachingUserStorage.java
@@ -212,7 +212,7 @@ public class LocalCachingUserStorage extends UserStorage {
         CachedUser user = userCache.getIfPresent(key);
         if (user == null) {
             try {
-                user = userCache.get(key, this::loadUserById);
+                user = userCache.get(key, k -> loadUserById(key, false));
             } catch (OXRuntimeException e) { // NOSONARLINT
                 throw e.getException();
             }
@@ -224,13 +224,14 @@ public class LocalCachingUserStorage extends UserStorage {
      * Loads the user by given identifier.
      *
      * @param uac The user and context identifier
+     * @param populateLoginCache <code>true</code> to populate login-2-user cache; otherwise <code>false</code>
      * @return The loaded user
      * @throws OXRuntimeException If retrieval fails
      */
-    private CachedUser loadUserById(UserAndContext uac) {
+    private CachedUser loadUserById(UserAndContext uac, boolean populateLoginCache) {
         try {
             User user = delegate.getUser(uac.getUserId(), uac.getContextId());
-            String loginInfo = user.getLoginInfo();
+            String loginInfo = populateLoginCache ? user.getLoginInfo() : null;
             if (loginInfo != null) {
                 logins2UserCache.put(new ContextIdAndString(uac.getContextId(), loginInfo), I(user.getId()));
             }
@@ -246,7 +247,7 @@ public class LocalCachingUserStorage extends UserStorage {
         CachedUser user = userCache.getIfPresent(key);
         if (user == null) {
             try {
-                user = userCache.get(key, uac -> loadUserById(uac, context, con));
+                user = userCache.get(key, uac -> loadUserById(uac, context, false, con));
             } catch (OXRuntimeException e) { // NOSONARLINT
                 throw e.getException();
             }
@@ -259,14 +260,15 @@ public class LocalCachingUserStorage extends UserStorage {
      *
      * @param uac The user and context identifier
      * @param context The given context
+     * @param populateLoginCache <code>true</code> to populate login-2-user cache; otherwise <code>false</code>
      * @param con The connection to use
      * @return The loaded user
      * @throws OXRuntimeException If retrieval fails
      */
-    private CachedUser loadUserById(UserAndContext uac, Context context, Connection con) {
+    private CachedUser loadUserById(UserAndContext uac, Context context, boolean populateLoginCache, Connection con) {
         try {
             User user = delegate.loadIfAbsent(uac.getUserId(), getEffectiveContext(uac.getContextId(), context), con);
-            String loginInfo = user.getLoginInfo();
+            String loginInfo = populateLoginCache ? user.getLoginInfo() : null;
             if (loginInfo != null) {
                 logins2UserCache.put(new ContextIdAndString(uac.getContextId(), loginInfo), I(user.getId()));
             }
@@ -303,7 +305,7 @@ public class LocalCachingUserStorage extends UserStorage {
         CachedUser user = userCache.getIfPresent(key);
         if (user == null) {
             try {
-                user = userCache.get(key, this::loadUserById);
+                user = userCache.get(key, k -> loadUserById(k, false));
             } catch (OXRuntimeException e) { // NOSONARLINT
                 throw e.getException();
             }
@@ -317,7 +319,7 @@ public class LocalCachingUserStorage extends UserStorage {
         CachedUser user = userCache.getIfPresent(key);
         if (user == null) {
             try {
-                user = userCache.get(key, uac -> loadUserById2(uac, ctx, con));
+                user = userCache.get(key, uac -> loadUserById2(uac, ctx, false, con));
             } catch (OXRuntimeException e) { // NOSONARLINT
                 throw e.getException();
             }
@@ -330,14 +332,15 @@ public class LocalCachingUserStorage extends UserStorage {
      *
      * @param uac The user and context identifier
      * @param context The given context
+     * @param populateLoginCache <code>true</code> to populate login-2-user cache; otherwise <code>false</code>
      * @param con The connection to use
      * @return The loaded user
      * @throws OXRuntimeException If retrieval fails
      */
-    private CachedUser loadUserById2(UserAndContext uac, Context context, Connection con) {
+    private CachedUser loadUserById2(UserAndContext uac, Context context, boolean populateLoginCache, Connection con) {
         try {
             User user = delegate.getUser(getEffectiveContext(uac.getContextId(), context), uac.getUserId(), con);
-            String loginInfo = user.getLoginInfo();
+            String loginInfo = populateLoginCache ? user.getLoginInfo() : null;
             if (loginInfo != null) {
                 logins2UserCache.put(new ContextIdAndString(uac.getContextId(), loginInfo), I(user.getId()));
             }
-- 
GitLab