Skip to content

Commit 2f9487e

Browse files
chore: implement 404 strategy and remove logs (dotCMS#32998) (dotCMS#33001)
As discussed on the parent [issue](dotCMS#32430 (comment)) a 404 strategy was added, and now the addPermissionsToCache function doesn't log an error if the list of permissions is empty, it returns an empty collection and puts on the cache a new object `EmptyPermissionsCacheEntry` which will represent this 404 and expires in 5 minutes. Then when getting the permissions from the cache if it is this object and it has expired then remove it from the cache and return null to recalculate it. This PR fixes: dotCMS#32998 --------- Co-authored-by: Daniel Silva <[email protected]>
1 parent 0974969 commit 2f9487e

File tree

1 file changed

+49
-10
lines changed

1 file changed

+49
-10
lines changed

dotCMS/src/main/java/com/dotmarketing/business/PermissionCacheImpl.java

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,24 @@
66
*/
77
package com.dotmarketing.business;
88

9+
import com.dotcms.cache.Expirable;
910
import com.dotmarketing.beans.Host;
1011
import com.dotmarketing.db.DbConnectionFactory;
11-
import com.dotmarketing.exception.DotDataException;
1212
import com.dotmarketing.portlets.contentlet.model.Contentlet;
13+
import com.dotmarketing.util.Config;
1314
import com.dotmarketing.util.UtilMethods;
1415
import com.liferay.portal.model.User;
1516
import com.liferay.util.StringPool;
17+
import java.io.Serializable;
18+
import java.time.LocalDateTime;
19+
import java.util.Collections;
1620
import java.util.List;
1721

1822
import com.dotmarketing.beans.Permission;
1923
import com.dotmarketing.util.Logger;
2024
import java.util.Optional;
2125
import javax.validation.constraints.NotNull;
26+
import io.vavr.Lazy;
2227

2328
/**
2429
*
@@ -28,6 +33,9 @@
2833
*/
2934
public class PermissionCacheImpl extends PermissionCache {
3035

36+
static final Lazy<Integer> EMPTY_PERMISSIONS_TTL =
37+
Lazy.of(() -> Config.getIntProperty("EMPTY_PERMISSIONS_TTL", 300)); // 5 minutes default
38+
3139
private DotCacheAdministrator cache;
3240

3341
private final String primaryGroup = "PermissionCache";
@@ -43,13 +51,13 @@ protected PermissionCacheImpl() {
4351
* @see com.dotmarketing.business.PermissionCache#addToPermissionCache(java.lang.String, java.util.List)
4452
*/
4553
protected List<Permission> addToPermissionCache(final String key, List<Permission> permissions) {
46-
if(permissions!=null && permissions.isEmpty()) {
47-
Logger.warn(this.getClass(), ()->" !!! Putting an empty list of permissions in the cache for asset:" + key +". Every asset should have at least 1 permission (or inherited permission) associated with it");
48-
Thread.dumpStack();
49-
}
54+
if (permissions != null && permissions.isEmpty()) {
55+
cache.put(primaryGroup + key, new EmptyPermissionsCacheEntry(EMPTY_PERMISSIONS_TTL.get()), primaryGroup);
56+
return Collections.emptyList();
57+
}
5058

5159
// Add the key to the cache
52-
cache.put(primaryGroup + key, permissions,primaryGroup);
60+
cache.put(primaryGroup + key, permissions, primaryGroup);
5361

5462
return permissions;
5563
}
@@ -59,14 +67,25 @@ protected List<Permission> addToPermissionCache(final String key, List<Permissio
5967
*/
6068
@SuppressWarnings("unchecked")
6169
protected List<Permission> getPermissionsFromCache(String key) {
62-
key = primaryGroup + key;
63-
List<Permission> perms = null;
70+
final String cacheKey = primaryGroup + key;
71+
Object cachedObject = null;
6472
try{
65-
perms = (List<Permission>) cache.get(key, primaryGroup);
73+
cachedObject = cache.get(cacheKey, primaryGroup);
6674
}catch (DotCacheException e) {
6775
Logger.debug(this,"Cache Entry not found", e);
6876
}
69-
return perms;
77+
78+
if (cachedObject instanceof EmptyPermissionsCacheEntry) {
79+
final EmptyPermissionsCacheEntry entry = (EmptyPermissionsCacheEntry) cachedObject;
80+
if (entry.isExpired()) {
81+
cache.remove(cacheKey, primaryGroup);
82+
return null;
83+
}
84+
85+
return Collections.emptyList();
86+
}
87+
88+
return (List<Permission>) cachedObject;
7089
}
7190

7291
/* (non-Javadoc)
@@ -173,4 +192,24 @@ private Optional<String> shortLivedKey(@NotNull final Permissionable permissiona
173192
public void flushShortTermCache() {
174193
cache.flushGroup(shortLivedGroup);
175194
}
195+
196+
/**
197+
* Cache entry for empty permissions with TTL expiration.
198+
* Implements the 404 strategy - cache empty results for a limited time to avoid repeated lookups.
199+
*/
200+
private static class EmptyPermissionsCacheEntry implements Serializable, Expirable {
201+
private static final long serialVersionUID = 1L;
202+
203+
private final long ttl;
204+
private final LocalDateTime since;
205+
206+
EmptyPermissionsCacheEntry(final long ttl) {
207+
this.ttl = ttl;
208+
this.since = LocalDateTime.now();
209+
}
210+
211+
public boolean isExpired() {
212+
return LocalDateTime.now().isAfter(since.plusSeconds(ttl));
213+
}
214+
}
176215
}

0 commit comments

Comments
 (0)