From db13cd09cc8aca2eb1d03127f8cd7eb5645ed603 Mon Sep 17 00:00:00 2001 From: reusedname <155286845+reusedname@users.noreply.github.com> Date: Thu, 27 Feb 2025 21:54:27 +0500 Subject: [PATCH] New settings, reduce config saving spam - max concurrent http requests (total and per host) - config saving is delayed for some millis to reduce disk and log spam in case of fast repeated calls --- .../java/ctbrec/ui/settings/SettingsTab.java | 23 +++++++++++++++++-- common/src/main/java/ctbrec/Settings.java | 3 +++ .../src/main/java/ctbrec/io/HttpClient.java | 11 +++++---- .../recorder/SimplifiedLocalRecorder.java | 2 +- 4 files changed, 32 insertions(+), 7 deletions(-) diff --git a/client/src/main/java/ctbrec/ui/settings/SettingsTab.java b/client/src/main/java/ctbrec/ui/settings/SettingsTab.java index d18d9492..4afdf31c 100644 --- a/client/src/main/java/ctbrec/ui/settings/SettingsTab.java +++ b/client/src/main/java/ctbrec/ui/settings/SettingsTab.java @@ -135,6 +135,9 @@ public class SettingsTab extends Tab implements TabSelectionListener { private SimpleStringProperty filterWhitelist; private SimpleBooleanProperty deleteOrphanedRecordingMetadata; private SimpleIntegerProperty restrictBitrate; + private SimpleIntegerProperty configSavingDelayMs; + private SimpleIntegerProperty httpClientMaxRequests; + private SimpleIntegerProperty httpClientMaxRequestsPerHost; public SettingsTab(List sites, Recorder recorder) { this.sites = sites; @@ -219,6 +222,9 @@ public class SettingsTab extends Tab implements TabSelectionListener { filterWhitelist = new SimpleStringProperty(null, "filterWhitelist", settings.filterWhitelist); deleteOrphanedRecordingMetadata = new SimpleBooleanProperty(null, "deleteOrphanedRecordingMetadata", settings.deleteOrphanedRecordingMetadata); restrictBitrate = new SimpleIntegerProperty(null, "restrictBitrate", settings.restrictBitrate); + configSavingDelayMs = new SimpleIntegerProperty(null, "configSavingDelayMs", settings.configSavingDelayMs); + httpClientMaxRequests = new SimpleIntegerProperty(null, "httpClientMaxRequests", settings.httpClientMaxRequests); + httpClientMaxRequestsPerHost = new SimpleIntegerProperty(null, "httpClientMaxRequestsPerHost", settings.httpClientMaxRequestsPerHost); } private void createGui() { @@ -332,7 +338,17 @@ public class SettingsTab extends Tab implements TabSelectionListener { Setting.of("Password", proxyPassword).needsRestart())), Category.of("Advanced / Devtools", Group.of("Networking", - Setting.of("Playlist request timeout (ms)", playlistRequestTimeout, "Timeout in ms for playlist requests")), + Setting.of("Playlist request timeout (ms)", playlistRequestTimeout, "Timeout in ms for playlist requests"), + Setting.of("Max requests", httpClientMaxRequests, + "The maximum number of requests to execute concurrently. Above this requests queue in memory,\n" + // + "waiting for the running calls to complete.\n\n" + // + "If more than [maxRequests] requests are in flight when this is invoked, those requests will remain in flight."), + Setting.of("Max requests per host", httpClientMaxRequestsPerHost, + "The maximum number of requests for each host to execute concurrently. This limits requests by\n" + // + "the URL's host name. Note that concurrent requests to a single IP address may still exceed this\n" + // + "limit: multiple hostnames may share an IP address or be routed through the same HTTP proxy.\n\n" + // + "If more than [maxRequestsPerHost] requests are in flight when this is invoked, those requests will remain in flight.\n\n" + // + "WebSocket connections to hosts **do not** count against this limit.")), Group.of("Logging", Setting.of("Log FFmpeg output", logFFmpegOutput, "Log FFmpeg output to files in the system's temp directory"), Setting.of("Log missed segments", logMissedSegments, @@ -341,7 +357,10 @@ public class SettingsTab extends Tab implements TabSelectionListener { Setting.of("Use hlsdl (if possible)", useHlsdl, "Use hlsdl to record the live streams. Some features might not work correctly."), Setting.of("hlsdl executable", hlsdlExecutable, "Path to the hlsdl executable"), - Setting.of("Log hlsdl output", loghlsdlOutput, "Log hlsdl output to files in the system's temp directory")))); + Setting.of("Log hlsdl output", loghlsdlOutput, "Log hlsdl output to files in the system's temp directory")), + Group.of("Miscelaneous", + Setting.of("Config file saving delay (ms)", configSavingDelayMs, + "Wait specified number of milliseconds before actually writing config to disk")))); Region preferencesView = prefs.getView(); prefs.onRestartRequired(this::showRestartRequired); storage.setPreferences(prefs); diff --git a/common/src/main/java/ctbrec/Settings.java b/common/src/main/java/ctbrec/Settings.java index 1e8f3eaf..320512a1 100644 --- a/common/src/main/java/ctbrec/Settings.java +++ b/common/src/main/java/ctbrec/Settings.java @@ -143,6 +143,8 @@ public class Settings { @Deprecated public String postProcessing = ""; public int playlistRequestTimeout = 2000; + public int httpClientMaxRequests = 64; + public int httpClientMaxRequestsPerHost = 16; public int postProcessingThreads = 2; public List postProcessors = new ArrayList<>(); public String proxyHost; @@ -228,4 +230,5 @@ public class Settings { public String filterWhitelist = ""; public boolean checkResolutionByMinSide = false; public int restrictBitrate = 0; + public int configSavingDelayMs = 400; } diff --git a/common/src/main/java/ctbrec/io/HttpClient.java b/common/src/main/java/ctbrec/io/HttpClient.java index 5dc48ea2..390d34a6 100644 --- a/common/src/main/java/ctbrec/io/HttpClient.java +++ b/common/src/main/java/ctbrec/io/HttpClient.java @@ -20,6 +20,7 @@ import java.io.File; import java.io.IOException; import java.net.Authenticator; import java.net.PasswordAuthentication; +import java.net.SocketTimeoutException; import java.nio.file.Files; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; @@ -114,10 +115,10 @@ public abstract class HttpClient { } public Response execute(Request request, int timeoutInMillis) throws IOException { - return client.newBuilder() // - .connectTimeout(timeoutInMillis, TimeUnit.MILLISECONDS) // - .readTimeout(timeoutInMillis, TimeUnit.MILLISECONDS).build() // - .newCall(request).execute(); + return client.newBuilder() // + .connectTimeout(timeoutInMillis, TimeUnit.MILLISECONDS) // + .readTimeout(timeoutInMillis, TimeUnit.MILLISECONDS).build() // + .newCall(request).execute(); } public Response executeWithCache(Request req) throws IOException { @@ -171,6 +172,8 @@ public abstract class HttpClient { } client = builder.build(); + client.dispatcher().setMaxRequests(config.getSettings().httpClientMaxRequests); + client.dispatcher().setMaxRequestsPerHost(config.getSettings().httpClientMaxRequestsPerHost); } /** diff --git a/common/src/main/java/ctbrec/recorder/SimplifiedLocalRecorder.java b/common/src/main/java/ctbrec/recorder/SimplifiedLocalRecorder.java index 909617ba..af47ce96 100644 --- a/common/src/main/java/ctbrec/recorder/SimplifiedLocalRecorder.java +++ b/common/src/main/java/ctbrec/recorder/SimplifiedLocalRecorder.java @@ -580,7 +580,7 @@ public class SimplifiedLocalRecorder implements Recorder { } } }; - saveConfigTimer.schedule(saveConfigTask, 400); + saveConfigTimer.schedule(saveConfigTask, config.getSettings().configSavingDelayMs); } @Override