mirror of
https://github.com/Suwayomi/Suwayomi-Server.git
synced 2026-06-30 17:34:39 -05:00
Feature/make config settings changeable during runtime (#545)
* Add logic to update config during runtime * Update ConfigModule to always use the latest config * Make ServerConfig settings re-assignable
This commit is contained in:
@@ -11,6 +11,9 @@ import ch.qos.logback.classic.Level
|
|||||||
import com.typesafe.config.Config
|
import com.typesafe.config.Config
|
||||||
import com.typesafe.config.ConfigFactory
|
import com.typesafe.config.ConfigFactory
|
||||||
import com.typesafe.config.ConfigRenderOptions
|
import com.typesafe.config.ConfigRenderOptions
|
||||||
|
import com.typesafe.config.ConfigValue
|
||||||
|
import com.typesafe.config.ConfigValueFactory
|
||||||
|
import com.typesafe.config.parser.ConfigDocumentFactory
|
||||||
import mu.KotlinLogging
|
import mu.KotlinLogging
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@@ -18,15 +21,17 @@ import java.io.File
|
|||||||
* Manages app config.
|
* Manages app config.
|
||||||
*/
|
*/
|
||||||
open class ConfigManager {
|
open class ConfigManager {
|
||||||
|
val logger = KotlinLogging.logger {}
|
||||||
private val generatedModules = mutableMapOf<Class<out ConfigModule>, ConfigModule>()
|
private val generatedModules = mutableMapOf<Class<out ConfigModule>, ConfigModule>()
|
||||||
val config by lazy { loadConfigs() }
|
private val userConfigFile = File(ApplicationRootDir, "server.conf")
|
||||||
|
private var internalConfig = loadConfigs()
|
||||||
|
val config: Config
|
||||||
|
get() = internalConfig
|
||||||
|
|
||||||
// Public read-only view of modules
|
// Public read-only view of modules
|
||||||
val loadedModules: Map<Class<out ConfigModule>, ConfigModule>
|
val loadedModules: Map<Class<out ConfigModule>, ConfigModule>
|
||||||
get() = generatedModules
|
get() = generatedModules
|
||||||
|
|
||||||
val logger = KotlinLogging.logger {}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a config module
|
* Get a config module
|
||||||
*/
|
*/
|
||||||
@@ -54,7 +59,7 @@ open class ConfigManager {
|
|||||||
|
|
||||||
// Load user config
|
// Load user config
|
||||||
val userConfig =
|
val userConfig =
|
||||||
File(ApplicationRootDir, "server.conf").let {
|
userConfigFile.let {
|
||||||
ConfigFactory.parseFile(it)
|
ConfigFactory.parseFile(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,6 +91,20 @@ open class ConfigManager {
|
|||||||
registerModule(it)
|
registerModule(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateUserConfigFile(path: String, value: ConfigValue) {
|
||||||
|
val userConfigDoc = ConfigDocumentFactory.parseFile(userConfigFile)
|
||||||
|
val updatedConfigDoc = userConfigDoc.withValue(path, value)
|
||||||
|
val newFileContent = updatedConfigDoc.render()
|
||||||
|
userConfigFile.writeText(newFileContent)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateValue(path: String, value: Any) {
|
||||||
|
val configValue = ConfigValueFactory.fromAnyRef(value)
|
||||||
|
|
||||||
|
updateUserConfigFile(path, configValue)
|
||||||
|
internalConfig = internalConfig.withValue(path, configValue)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object GlobalConfigManager : ConfigManager()
|
object GlobalConfigManager : ConfigManager()
|
||||||
|
|||||||
@@ -15,19 +15,23 @@ import kotlin.reflect.KProperty
|
|||||||
* Abstract config module.
|
* Abstract config module.
|
||||||
*/
|
*/
|
||||||
@Suppress("UNUSED_PARAMETER")
|
@Suppress("UNUSED_PARAMETER")
|
||||||
abstract class ConfigModule(config: Config)
|
abstract class ConfigModule(getConfig: () -> Config)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract jvm-commandline-argument-overridable config module.
|
* Abstract jvm-commandline-argument-overridable config module.
|
||||||
*/
|
*/
|
||||||
abstract class SystemPropertyOverridableConfigModule(config: Config, moduleName: String) : ConfigModule(config) {
|
abstract class SystemPropertyOverridableConfigModule(getConfig: () -> Config, moduleName: String) : ConfigModule(getConfig) {
|
||||||
val overridableConfig = SystemPropertyOverrideDelegate(config, moduleName)
|
val overridableConfig = SystemPropertyOverrideDelegate(getConfig, moduleName)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Defines a config property that is overridable with jvm `-D` commandline arguments prefixed with [CONFIG_PREFIX] */
|
/** Defines a config property that is overridable with jvm `-D` commandline arguments prefixed with [CONFIG_PREFIX] */
|
||||||
class SystemPropertyOverrideDelegate(val config: Config, val moduleName: String) {
|
class SystemPropertyOverrideDelegate(val getConfig: () -> Config, val moduleName: String) {
|
||||||
|
operator fun <R> setValue(thisRef: R, property: KProperty<*>, value: Any) {
|
||||||
|
GlobalConfigManager.updateValue("$moduleName.${property.name}", value)
|
||||||
|
}
|
||||||
|
|
||||||
inline operator fun <R, reified T> getValue(thisRef: R, property: KProperty<*>): T {
|
inline operator fun <R, reified T> getValue(thisRef: R, property: KProperty<*>): T {
|
||||||
val configValue: T = config.getValue(thisRef, property)
|
val configValue: T = getConfig().getValue(thisRef, property)
|
||||||
|
|
||||||
val combined = System.getProperty(
|
val combined = System.getProperty(
|
||||||
"$CONFIG_PREFIX.$moduleName.${property.name}",
|
"$CONFIG_PREFIX.$moduleName.${property.name}",
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ import xyz.nulldev.ts.config.ConfigModule
|
|||||||
* Application info config.
|
* Application info config.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ApplicationInfoConfigModule(config: Config) : ConfigModule(config) {
|
class ApplicationInfoConfigModule(getConfig: () -> Config) : ConfigModule(getConfig) {
|
||||||
val packageName: String by config
|
val packageName: String by getConfig()
|
||||||
val debug: Boolean by config
|
val debug: Boolean by getConfig()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun register(config: Config) =
|
fun register(config: Config) =
|
||||||
ApplicationInfoConfigModule(config.getConfig("android.app"))
|
ApplicationInfoConfigModule { config.getConfig("android.app") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,27 +8,27 @@ import xyz.nulldev.ts.config.ConfigModule
|
|||||||
* Files configuration modules. Specifies where to store the Android files.
|
* Files configuration modules. Specifies where to store the Android files.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class FilesConfigModule(config: Config) : ConfigModule(config) {
|
class FilesConfigModule(getConfig: () -> Config) : ConfigModule(getConfig) {
|
||||||
val dataDir: String by config
|
val dataDir: String by getConfig()
|
||||||
val filesDir: String by config
|
val filesDir: String by getConfig()
|
||||||
val noBackupFilesDir: String by config
|
val noBackupFilesDir: String by getConfig()
|
||||||
val externalFilesDirs: MutableList<String> by config
|
val externalFilesDirs: MutableList<String> by getConfig()
|
||||||
val obbDirs: MutableList<String> by config
|
val obbDirs: MutableList<String> by getConfig()
|
||||||
val cacheDir: String by config
|
val cacheDir: String by getConfig()
|
||||||
val codeCacheDir: String by config
|
val codeCacheDir: String by getConfig()
|
||||||
val externalCacheDirs: MutableList<String> by config
|
val externalCacheDirs: MutableList<String> by getConfig()
|
||||||
val externalMediaDirs: MutableList<String> by config
|
val externalMediaDirs: MutableList<String> by getConfig()
|
||||||
val rootDir: String by config
|
val rootDir: String by getConfig()
|
||||||
val externalStorageDir: String by config
|
val externalStorageDir: String by getConfig()
|
||||||
val downloadCacheDir: String by config
|
val downloadCacheDir: String by getConfig()
|
||||||
val databasesDir: String by config
|
val databasesDir: String by getConfig()
|
||||||
|
|
||||||
val prefsDir: String by config
|
val prefsDir: String by getConfig()
|
||||||
|
|
||||||
val packageDir: String by config
|
val packageDir: String by getConfig()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun register(config: Config) =
|
fun register(config: Config) =
|
||||||
FilesConfigModule(config.getConfig("android.files"))
|
FilesConfigModule { config.getConfig("android.files") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,19 +4,19 @@ import com.typesafe.config.Config
|
|||||||
import io.github.config4k.getValue
|
import io.github.config4k.getValue
|
||||||
import xyz.nulldev.ts.config.ConfigModule
|
import xyz.nulldev.ts.config.ConfigModule
|
||||||
|
|
||||||
class SystemConfigModule(val config: Config) : ConfigModule(config) {
|
class SystemConfigModule(val getConfig: () -> Config) : ConfigModule(getConfig) {
|
||||||
val isDebuggable: Boolean by config
|
val isDebuggable: Boolean by getConfig()
|
||||||
|
|
||||||
val propertyPrefix = "properties."
|
val propertyPrefix = "properties."
|
||||||
|
|
||||||
fun getStringProperty(property: String) = config.getString("$propertyPrefix$property")!!
|
fun getStringProperty(property: String) = getConfig().getString("$propertyPrefix$property")!!
|
||||||
fun getIntProperty(property: String) = config.getInt("$propertyPrefix$property")
|
fun getIntProperty(property: String) = getConfig().getInt("$propertyPrefix$property")
|
||||||
fun getLongProperty(property: String) = config.getLong("$propertyPrefix$property")
|
fun getLongProperty(property: String) = getConfig().getLong("$propertyPrefix$property")
|
||||||
fun getBooleanProperty(property: String) = config.getBoolean("$propertyPrefix$property")
|
fun getBooleanProperty(property: String) = getConfig().getBoolean("$propertyPrefix$property")
|
||||||
fun hasProperty(property: String) = config.hasPath("$propertyPrefix$property")
|
fun hasProperty(property: String) = getConfig().hasPath("$propertyPrefix$property")
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun register(config: Config) =
|
fun register(config: Config) =
|
||||||
SystemConfigModule(config.getConfig("android.system"))
|
SystemConfigModule { config.getConfig("android.system") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,39 +13,39 @@ import xyz.nulldev.ts.config.SystemPropertyOverridableConfigModule
|
|||||||
import xyz.nulldev.ts.config.debugLogsEnabled
|
import xyz.nulldev.ts.config.debugLogsEnabled
|
||||||
|
|
||||||
private const val MODULE_NAME = "server"
|
private const val MODULE_NAME = "server"
|
||||||
class ServerConfig(config: Config, moduleName: String = MODULE_NAME) : SystemPropertyOverridableConfigModule(config, moduleName) {
|
class ServerConfig(getConfig: () -> Config, moduleName: String = MODULE_NAME) : SystemPropertyOverridableConfigModule(getConfig, moduleName) {
|
||||||
val ip: String by overridableConfig
|
var ip: String by overridableConfig
|
||||||
val port: Int by overridableConfig
|
var port: Int by overridableConfig
|
||||||
|
|
||||||
// proxy
|
// proxy
|
||||||
val socksProxyEnabled: Boolean by overridableConfig
|
var socksProxyEnabled: Boolean by overridableConfig
|
||||||
val socksProxyHost: String by overridableConfig
|
var socksProxyHost: String by overridableConfig
|
||||||
val socksProxyPort: String by overridableConfig
|
var socksProxyPort: String by overridableConfig
|
||||||
|
|
||||||
// webUI
|
// webUI
|
||||||
val webUIEnabled: Boolean by overridableConfig
|
var webUIEnabled: Boolean by overridableConfig
|
||||||
val webUIFlavor: String by overridableConfig
|
var webUIFlavor: String by overridableConfig
|
||||||
val initialOpenInBrowserEnabled: Boolean by overridableConfig
|
var initialOpenInBrowserEnabled: Boolean by overridableConfig
|
||||||
val webUIInterface: String by overridableConfig
|
var webUIInterface: String by overridableConfig
|
||||||
val electronPath: String by overridableConfig
|
var electronPath: String by overridableConfig
|
||||||
|
|
||||||
// downloader
|
// downloader
|
||||||
val downloadAsCbz: Boolean by overridableConfig
|
var downloadAsCbz: Boolean by overridableConfig
|
||||||
val downloadsPath: String by overridableConfig
|
var downloadsPath: String by overridableConfig
|
||||||
|
|
||||||
// updater
|
// updater
|
||||||
val maxParallelUpdateRequests: Int by overridableConfig
|
var maxParallelUpdateRequests: Int by overridableConfig
|
||||||
|
|
||||||
// Authentication
|
// Authentication
|
||||||
val basicAuthEnabled: Boolean by overridableConfig
|
var basicAuthEnabled: Boolean by overridableConfig
|
||||||
val basicAuthUsername: String by overridableConfig
|
var basicAuthUsername: String by overridableConfig
|
||||||
val basicAuthPassword: String by overridableConfig
|
var basicAuthPassword: String by overridableConfig
|
||||||
|
|
||||||
// misc
|
// misc
|
||||||
val debugLogsEnabled: Boolean = debugLogsEnabled(GlobalConfigManager.config)
|
var debugLogsEnabled: Boolean = debugLogsEnabled(GlobalConfigManager.config)
|
||||||
val systemTrayEnabled: Boolean by overridableConfig
|
var systemTrayEnabled: Boolean by overridableConfig
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun register(config: Config) = ServerConfig(config.getConfig(MODULE_NAME))
|
fun register(getConfig: () -> Config) = ServerConfig({ getConfig().getConfig(MODULE_NAME) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ fun applicationSetup() {
|
|||||||
|
|
||||||
// register Tachidesk's config which is dubbed "ServerConfig"
|
// register Tachidesk's config which is dubbed "ServerConfig"
|
||||||
GlobalConfigManager.registerModule(
|
GlobalConfigManager.registerModule(
|
||||||
ServerConfig.register(GlobalConfigManager.config)
|
ServerConfig.register { GlobalConfigManager.config }
|
||||||
)
|
)
|
||||||
|
|
||||||
// Application dirs
|
// Application dirs
|
||||||
|
|||||||
Reference in New Issue
Block a user