Kotlinify some more things
This commit is contained in:
parent
57ba8eb019
commit
9afa914566
|
@ -4,6 +4,7 @@ plugins {
|
||||||
id "application"
|
id "application"
|
||||||
id "com.github.johnrengelman.shadow" version "5.2.0"
|
id "com.github.johnrengelman.shadow" version "5.2.0"
|
||||||
id "com.diffplug.gradle.spotless" version "3.18.0"
|
id "com.diffplug.gradle.spotless" version "3.18.0"
|
||||||
|
id 'dev.afanasev.sekret' version '0.0.3'
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "com.mangadex"
|
group = "com.mangadex"
|
||||||
|
@ -26,8 +27,10 @@ dependencies {
|
||||||
|
|
||||||
implementation group: "commons-io", name: "commons-io", version: "2.7"
|
implementation group: "commons-io", name: "commons-io", version: "2.7"
|
||||||
|
|
||||||
implementation "ch.qos.logback:logback-classic:$logback_version"
|
implementation group:"ch.qos.logback", name: "logback-classic", version: "$logback_version"
|
||||||
runtimeOnly 'io.netty:netty-tcnative-boringssl-static:2.0.30.Final'
|
runtimeOnly group:"io.netty", name: "netty-tcnative-boringssl-static", version: "2.0.30.Final"
|
||||||
|
|
||||||
|
compileOnly group:"dev.afanasev", name: "sekret-annotation", version: "0.0.3"
|
||||||
}
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
package mdnet.base;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
|
|
||||||
public class Constants {
|
|
||||||
public static final int CLIENT_BUILD = 5;
|
|
||||||
public static final String CLIENT_VERSION = "1.0";
|
|
||||||
public static final Duration MAX_AGE_CACHE = Duration.ofDays(14);
|
|
||||||
}
|
|
|
@ -3,8 +3,8 @@ package mdnet.base;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import mdnet.base.settings.ClientSettings;
|
import mdnet.base.settings.ClientSettings;
|
||||||
import mdnet.base.web.ApplicationKt;
|
import mdnet.base.server.ApplicationKt;
|
||||||
import mdnet.base.web.WebUiKt;
|
import mdnet.base.server.WebUiKt;
|
||||||
import mdnet.cache.DiskLruCache;
|
import mdnet.cache.DiskLruCache;
|
||||||
import org.http4k.server.Http4kServer;
|
import org.http4k.server.Http4kServer;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -32,10 +32,10 @@ public class MangaDexClient {
|
||||||
private final ClientSettings clientSettings;
|
private final ClientSettings clientSettings;
|
||||||
|
|
||||||
private final Map<Instant, Statistics> statsMap = Collections
|
private final Map<Instant, Statistics> statsMap = Collections
|
||||||
.synchronizedMap(new LinkedHashMap<Instant, Statistics>(80) {
|
.synchronizedMap(new LinkedHashMap<Instant, Statistics>(240) {
|
||||||
@Override
|
@Override
|
||||||
protected boolean removeEldestEntry(Map.Entry eldest) {
|
protected boolean removeEldestEntry(Map.Entry eldest) {
|
||||||
return this.size() > 80;
|
return this.size() > 240;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
private final AtomicReference<Statistics> statistics;
|
private final AtomicReference<Statistics> statistics;
|
||||||
|
@ -66,7 +66,6 @@ public class MangaDexClient {
|
||||||
} else {
|
} else {
|
||||||
statistics.set(new Statistics());
|
statistics.set(new Statistics());
|
||||||
}
|
}
|
||||||
lastBytesSent = statistics.get().getBytesSent();
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
MangaDexClient.dieWithError(e);
|
MangaDexClient.dieWithError(e);
|
||||||
}
|
}
|
||||||
|
@ -81,6 +80,7 @@ public class MangaDexClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lastBytesSent = statistics.get().getBytesSent();
|
||||||
statsMap.put(Instant.now(), statistics.get());
|
statsMap.put(Instant.now(), statistics.get());
|
||||||
|
|
||||||
if (clientSettings.getWebSettings() != null) {
|
if (clientSettings.getWebSettings() != null) {
|
||||||
|
@ -89,9 +89,29 @@ public class MangaDexClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LOGGER.isInfoEnabled()) {
|
if (LOGGER.isInfoEnabled()) {
|
||||||
LOGGER.info("MDNet initialization completed successfully. Starting normal operation.");
|
LOGGER.info("Mangadex@Home Client initialization completed successfully. Starting normal operation.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
executorService.scheduleWithFixedDelay(() -> {
|
||||||
|
statistics.updateAndGet(n -> n.copy(n.getRequestsServed(), n.getCacheHits(), n.getCacheMisses(),
|
||||||
|
n.getBrowserCached(), n.getBytesSent(), cache.size()));
|
||||||
|
|
||||||
|
statsMap.put(Instant.now(), statistics.get());
|
||||||
|
|
||||||
|
try {
|
||||||
|
DiskLruCache.Editor editor = cache.edit("statistics");
|
||||||
|
if (editor != null) {
|
||||||
|
String json = GSON.toJson(statistics.get(), Statistics.class);
|
||||||
|
editor.setString(0, json);
|
||||||
|
editor.setString(1, "");
|
||||||
|
editor.setString(2, "");
|
||||||
|
editor.commit();
|
||||||
|
}
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}, 15, 15, TimeUnit.SECONDS);
|
||||||
|
|
||||||
executorService.scheduleAtFixedRate(() -> {
|
executorService.scheduleAtFixedRate(() -> {
|
||||||
if (counter == 80) {
|
if (counter == 80) {
|
||||||
counter = 0;
|
counter = 0;
|
||||||
|
@ -108,20 +128,6 @@ public class MangaDexClient {
|
||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
statsMap.put(Instant.now(), statistics.get());
|
|
||||||
|
|
||||||
try {
|
|
||||||
DiskLruCache.Editor editor = cache.edit("statistics");
|
|
||||||
if (editor != null) {
|
|
||||||
String json = GSON.toJson(statistics.get(), Statistics.class);
|
|
||||||
editor.setString(0, json);
|
|
||||||
editor.setString(1, "");
|
|
||||||
editor.setString(2, "");
|
|
||||||
editor.commit();
|
|
||||||
}
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the server is offline then don't try and refresh certs
|
// if the server is offline then don't try and refresh certs
|
||||||
if (engine == null) {
|
if (engine == null) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,77 +0,0 @@
|
||||||
package mdnet.base.settings;
|
|
||||||
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public final class ClientSettings {
|
|
||||||
@SerializedName("max_cache_size_mib")
|
|
||||||
private final long maxCacheSizeMib;
|
|
||||||
@SerializedName("max_bandwidth_mib_per_hour")
|
|
||||||
private final long maxBandwidthMibPerHour;
|
|
||||||
@SerializedName("max_burst_rate_kib_per_second")
|
|
||||||
private final long maxBurstRateKibPerSecond;
|
|
||||||
@SerializedName("client_port")
|
|
||||||
private final int clientPort;
|
|
||||||
@SerializedName("client_secret")
|
|
||||||
private final String clientSecret;
|
|
||||||
@SerializedName("threads")
|
|
||||||
private final int threads;
|
|
||||||
@SerializedName("web_settings")
|
|
||||||
private final WebSettings webSettings;
|
|
||||||
|
|
||||||
public ClientSettings() {
|
|
||||||
this.maxCacheSizeMib = 20480;
|
|
||||||
this.maxBandwidthMibPerHour = 0;
|
|
||||||
this.maxBurstRateKibPerSecond = 0;
|
|
||||||
this.clientPort = 443;
|
|
||||||
this.clientSecret = "PASTE-YOUR-SECRET-HERE";
|
|
||||||
this.threads = 32;
|
|
||||||
this.webSettings = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClientSettings(long maxCacheSizeMib, long maxBandwidthMibPerHour, long maxBurstRateKibPerSecond,
|
|
||||||
int clientPort, String clientSecret, int threads, WebSettings webSettings) {
|
|
||||||
this.maxCacheSizeMib = maxCacheSizeMib;
|
|
||||||
this.maxBandwidthMibPerHour = maxBandwidthMibPerHour;
|
|
||||||
this.maxBurstRateKibPerSecond = maxBurstRateKibPerSecond;
|
|
||||||
this.clientPort = clientPort;
|
|
||||||
this.clientSecret = Objects.requireNonNull(clientSecret);
|
|
||||||
this.threads = threads;
|
|
||||||
this.webSettings = webSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getMaxCacheSizeMib() {
|
|
||||||
return maxCacheSizeMib;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getMaxBandwidthMibPerHour() {
|
|
||||||
return maxBandwidthMibPerHour;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getMaxBurstRateKibPerSecond() {
|
|
||||||
return maxBurstRateKibPerSecond;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getClientPort() {
|
|
||||||
return clientPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getClientSecret() {
|
|
||||||
return clientSecret;
|
|
||||||
}
|
|
||||||
public WebSettings getWebSettings() {
|
|
||||||
return webSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getThreads() {
|
|
||||||
return threads;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "ClientSettings{" + "maxCacheSizeMib=" + maxCacheSizeMib + ", maxBandwidthMibPerHour="
|
|
||||||
+ maxBandwidthMibPerHour + ", maxBurstRateKibPerSecond=" + maxBurstRateKibPerSecond + ", clientPort="
|
|
||||||
+ clientPort + ", clientSecret='" + "<hidden>" + '\'' + ", threads=" + getThreads() + '}';
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
package mdnet.base.settings;
|
|
||||||
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
|
||||||
|
|
||||||
public final class WebSettings {
|
|
||||||
@SerializedName("ui_port")
|
|
||||||
private final int uiPort;
|
|
||||||
|
|
||||||
public WebSettings() {
|
|
||||||
this.uiPort = 8080;
|
|
||||||
}
|
|
||||||
|
|
||||||
public WebSettings(int uiPort) {
|
|
||||||
this.uiPort = uiPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getUiPort() {
|
|
||||||
return uiPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "WebSettings{" + "uiPort=" + uiPort + '}';
|
|
||||||
}
|
|
||||||
}
|
|
9
src/main/kotlin/mdnet/base/Constants.kt
Normal file
9
src/main/kotlin/mdnet/base/Constants.kt
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
package mdnet.base
|
||||||
|
|
||||||
|
import java.time.Duration
|
||||||
|
|
||||||
|
object Constants {
|
||||||
|
const val CLIENT_BUILD = 5
|
||||||
|
const val CLIENT_VERSION = "1.0"
|
||||||
|
val MAX_AGE_CACHE: Duration = Duration.ofDays(14)
|
||||||
|
}
|
|
@ -45,7 +45,7 @@ class Netty(private val tls: ServerSettings.TlsCert, private val clientSettings:
|
||||||
private lateinit var address: InetSocketAddress
|
private lateinit var address: InetSocketAddress
|
||||||
|
|
||||||
private val burstLimiter = object : GlobalTrafficShapingHandler(
|
private val burstLimiter = object : GlobalTrafficShapingHandler(
|
||||||
workerGroup, 1024 * clientSettings.maxBurstRateKibPerSecond, 0, 50) {
|
workerGroup, 1024L * clientSettings.maxBurstRateKibPerSecond, 0, 50) {
|
||||||
override fun doAccounting(counter: TrafficCounter) {
|
override fun doAccounting(counter: TrafficCounter) {
|
||||||
statistics.getAndUpdate {
|
statistics.getAndUpdate {
|
||||||
it.copy(bytesSent = it.bytesSent + counter.cumulativeWrittenBytes())
|
it.copy(bytesSent = it.bytesSent + counter.cumulativeWrittenBytes())
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* ktlint-disable no-wildcard-imports */
|
/* ktlint-disable no-wildcard-imports */
|
||||||
package mdnet.base.web
|
package mdnet.base.server
|
||||||
|
|
||||||
import mdnet.base.Netty
|
import mdnet.base.Netty
|
||||||
import mdnet.base.ServerSettings
|
import mdnet.base.ServerSettings
|
|
@ -1,5 +1,5 @@
|
||||||
/* ktlint-disable no-wildcard-imports */
|
/* ktlint-disable no-wildcard-imports */
|
||||||
package mdnet.base.web
|
package mdnet.base.server
|
||||||
|
|
||||||
import mdnet.base.Constants
|
import mdnet.base.Constants
|
||||||
import mdnet.base.Statistics
|
import mdnet.base.Statistics
|
|
@ -1,5 +1,5 @@
|
||||||
/* ktlint-disable no-wildcard-imports */
|
/* ktlint-disable no-wildcard-imports */
|
||||||
package mdnet.base.web
|
package mdnet.base.server
|
||||||
|
|
||||||
import mdnet.base.Statistics
|
import mdnet.base.Statistics
|
||||||
import mdnet.base.settings.WebSettings
|
import mdnet.base.settings.WebSettings
|
|
@ -1,5 +1,5 @@
|
||||||
/* ktlint-disable no-wildcard-imports */
|
/* ktlint-disable no-wildcard-imports */
|
||||||
package mdnet.base.web
|
package mdnet.base.server
|
||||||
|
|
||||||
import mdnet.base.Constants
|
import mdnet.base.Constants
|
||||||
import org.http4k.core.Filter
|
import org.http4k.core.Filter
|
16
src/main/kotlin/mdnet/base/settings/ClientSettings.kt
Normal file
16
src/main/kotlin/mdnet/base/settings/ClientSettings.kt
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
package mdnet.base.settings
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
import dev.afanasev.sekret.Secret
|
||||||
|
|
||||||
|
data class ClientSettings(
|
||||||
|
@field:SerializedName("max_cache_size_mib") val maxCacheSizeMib: Long = 20480,
|
||||||
|
@field:SerializedName("max_bandwidth_mib_per_hour") val maxBandwidthMibPerHour: Long = 0,
|
||||||
|
@field:SerializedName("max_burst_rate_kib_per_second") val maxBurstRateKibPerSecond: Long = 0,
|
||||||
|
@field:SerializedName("client_port") val clientPort: Int = 443,
|
||||||
|
@field:Secret @field:SerializedName("client_secret") val clientSecret: String = "PASTE-YOUR-SECRET-HERE",
|
||||||
|
@field:SerializedName("threads") val threads: Int = 32,
|
||||||
|
@field:SerializedName("web_settings") val webSettings: WebSettings? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
data class WebSettings(@field:SerializedName("ui_port") val uiPort: Int = 8080)
|
|
@ -1,5 +1,4 @@
|
||||||
<configuration>
|
<configuration>
|
||||||
<shutdownHook/>
|
|
||||||
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||||
<level>${file-level:-TRACE}</level>
|
<level>${file-level:-TRACE}</level>
|
||||||
|
|
Loading…
Reference in a new issue