Use a separate fork join pool for cache loading operations
This commit is contained in:
@@ -27,7 +27,6 @@ package me.lucko.luckperms.common.cacheddata;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.AsyncLoadingCache;
|
||||
import com.github.benmanes.caffeine.cache.CacheLoader;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
|
||||
import me.lucko.luckperms.api.ChatMetaType;
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
@@ -41,6 +40,7 @@ import me.lucko.luckperms.common.calculator.CalculatorFactory;
|
||||
import me.lucko.luckperms.common.calculator.PermissionCalculator;
|
||||
import me.lucko.luckperms.common.metastacking.SimpleMetaStack;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.util.CaffeineFactory;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
@@ -64,14 +64,14 @@ public abstract class AbstractCachedData implements CachedData {
|
||||
/**
|
||||
* The cache used for {@link PermissionCache} instances.
|
||||
*/
|
||||
private final AsyncLoadingCache<Contexts, PermissionCache> permission = Caffeine.newBuilder()
|
||||
private final AsyncLoadingCache<Contexts, PermissionCache> permission = CaffeineFactory.newBuilder()
|
||||
.expireAfterAccess(2, TimeUnit.MINUTES)
|
||||
.buildAsync(new PermissionCacheLoader());
|
||||
|
||||
/**
|
||||
* The cache used for {@link MetaCache} instances.
|
||||
*/
|
||||
private final AsyncLoadingCache<MetaContexts, MetaCache> meta = Caffeine.newBuilder()
|
||||
private final AsyncLoadingCache<MetaContexts, MetaCache> meta = CaffeineFactory.newBuilder()
|
||||
.expireAfterAccess(2, TimeUnit.MINUTES)
|
||||
.buildAsync(new MetaCacheLoader());
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
package me.lucko.luckperms.common.commands.group;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
@@ -43,6 +42,7 @@ import me.lucko.luckperms.common.locale.command.CommandSpec;
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.util.CaffeineFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -55,7 +55,7 @@ public class GroupMainCommand extends MainCommand<Group, String> {
|
||||
// this helps prevent race conditions where commands are being executed concurrently
|
||||
// and overriding each other.
|
||||
// it's not a great solution, but it mostly works.
|
||||
private final LoadingCache<String, ReentrantLock> locks = Caffeine.newBuilder()
|
||||
private final LoadingCache<String, ReentrantLock> locks = CaffeineFactory.newBuilder()
|
||||
.expireAfterAccess(1, TimeUnit.HOURS)
|
||||
.build(key -> new ReentrantLock());
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
package me.lucko.luckperms.common.commands.misc;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
|
||||
import me.lucko.luckperms.common.bulkupdate.BulkUpdate;
|
||||
import me.lucko.luckperms.common.bulkupdate.BulkUpdateBuilder;
|
||||
@@ -48,6 +47,7 @@ import me.lucko.luckperms.common.locale.command.CommandSpec;
|
||||
import me.lucko.luckperms.common.locale.message.Message;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.util.CaffeineFactory;
|
||||
import me.lucko.luckperms.common.util.Predicates;
|
||||
|
||||
import java.util.List;
|
||||
@@ -55,7 +55,7 @@ import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class BulkUpdateCommand extends SingleCommand {
|
||||
private final Cache<String, BulkUpdate> pendingOperations = Caffeine.newBuilder().expireAfterWrite(30, TimeUnit.SECONDS).build();
|
||||
private final Cache<String, BulkUpdate> pendingOperations = CaffeineFactory.newBuilder().expireAfterWrite(30, TimeUnit.SECONDS).build();
|
||||
|
||||
public BulkUpdateCommand(LocaleManager locale) {
|
||||
super(CommandSpec.BULK_UPDATE.localize(locale), "BulkUpdate", CommandPermission.BULK_UPDATE, Predicates.alwaysFalse());
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
package me.lucko.luckperms.common.commands.track;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
@@ -37,6 +36,7 @@ import me.lucko.luckperms.common.locale.command.CommandSpec;
|
||||
import me.lucko.luckperms.common.model.Track;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.util.CaffeineFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -49,7 +49,7 @@ public class TrackMainCommand extends MainCommand<Track, String> {
|
||||
// this helps prevent race conditions where commands are being executed concurrently
|
||||
// and overriding each other.
|
||||
// it's not a great solution, but it mostly works.
|
||||
private final LoadingCache<String, ReentrantLock> locks = Caffeine.newBuilder()
|
||||
private final LoadingCache<String, ReentrantLock> locks = CaffeineFactory.newBuilder()
|
||||
.expireAfterAccess(1, TimeUnit.HOURS)
|
||||
.build(key -> new ReentrantLock());
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
package me.lucko.luckperms.common.commands.user;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
@@ -46,6 +45,7 @@ import me.lucko.luckperms.common.model.UserIdentifier;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.sender.Sender;
|
||||
import me.lucko.luckperms.common.storage.misc.DataConstraints;
|
||||
import me.lucko.luckperms.common.util.CaffeineFactory;
|
||||
import me.lucko.luckperms.common.util.Uuids;
|
||||
|
||||
import java.util.List;
|
||||
@@ -60,7 +60,7 @@ public class UserMainCommand extends MainCommand<User, UserIdentifier> {
|
||||
// this helps prevent race conditions where commands are being executed concurrently
|
||||
// and overriding each other.
|
||||
// it's not a great solution, but it mostly works.
|
||||
private final LoadingCache<UUID, ReentrantLock> locks = Caffeine.newBuilder()
|
||||
private final LoadingCache<UUID, ReentrantLock> locks = CaffeineFactory.newBuilder()
|
||||
.expireAfterAccess(1, TimeUnit.HOURS)
|
||||
.build(key -> new ReentrantLock());
|
||||
|
||||
|
||||
@@ -25,12 +25,12 @@
|
||||
|
||||
package me.lucko.luckperms.common.primarygroup;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
|
||||
import me.lucko.luckperms.api.Contexts;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.node.factory.NodeFactory;
|
||||
import me.lucko.luckperms.common.util.CaffeineFactory;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
@@ -44,7 +44,7 @@ import java.util.concurrent.TimeUnit;
|
||||
public abstract class ContextualHolder extends StoredHolder {
|
||||
|
||||
// cache lookups
|
||||
private final LoadingCache<Contexts, Optional<String>> cache = Caffeine.newBuilder()
|
||||
private final LoadingCache<Contexts, Optional<String>> cache = CaffeineFactory.newBuilder()
|
||||
.expireAfterAccess(1, TimeUnit.MINUTES)
|
||||
.build(this::calculateValue);
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package me.lucko.luckperms.common.util;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
|
||||
public final class CaffeineFactory {
|
||||
private CaffeineFactory() {}
|
||||
|
||||
/**
|
||||
* Our own fork join pool for LuckPerms cache operations.
|
||||
*
|
||||
* By default, Caffeine uses the ForkJoinPool.commonPool instance.
|
||||
* However... ForkJoinPool is a fixed size pool limited by Runtime.availableProcessors.
|
||||
* Some (bad) plugins incorrectly use this pool for i/o operations, make calls to Thread.sleep
|
||||
* or otherwise block waiting for something else to complete. This prevents the LP cache loading
|
||||
* operations from running.
|
||||
*
|
||||
* By using our own pool, we ensure this will never happen.
|
||||
*/
|
||||
private static final ForkJoinPool loaderPool = new ForkJoinPool();
|
||||
|
||||
public static Caffeine<Object, Object> newBuilder() {
|
||||
return Caffeine.newBuilder().executor(loaderPool);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user