diff --git a/settings.sample.yaml b/settings.sample.yaml index f072b2d..51b9bcc 100644 --- a/settings.sample.yaml +++ b/settings.sample.yaml @@ -23,7 +23,7 @@ # The size in mebibytes of the cache # You can use megabytes instead in a pinch, # but just know the two are **NOT** the same. -max_cache_size_in_mebibytes: 1024 +max_cache_size_in_mebibytes: 0 # Optional settings for fancy geoip analytics metrics_settings: diff --git a/src/main/kotlin/mdnet/Main.kt b/src/main/kotlin/mdnet/Main.kt index 8dc9d89..aad7511 100644 --- a/src/main/kotlin/mdnet/Main.kt +++ b/src/main/kotlin/mdnet/Main.kt @@ -32,7 +32,11 @@ object Main { @JvmStatic fun main(args: Array) { - CommandLine(ClientArgs()).execute(*args) + try { + CommandLine(ClientArgs()).execute(*args) + } catch (e: Throwable) { + LOGGER.error(e) { "Critical Error " } + } } fun dieWithError(e: Throwable): Nothing { diff --git a/src/main/kotlin/mdnet/MangaDexClient.kt b/src/main/kotlin/mdnet/MangaDexClient.kt index aebc86e..17cff98 100644 --- a/src/main/kotlin/mdnet/MangaDexClient.kt +++ b/src/main/kotlin/mdnet/MangaDexClient.kt @@ -175,8 +175,14 @@ class MangaDexClient(private val settingsFile: File, databaseFile: File, cacheFo storage.maxSize = (newSettings.maxCacheSizeInMebibytes * 1024 * 1024 * 0.95).toLong() - stopImageServer() - startImageServer() + if (imageServer != null) { + stopImageServer() + } + try { + startImageServer() + } catch (e: Exception) { + LOGGER.warn(e) { "Error starting the image server" } + } } catch (e: UnrecognizedPropertyException) { LOGGER.warn { "Settings file is invalid: '$e.propertyName' is not a valid setting" } } catch (e: JsonProcessingException) { @@ -189,8 +195,8 @@ class MangaDexClient(private val settingsFile: File, databaseFile: File, cacheFo } private fun validateSettings(settings: ClientSettings) { - if (settings.maxCacheSizeInMebibytes < 1024) { - throw ClientSettingsException("Config Error: Invalid max cache size, must be >= 1024 MiB (1GiB)") + if (settings.maxCacheSizeInMebibytes < 20480) { + throw ClientSettingsException("Config Error: Invalid max cache size, must be >= 20480 MiB (20 GiB)") } fun isSecretValid(clientSecret: String): Boolean { diff --git a/src/main/kotlin/mdnet/ServerManager.kt b/src/main/kotlin/mdnet/ServerManager.kt index 40ac3ce..c3e4fe8 100644 --- a/src/main/kotlin/mdnet/ServerManager.kt +++ b/src/main/kotlin/mdnet/ServerManager.kt @@ -58,7 +58,7 @@ object Shutdown : State() data class GracefulStop( val lastRunning: Running, val counts: Int = 0, - val nextState: State = Uninitialized, + val nextState: State, val action: () -> Unit = {} ) : State() @@ -193,7 +193,7 @@ class ServerManager( if (settings.serverSettings.maxMebibytesPerHour != 0L && settings.serverSettings.maxMebibytesPerHour * 1024 * 1024 /* MiB to bytes */ < currentBytesSent) { LOGGER.info { "Stopping image server as hourly bandwidth limit reached" } - this.state = GracefulStop(lastRunning = state) + this.state = GracefulStop(lastRunning = state, nextState = Uninitialized) } else { pingControl() } @@ -245,7 +245,7 @@ class ServerManager( if (!state.settings.logicalEqual(newSettings)) { LOGGER.info { "Doing internal restart of HTTP server to refresh settings" } - this.state = GracefulStop(lastRunning = state) { + this.state = GracefulStop(lastRunning = state, nextState = Uninitialized) { loginAndStartServer() } } diff --git a/src/main/kotlin/mdnet/netty/ApplicationNetty.kt b/src/main/kotlin/mdnet/netty/ApplicationNetty.kt index 1e7f0be..f368f23 100644 --- a/src/main/kotlin/mdnet/netty/ApplicationNetty.kt +++ b/src/main/kotlin/mdnet/netty/ApplicationNetty.kt @@ -77,9 +77,9 @@ sealed class NettyTransport(threads: Int) { ) fun shutdownGracefully() { - bossGroup.shutdownGracefully() - workerGroup.shutdownGracefully() - executor.shutdownGracefully() + bossGroup.shutdownGracefully().sync() + workerGroup.shutdownGracefully().sync() + executor.shutdownGracefully().sync() } private class NioTransport(threads: Int) : NettyTransport(threads) { @@ -111,21 +111,25 @@ sealed class NettyTransport(threads: Int) { LOGGER.info { "Choosing a transport using $threadsToUse threads" } if (name.startsWith("linux")) { - if (IOUring.isAvailable()) { - LOGGER.info { "Using IOUring transport" } - return IOUringTransport(threadsToUse) - } else { - LOGGER.info(IOUring.unavailabilityCause()) { - "IOUring transport not available" + if (!SystemPropertyUtil.get("no-iouring").toBoolean()) { + if (IOUring.isAvailable()) { + LOGGER.info { "Using IOUring transport" } + return IOUringTransport(threadsToUse) + } else { + LOGGER.info(IOUring.unavailabilityCause()) { + "IOUring transport not available" + } } } - if (Epoll.isAvailable()) { - LOGGER.info { "Using Epoll transport" } - return EpollTransport(threadsToUse) - } else { - LOGGER.info(Epoll.unavailabilityCause()) { - "Epoll transport not available" + if (!SystemPropertyUtil.get("no-epoll").toBoolean()) { + if (Epoll.isAvailable()) { + LOGGER.info { "Using Epoll transport" } + return EpollTransport(threadsToUse) + } else { + LOGGER.info(Epoll.unavailabilityCause()) { + "Epoll transport not available" + } } } } @@ -144,9 +148,7 @@ class Netty( override fun toServer(httpHandler: HttpHandler): Http4kServer = object : Http4kServer { private val transport = NettyTransport.bestForPlatform(serverSettings.threads) - private lateinit var closeFuture: ChannelFuture - private lateinit var address: InetSocketAddress - + private lateinit var channel: Channel private val burstLimiter = object : GlobalTrafficShapingHandler( transport.workerGroup, serverSettings.maxKilobitsPerSecond * 1000L / 8L, 0, 100 ) { @@ -209,14 +211,12 @@ class Netty( .option(ChannelOption.SO_BACKLOG, 1000) .childOption(ChannelOption.SO_KEEPALIVE, true) - val channel = bootstrap.bind(InetSocketAddress(serverSettings.hostname, serverSettings.port)).sync().channel() - address = channel.localAddress() as InetSocketAddress - closeFuture = channel.closeFuture() + channel = bootstrap.bind(InetSocketAddress(serverSettings.hostname, serverSettings.port)).sync().channel() } override fun stop() = apply { - closeFuture.cancel(false) transport.shutdownGracefully() + channel.closeFuture().sync() } override fun port(): Int = serverSettings.port