Limit rate+concurrency instead of only concurrency
Rename post-relog update to Login sync
This commit is contained in:
@@ -845,7 +845,6 @@ public class Config
|
||||
+ "")
|
||||
.build();
|
||||
|
||||
// TODO Write strings
|
||||
public static class ServerNetworking
|
||||
{
|
||||
public static ConfigEntry<Boolean> enableServerNetworking = new ConfigEntry.Builder<Boolean>()
|
||||
@@ -862,23 +861,6 @@ public class Config
|
||||
+ "Note: This requires DH to be installed on the server in order to function. \n"
|
||||
+ "")
|
||||
.build();
|
||||
|
||||
public static ConfigEntry<Boolean> enableRealTimeUpdates = new ConfigEntry.Builder<Boolean>()
|
||||
.setServersideShortName("enableRealTimeUpdates")
|
||||
.set(false)
|
||||
.comment(""
|
||||
+ "Enables real time updates from server."
|
||||
+ "")
|
||||
.build();
|
||||
|
||||
public static ConfigEntry<Boolean> enablePostRelogUpdate = new ConfigEntry.Builder<Boolean>()
|
||||
.setServersideShortName("enablePostRelogUpdate")
|
||||
.set(false)
|
||||
.comment(""
|
||||
+ "Enables updating of LODs after relog."
|
||||
+ "")
|
||||
.build();
|
||||
|
||||
public static ConfigEntry<Integer> serverPort = new ConfigEntry.Builder<Integer>()
|
||||
.setServersideShortName("serverPort")
|
||||
.setMinDefaultMax(1, 25049, 65535)
|
||||
@@ -893,16 +875,16 @@ public class Config
|
||||
.setMinDefaultMax(1, 10, 100)
|
||||
.comment(""
|
||||
+ "Amount of rate/concurrency limit hits in one second before disconnecting the offending clients. \n"
|
||||
+ "Warning: too low values can cause slower clients to disconnect prematurely.\n"
|
||||
+ "This setting is server-only; it does not have effect on client.\n"
|
||||
+ "This setting is server-only; it does not have effect on the client.\n"
|
||||
+ "")
|
||||
.build();
|
||||
|
||||
public static ConfigEntry<Integer> fullDataRequestConcurrencyLimit = new ConfigEntry.Builder<Integer>()
|
||||
.setServersideShortName("fullDataRequestConcurrencyLimit")
|
||||
|
||||
public static ConfigEntry<Integer> generationRequestRCLimit = new ConfigEntry.Builder<Integer>()
|
||||
.setServersideShortName("generationRequestRCLimit")
|
||||
.setMinDefaultMax(1, 20, 100)
|
||||
.comment(""
|
||||
+ "Limits the amount of sent/processed LOD *generation* requests concurrently on server, per player. \n"
|
||||
+ "Limits the amount of generation requests sent by client and processed by server. \n"
|
||||
+ "")
|
||||
.build();
|
||||
|
||||
@@ -914,7 +896,7 @@ public class Config
|
||||
+ "")
|
||||
.build();
|
||||
|
||||
public static ConfigEntry<Integer> fullDataRequestBeginDelay = new ConfigEntry.Builder<Integer>()
|
||||
public static ConfigEntry<Integer> generationRequestBeginDelay = new ConfigEntry.Builder<Integer>()
|
||||
.setMinDefaultMax(0, 3, 10)
|
||||
.comment(""
|
||||
+ "Adds a delay in seconds before sending LOD requests, when generation is enabled. \n"
|
||||
@@ -922,25 +904,31 @@ public class Config
|
||||
+ "")
|
||||
.build();
|
||||
|
||||
public static ConfigEntry<Integer> postRelogUpdateConcurrencyLimit = new ConfigEntry.Builder<Integer>()
|
||||
.setServersideShortName("postRelogUpdateConcurrencyLimit")
|
||||
.setMinDefaultMax(1, 50, 100)
|
||||
|
||||
public static ConfigEntry<Boolean> enableRealTimeUpdates = new ConfigEntry.Builder<Boolean>()
|
||||
.setServersideShortName("enableRealTimeUpdates")
|
||||
.set(false)
|
||||
.comment(""
|
||||
+ "Limits the amount of sent/processed LOD *update* requests concurrently on server, per player. \n"
|
||||
+ "Enables real time updates from server."
|
||||
+ "")
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Intentionally disabled.
|
||||
* @see #enablePostRelogUpdate
|
||||
*/
|
||||
private static final ConfigEntry<Integer> fullDataChangeSummaryRequestRateLimit = new ConfigEntry.Builder<Integer>()
|
||||
.setServersideShortName("fullDataChangeSummaryRequestRateLimit")
|
||||
.setMinDefaultMax(1, 20, 100)
|
||||
|
||||
public static ConfigEntry<Boolean> enableLoginDataSync = new ConfigEntry.Builder<Boolean>()
|
||||
.setServersideShortName("enableLoginDataSync")
|
||||
.set(false)
|
||||
.comment(""
|
||||
+ "Limits the amount of LOD updates the client can check within a second. \n"
|
||||
+ "Enables updating of saved LODs after login."
|
||||
+ "")
|
||||
.build();
|
||||
.build();
|
||||
|
||||
public static ConfigEntry<Integer> loginDataSyncRCLimit = new ConfigEntry.Builder<Integer>()
|
||||
.setServersideShortName("loginDataSyncRCLimit")
|
||||
.setMinDefaultMax(1, 50, 100)
|
||||
.comment(""
|
||||
+ "Limits the amount of sent/processed LOD *update* requests concurrently, per player. \n"
|
||||
+ "")
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ public class WorldRemoteGenerationQueue extends AbstractFullDataRequestQueue imp
|
||||
|
||||
// Used to prevent requests for section very far away, as result of request list not completely filled.
|
||||
// Kinda a hack, since queue is not notified when file handler is done with feeding sections to generate
|
||||
private static final ConfigEntry<Integer> REQUEST_BEGIN_DELAY = Config.Client.Advanced.Multiplayer.ServerNetworking.fullDataRequestBeginDelay;
|
||||
private static final ConfigEntry<Integer> REQUEST_BEGIN_DELAY = Config.Client.Advanced.Multiplayer.ServerNetworking.generationRequestBeginDelay;
|
||||
private final Stopwatch requestBeginStopwatch = Stopwatch.createStarted();
|
||||
|
||||
private CompletableFuture<?> genTaskPriorityRequest = CompletableFuture.completedFuture(null);
|
||||
|
||||
@@ -127,15 +127,15 @@ public class DhServerLevel extends DhLevel implements IDhServerLevel
|
||||
}
|
||||
else
|
||||
{
|
||||
// Post-relog update
|
||||
// Sync only
|
||||
|
||||
if (!serverPlayerState.config.isPostRelogUpdateEnabled())
|
||||
if (!serverPlayerState.config.isLoginDataSyncEnabled())
|
||||
{
|
||||
msg.sendResponse(new RequestRejectedException("Operation is disabled from config."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!serverPlayerState.postRelogUpdateRequestConcurrencyLimiter.tryAcquire(msg))
|
||||
if (!serverPlayerState.loginDataSyncRCLimiter.tryAcquire(msg))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -143,14 +143,14 @@ public class DhServerLevel extends DhLevel implements IDhServerLevel
|
||||
Integer serverChecksum = this.serverside.dataFileHandler.repo.getChecksumForSection(msg.sectionPos);
|
||||
if (serverChecksum == null || serverChecksum.equals(msg.checksum))
|
||||
{
|
||||
serverPlayerState.postRelogUpdateRequestConcurrencyLimiter.release();
|
||||
serverPlayerState.loginDataSyncRCLimiter.release();
|
||||
msg.sendResponse(new FullDataSourceResponseMessage(null, this));
|
||||
return;
|
||||
}
|
||||
|
||||
this.serverside.dataFileHandler.getAsync(msg.sectionPos).thenAccept(fullDataSource ->
|
||||
{
|
||||
serverPlayerState.postRelogUpdateRequestConcurrencyLimiter.release();
|
||||
serverPlayerState.loginDataSyncRCLimiter.release();
|
||||
msg.sendResponse(new FullDataSourceResponseMessage((CompleteFullDataSource) fullDataSource, this));
|
||||
});
|
||||
}
|
||||
|
||||
+10
-2
@@ -16,6 +16,7 @@ import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.util.ratelimiting.SupplierBasedRateLimiter;
|
||||
import io.netty.channel.ChannelException;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@@ -51,6 +52,8 @@ public abstract class AbstractFullDataRequestQueue implements IDebugRenderable,
|
||||
|
||||
private final Set<DhSectionPos> alreadyRequestedPositions = ConcurrentHashMap.newKeySet();
|
||||
|
||||
private final SupplierBasedRateLimiter<Void> rateLimiter = new SupplierBasedRateLimiter<>(this::getRequestConcurrencyLimit);
|
||||
|
||||
|
||||
protected abstract int getRequestConcurrencyLimit();
|
||||
|
||||
@@ -104,6 +107,12 @@ public abstract class AbstractFullDataRequestQueue implements IDebugRenderable,
|
||||
&& this.getInProgressTaskCount() < this.getRequestConcurrencyLimit()
|
||||
&& this.pendingTasksSemaphore.tryAcquire())
|
||||
{
|
||||
if (!this.rateLimiter.tryAcquire())
|
||||
{
|
||||
this.pendingTasksSemaphore.release();
|
||||
break;
|
||||
}
|
||||
|
||||
this.sendNewRequest(targetPos);
|
||||
}
|
||||
|
||||
@@ -277,8 +286,7 @@ public abstract class AbstractFullDataRequestQueue implements IDebugRenderable,
|
||||
|
||||
public RequestQueueEntry(
|
||||
Consumer<ChunkSizedFullDataAccessor> chunkDataConsumer,
|
||||
@Nullable
|
||||
Integer currentChecksum)
|
||||
@Nullable Integer currentChecksum)
|
||||
{
|
||||
this.chunkDataConsumer = chunkDataConsumer;
|
||||
this.currentChecksum = currentChecksum;
|
||||
|
||||
+2
-2
@@ -12,7 +12,7 @@ public class FullDataRefreshQueue extends AbstractFullDataRequestQueue
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getRequestConcurrencyLimit() { return this.networkState.config.postRelogUpdateConcurrencyLimit; }
|
||||
protected int getRequestConcurrencyLimit() { return this.networkState.config.loginDataSyncRCLimit; }
|
||||
|
||||
@Override
|
||||
protected String getQueueName() { return "Data Refresh Queue"; }
|
||||
@@ -20,7 +20,7 @@ public class FullDataRefreshQueue extends AbstractFullDataRequestQueue
|
||||
@Override
|
||||
public boolean tick(DhBlockPos2D targetPos)
|
||||
{
|
||||
if (!this.networkState.config.postRelogUpdateEnabled)
|
||||
if (!this.networkState.config.loginDataSyncEnabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
+4
-4
@@ -10,8 +10,8 @@ public abstract class AbstractMultiplayerConfig implements INetworkObject
|
||||
public abstract int getFullDataRequestConcurrencyLimit();
|
||||
public abstract int getGenTaskPriorityRequestRateLimit();
|
||||
public abstract boolean isRealTimeUpdatesEnabled();
|
||||
public abstract boolean isPostRelogUpdateEnabled();
|
||||
public abstract int getPostRelogUpdateConcurrencyLimit();
|
||||
public abstract boolean isLoginDataSyncEnabled();
|
||||
public abstract int getLoginDataSyncRCLimit();
|
||||
|
||||
@Override
|
||||
public void encode(ByteBuf out)
|
||||
@@ -21,8 +21,8 @@ public abstract class AbstractMultiplayerConfig implements INetworkObject
|
||||
out.writeInt(this.getFullDataRequestConcurrencyLimit());
|
||||
out.writeInt(this.getGenTaskPriorityRequestRateLimit());
|
||||
out.writeBoolean(this.isRealTimeUpdatesEnabled());
|
||||
out.writeBoolean(this.isPostRelogUpdateEnabled());
|
||||
out.writeInt(this.getPostRelogUpdateConcurrencyLimit());
|
||||
out.writeBoolean(this.isLoginDataSyncEnabled());
|
||||
out.writeInt(this.getLoginDataSyncRCLimit());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+10
-10
@@ -13,7 +13,7 @@ public class MultiplayerConfig extends AbstractMultiplayerConfig
|
||||
public boolean distantGenerationEnabled = Config.Client.Advanced.WorldGenerator.enableDistantGeneration.get();
|
||||
@Override public boolean isDistantGenerationEnabled() { return this.distantGenerationEnabled; }
|
||||
|
||||
public int fullDataRequestConcurrencyLimit = Config.Client.Advanced.Multiplayer.ServerNetworking.fullDataRequestConcurrencyLimit.get();
|
||||
public int fullDataRequestConcurrencyLimit = Config.Client.Advanced.Multiplayer.ServerNetworking.generationRequestRCLimit.get();
|
||||
@Override public int getFullDataRequestConcurrencyLimit() { return this.fullDataRequestConcurrencyLimit; }
|
||||
|
||||
public int genTaskPriorityRequestRateLimit = Config.Client.Advanced.Multiplayer.ServerNetworking.genTaskPriorityRequestRateLimit.get();
|
||||
@@ -22,11 +22,11 @@ public class MultiplayerConfig extends AbstractMultiplayerConfig
|
||||
public boolean realTimeUpdatesEnabled = Config.Client.Advanced.Multiplayer.ServerNetworking.enableRealTimeUpdates.get();
|
||||
@Override public boolean isRealTimeUpdatesEnabled() { return this.realTimeUpdatesEnabled; }
|
||||
|
||||
public boolean postRelogUpdateEnabled = Config.Client.Advanced.Multiplayer.ServerNetworking.enablePostRelogUpdate.get();
|
||||
@Override public boolean isPostRelogUpdateEnabled() { return this.postRelogUpdateEnabled; }
|
||||
public boolean loginDataSyncEnabled = Config.Client.Advanced.Multiplayer.ServerNetworking.enableLoginDataSync.get();
|
||||
@Override public boolean isLoginDataSyncEnabled() { return this.loginDataSyncEnabled; }
|
||||
|
||||
public int postRelogUpdateConcurrencyLimit = Config.Client.Advanced.Multiplayer.ServerNetworking.postRelogUpdateConcurrencyLimit.get();
|
||||
@Override public int getPostRelogUpdateConcurrencyLimit() { return this.postRelogUpdateConcurrencyLimit; }
|
||||
public int loginDataSyncRCLimit = Config.Client.Advanced.Multiplayer.ServerNetworking.loginDataSyncRCLimit.get();
|
||||
@Override public int getLoginDataSyncRCLimit() { return this.loginDataSyncRCLimit; }
|
||||
|
||||
@Override
|
||||
public void decode(ByteBuf in)
|
||||
@@ -36,20 +36,20 @@ public class MultiplayerConfig extends AbstractMultiplayerConfig
|
||||
this.fullDataRequestConcurrencyLimit = in.readInt();
|
||||
this.genTaskPriorityRequestRateLimit = in.readInt();
|
||||
this.realTimeUpdatesEnabled = in.readBoolean();
|
||||
this.postRelogUpdateEnabled = in.readBoolean();
|
||||
this.postRelogUpdateConcurrencyLimit = in.readInt();
|
||||
this.loginDataSyncEnabled = in.readBoolean();
|
||||
this.loginDataSyncRCLimit = in.readInt();
|
||||
}
|
||||
|
||||
@Override public String toString()
|
||||
{
|
||||
return "MultiplayerConfig{" +
|
||||
"renderDistance=" + this.renderDistanceRadius +
|
||||
"renderDistanceRadius=" + this.renderDistanceRadius +
|
||||
", distantGenerationEnabled=" + this.distantGenerationEnabled +
|
||||
", fullDataRequestConcurrencyLimit=" + this.fullDataRequestConcurrencyLimit +
|
||||
", genTaskPriorityRequestRateLimit=" + this.genTaskPriorityRequestRateLimit +
|
||||
", realTimeUpdatesEnabled=" + this.realTimeUpdatesEnabled +
|
||||
", postRelogUpdatesEnabled=" + this.postRelogUpdateEnabled +
|
||||
", postRelogUpdateConcurrencyLimit=" + this.postRelogUpdateConcurrencyLimit +
|
||||
", loginDataSyncEnabled=" + this.loginDataSyncEnabled +
|
||||
", loginDataSyncRCLimit=" + this.loginDataSyncRCLimit +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -13,11 +13,11 @@ public class MultiplayerConfigChangeListener implements Closeable
|
||||
private static final ConfigEntry[] CONFIG_ENTRIES = new ConfigEntry[] {
|
||||
Config.Client.Advanced.Graphics.Quality.lodChunkRenderDistanceRadius,
|
||||
Config.Client.Advanced.WorldGenerator.enableDistantGeneration,
|
||||
Config.Client.Advanced.Multiplayer.ServerNetworking.fullDataRequestConcurrencyLimit,
|
||||
Config.Client.Advanced.Multiplayer.ServerNetworking.generationRequestRCLimit,
|
||||
Config.Client.Advanced.Multiplayer.ServerNetworking.genTaskPriorityRequestRateLimit,
|
||||
Config.Client.Advanced.Multiplayer.ServerNetworking.enableRealTimeUpdates,
|
||||
Config.Client.Advanced.Multiplayer.ServerNetworking.enablePostRelogUpdate,
|
||||
Config.Client.Advanced.Multiplayer.ServerNetworking.postRelogUpdateConcurrencyLimit,
|
||||
Config.Client.Advanced.Multiplayer.ServerNetworking.enableLoginDataSync,
|
||||
Config.Client.Advanced.Multiplayer.ServerNetworking.loginDataSyncRCLimit,
|
||||
};
|
||||
|
||||
private final ArrayList<ConfigChangeListener> changeListeners = new ArrayList<>();
|
||||
|
||||
+8
-8
@@ -4,7 +4,7 @@ import com.seibel.distanthorizons.core.network.IConnection;
|
||||
import com.seibel.distanthorizons.core.network.exceptions.RateLimitedException;
|
||||
import com.seibel.distanthorizons.core.network.messages.fullData.generation.FullDataSourceRequestMessage;
|
||||
import com.seibel.distanthorizons.core.network.messages.fullData.generation.priority.GenTaskPriorityRequestMessage;
|
||||
import com.seibel.distanthorizons.core.util.ratelimiting.SupplierBasedConcurrencyLimiter;
|
||||
import com.seibel.distanthorizons.core.util.ratelimiting.SupplierBasedRateAndConcurrencyLimiter;
|
||||
import com.seibel.distanthorizons.core.util.ratelimiting.SupplierBasedRateLimiter;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -24,10 +24,10 @@ public class ServerPlayerState
|
||||
ignored -> this.connection.disconnect("You have been repeatedly exceeding rate/concurrency limits.")
|
||||
);
|
||||
|
||||
public final SupplierBasedConcurrencyLimiter<FullDataSourceRequestMessage> fullDataRequestConcurrencyLimiter = new SupplierBasedConcurrencyLimiter<>(
|
||||
() -> ServerNetworking.fullDataRequestConcurrencyLimit.get(),
|
||||
public final SupplierBasedRateAndConcurrencyLimiter<FullDataSourceRequestMessage> fullDataRequestConcurrencyLimiter = new SupplierBasedRateAndConcurrencyLimiter<>(
|
||||
() -> ServerNetworking.generationRequestRCLimit.get(),
|
||||
msg -> {
|
||||
msg.sendResponse(new RateLimitedException("Max concurrent full data requests: " + this.config.getFullDataRequestConcurrencyLimit()));
|
||||
msg.sendResponse(new RateLimitedException("Full data request rate/concurrency limit: " + this.config.getFullDataRequestConcurrencyLimit()));
|
||||
this.rateLimitKickTrigger.tryAcquire(null);
|
||||
}
|
||||
);
|
||||
@@ -35,15 +35,15 @@ public class ServerPlayerState
|
||||
public final SupplierBasedRateLimiter<GenTaskPriorityRequestMessage> genTaskPriorityRequestRateLimiter = new SupplierBasedRateLimiter<>(
|
||||
() -> ServerNetworking.genTaskPriorityRequestRateLimit.get(),
|
||||
msg -> {
|
||||
msg.sendResponse(new RateLimitedException("Max section checks per second: " + this.config.getFullDataRequestConcurrencyLimit()));
|
||||
msg.sendResponse(new RateLimitedException("Generation task priority check rate limit: " + this.config.getFullDataRequestConcurrencyLimit()));
|
||||
this.rateLimitKickTrigger.tryAcquire(null);
|
||||
}
|
||||
);
|
||||
|
||||
public final SupplierBasedConcurrencyLimiter<FullDataSourceRequestMessage> postRelogUpdateRequestConcurrencyLimiter = new SupplierBasedConcurrencyLimiter<>(
|
||||
() -> ServerNetworking.postRelogUpdateConcurrencyLimit.get(),
|
||||
public final SupplierBasedRateAndConcurrencyLimiter<FullDataSourceRequestMessage> loginDataSyncRCLimiter = new SupplierBasedRateAndConcurrencyLimiter<>(
|
||||
() -> ServerNetworking.loginDataSyncRCLimit.get(),
|
||||
msg -> {
|
||||
msg.sendResponse(new RateLimitedException("Max concurrent post-relog update requests: " + this.config.getPostRelogUpdateConcurrencyLimit()));
|
||||
msg.sendResponse(new RateLimitedException("Data sync rate/concurrency limit: " + this.config.getLoginDataSyncRCLimit()));
|
||||
this.rateLimitKickTrigger.tryAcquire(null);
|
||||
}
|
||||
);
|
||||
|
||||
+6
-5
@@ -27,7 +27,7 @@ public class ServersideMultiplayerConfig extends AbstractMultiplayerConfig
|
||||
@Override
|
||||
public int getFullDataRequestConcurrencyLimit()
|
||||
{
|
||||
return Math.min(this.clientConfig.fullDataRequestConcurrencyLimit, Config.Client.Advanced.Multiplayer.ServerNetworking.fullDataRequestConcurrencyLimit.get());
|
||||
return Math.min(this.clientConfig.fullDataRequestConcurrencyLimit, Config.Client.Advanced.Multiplayer.ServerNetworking.generationRequestRCLimit.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -43,14 +43,15 @@ public class ServersideMultiplayerConfig extends AbstractMultiplayerConfig
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPostRelogUpdateEnabled() {
|
||||
return this.clientConfig.postRelogUpdateEnabled && Config.Client.Advanced.Multiplayer.ServerNetworking.enablePostRelogUpdate.get();
|
||||
public boolean isLoginDataSyncEnabled()
|
||||
{
|
||||
return this.clientConfig.loginDataSyncEnabled && Config.Client.Advanced.Multiplayer.ServerNetworking.enableLoginDataSync.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPostRelogUpdateConcurrencyLimit()
|
||||
public int getLoginDataSyncRCLimit()
|
||||
{
|
||||
return Math.min(this.clientConfig.postRelogUpdateConcurrencyLimit, Config.Client.Advanced.Multiplayer.ServerNetworking.postRelogUpdateConcurrencyLimit.get());
|
||||
return Math.min(this.clientConfig.loginDataSyncRCLimit, Config.Client.Advanced.Multiplayer.ServerNetworking.loginDataSyncRCLimit.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package com.seibel.distanthorizons.core.util.ratelimiting;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class SupplierBasedRateAndConcurrencyLimiter<T>
|
||||
{
|
||||
private final SupplierBasedRateLimiter<T> rateLimiter;
|
||||
private final SupplierBasedConcurrencyLimiter<T> concurrencyLimiter;
|
||||
|
||||
public SupplierBasedRateAndConcurrencyLimiter(Supplier<Integer> maxRateSupplier, Consumer<T> onFailureConsumer)
|
||||
{
|
||||
this.rateLimiter = new SupplierBasedRateLimiter<>(maxRateSupplier, onFailureConsumer);
|
||||
this.concurrencyLimiter = new SupplierBasedConcurrencyLimiter<>(maxRateSupplier, onFailureConsumer);
|
||||
}
|
||||
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public boolean tryAcquire(T context)
|
||||
{
|
||||
if (!this.concurrencyLimiter.tryAcquire(context))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.rateLimiter.tryAcquire(context))
|
||||
{
|
||||
this.concurrencyLimiter.release();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void release()
|
||||
{
|
||||
this.concurrencyLimiter.release();
|
||||
}
|
||||
|
||||
}
|
||||
+17
-6
@@ -18,6 +18,7 @@ public class SupplierBasedRateLimiter<T>
|
||||
|
||||
private final RateLimiter rateLimiter = RateLimiter.create(1);
|
||||
|
||||
public SupplierBasedRateLimiter(Supplier<Integer> maxRateSupplier) { this(maxRateSupplier, ignored -> { }); }
|
||||
public SupplierBasedRateLimiter(Supplier<Integer> maxRateSupplier, Consumer<T> onFailureConsumer)
|
||||
{
|
||||
this.maxRateSupplier = maxRateSupplier;
|
||||
@@ -27,30 +28,40 @@ public class SupplierBasedRateLimiter<T>
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public boolean tryAcquire(T context)
|
||||
{
|
||||
return tryAcquire(context, 1);
|
||||
return this.tryAcquire(context, 1);
|
||||
}
|
||||
|
||||
public boolean tryAcquire()
|
||||
{
|
||||
return this.tryAcquire(null, 1);
|
||||
}
|
||||
|
||||
public int acquireOrDrain(int permits)
|
||||
{
|
||||
rateLimiter.setRate(maxRateSupplier.get());
|
||||
this.rateLimiter.setRate(this.maxRateSupplier.get());
|
||||
|
||||
if (rateLimiter.tryAcquire(permits))
|
||||
if (this.rateLimiter.tryAcquire(permits))
|
||||
{
|
||||
return permits;
|
||||
}
|
||||
|
||||
int acquired = 0;
|
||||
while ((permits /= 2) > 0)
|
||||
{
|
||||
if (rateLimiter.tryAcquire(permits))
|
||||
if (this.rateLimiter.tryAcquire(permits))
|
||||
{
|
||||
acquired += permits;
|
||||
}
|
||||
}
|
||||
|
||||
return acquired;
|
||||
}
|
||||
|
||||
public boolean tryAcquire(T context, int permits)
|
||||
{
|
||||
rateLimiter.setRate(maxRateSupplier.get());
|
||||
this.rateLimiter.setRate(this.maxRateSupplier.get());
|
||||
|
||||
if (!rateLimiter.tryAcquire(permits))
|
||||
if (!this.rateLimiter.tryAcquire(permits))
|
||||
{
|
||||
this.onFailureConsumer.accept(context);
|
||||
return false;
|
||||
|
||||
@@ -345,15 +345,23 @@
|
||||
"Multiplayer",
|
||||
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking": "Server Networking",
|
||||
|
||||
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.enableServerNetworking": "Enable Server Networking",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.fullDataRequestConcurrencyLimit": "Sections - request concurrency limit",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.genTaskPriorityRequestRateLimit": "Generation task priority - request rate limit",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.fullDataRequestBeginDelay": "Generation request begin delay",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.enableRealTimeUpdates": "Enable Real Time Updates",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.enablePostRelogUpdates": "Enable Post Relog Updates",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.enableServerNetworking.@tooltip": "§6Attention:§r this feature is not fully implemented. \n\nIf true Distant Horizons will attempt to communicate with the connected \nserver in order to load LODs outside your vanilla render distance. \n\nNote: This requires DH to be installed on the server in order to function.",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.serverPort": "Server Port",
|
||||
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.serverPort.@tooltip": "The port on the server that's used for sending LOD data.",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.generationRequestRCLimit": "Gen task rate/concurrency limit",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.generationRequestRCLimit.@tooltip": "Limits the amount of generation requests sent by client and processed by server.",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.genTaskPriorityRequestRateLimit": "Gen task priority check rate limit",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.genTaskPriorityRequestRateLimit.@tooltip": "Limits the amount of LOD sections that the client can request states for, per second.",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.generationRequestBeginDelay": "Generation request begin delay",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.generationRequestBeginDelay.@tooltip": "Adds a delay in seconds before sending LOD requests, when generation is enabled. \nIncrease this value if initial generation starts too far away.",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.enableRealTimeUpdates": "Enable Real Time Updates",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.enableRealTimeUpdates.@tooltip": "Enables real time updates from server.",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.enableLoginDataSync": "Synchronize LODs on Login",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.enableLoginDataSync.@tooltip": "Enables updating of saved LODs after login.",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.loginDataSyncRCLimit": "Login sync rate/concurrency limit",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworking.loginDataSyncRCLimit.@tooltip": "Limits the amount of sent/processed LOD *update* requests concurrently, per player.",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverFolderNameMode":
|
||||
"Server Folder Mode",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverFolderNameMode.@tooltip":
|
||||
@@ -366,15 +374,6 @@
|
||||
"Networked Multiverse Support",
|
||||
"distanthorizons.config.client.advanced.multiplayer.enableMultiverseNetworking.@tooltip":
|
||||
"If true Distant Horizons will attempt to communicate with the connected \nserver in order to improve multiverse support.",
|
||||
"distanthorizons.config.client.advanced.multiplayer.enableServerNetworking":
|
||||
"§4Partially implemented§r - Server Support",
|
||||
"distanthorizons.config.client.advanced.multiplayer.enableServerNetworking.@tooltip":
|
||||
"§6Attention:§r this feature is not fully implemented. \n\nIf true Distant Horizons will attempt to communicate with the connected \nserver in order to load LODs outside your vanilla render distance. \n\nNote: This requires DH to be installed on the server in order to function.",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworkingRateLimit":
|
||||
"Server Support - Request Rate Limit",
|
||||
"distanthorizons.config.client.advanced.multiplayer.serverNetworkingRateLimit.@tooltip":
|
||||
"Limits the amount of sent/processed LOD requests concurrently. \n\nNote: Server can set its own rate limit.",
|
||||
|
||||
|
||||
|
||||
"distanthorizons.config.client.advanced.multiThreading":
|
||||
|
||||
Reference in New Issue
Block a user