feat(config): 支持通过环境变量或 VM 参数指定数据目录.

主要是为 Docker 镜像支持, 这样可以在镜像中指定数据目录, 方便设置持久卷或者文件映射.
This commit is contained in:
LamGC 2022-02-26 12:00:16 +08:00
parent 737ac9a08a
commit b3c63e5abe
Signed by: LamGC
GPG Key ID: 6C5AE2A913941E1D
3 changed files with 57 additions and 17 deletions

View File

@ -1,5 +1,6 @@
package net.lamgc.scalabot
import ch.qos.logback.core.PropertyDefinerBase
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
@ -90,19 +91,38 @@ internal data class AppConfig(
/**
* 需要用到的路径.
*
* 必须提供 `pathSupplier` `fileSupplier` 其中一个, 才能正常提供路径.
*/
internal enum class AppPaths(
private val pathSupplier: () -> String,
private val initializer: AppPaths.() -> Unit = AppPaths::defaultInitializer
private val pathSupplier: () -> String = { fileSupplier.invoke().canonicalPath },
private val initializer: AppPaths.() -> Unit = AppPaths::defaultInitializer,
private val fileSupplier: () -> File = { File(pathSupplier()) }
) {
DEFAULT_CONFIG_APPLICATION({ "./config.json" }, {
/**
* 数据根目录.
*
* 所有运行数据的存放位置.
*
* 提示: 结尾不带 `/`.
*/
DATA_ROOT(fileSupplier = {
File(System.getProperty(PathConst.PROP_DATA_PATH) ?: System.getenv(PathConst.ENV_DATA_PATH) ?: ".")
}, initializer = {
val f = file
if (!f.exists()) {
f.mkdirs()
}
}),
DEFAULT_CONFIG_APPLICATION({ "$DATA_ROOT/config.json" }, {
if (!file.exists()) {
file.bufferedWriter(StandardCharsets.UTF_8).use {
GsonConst.botConfigGson.toJson(AppConfig(), it)
}
}
}),
DEFAULT_CONFIG_BOT({ "./bot.json" }, {
DEFAULT_CONFIG_BOT({ "$DATA_ROOT/bot.json" }, {
if (!file.exists()) {
file.bufferedWriter(StandardCharsets.UTF_8).use {
GsonConst.botConfigGson.toJson(
@ -121,15 +141,15 @@ internal enum class AppPaths(
}
}
}),
DATA_DB({ "./data/db/" }),
DATA_LOGS({ "./data/logs/" }),
EXTENSIONS({ "./extensions/" }),
DATA_EXTENSIONS({ "./data/extensions/" }),
TEMP({ "./tmp/" })
DATA_DB({ "$DATA_ROOT/data/db/" }),
DATA_LOGS({ "$DATA_ROOT/data/logs/" }),
EXTENSIONS({ "$DATA_ROOT/extensions/" }),
DATA_EXTENSIONS({ "$DATA_ROOT/data/extensions/" }),
TEMP({ "$DATA_ROOT/tmp/" })
;
val file: File
get() = File(pathSupplier.invoke())
get() = fileSupplier.invoke()
val path: String
get() = pathSupplier.invoke()
@ -138,7 +158,7 @@ internal enum class AppPaths(
@Synchronized
fun initial() {
if (!initialized.get()) {
initializer(this)
initializer()
initialized.set(true)
}
}
@ -146,6 +166,21 @@ internal enum class AppPaths(
override fun toString(): String {
return path
}
private companion object PathConst {
private const val PROP_DATA_PATH = "bot.path.data"
private const val ENV_DATA_PATH = "BOT_DATA_PATH"
}
}
/**
* LogBack 提供日志目录路径.
*/
internal class LogDirectorySupplier : PropertyDefinerBase() {
override fun getPropertyValue(): String {
return AppPaths.DATA_LOGS.path
}
}
internal object Const {
@ -153,14 +188,16 @@ internal object Const {
}
private fun AppPaths.defaultInitializer() {
if (!file.exists()) {
val result = if (path.endsWith("/")) {
file.mkdirs()
val f = file
val p = path
if (!f.exists()) {
val result = if (p.endsWith("/")) {
f.mkdirs()
} else {
file.createNewFile()
f.createNewFile()
}
if (!result) {
log.warn { "初始化文件(夹)失败: $path" }
log.warn { "初始化文件(夹)失败: $p" }
}
}
}

View File

@ -17,6 +17,7 @@ private val launcher = Launcher()
fun main(args: Array<String>): Unit = runBlocking {
log.info { "ScalaBot 正在启动中..." }
log.info { "数据目录: ${AppPaths.DATA_ROOT}" }
log.debug { "启动参数: ${args.joinToString(prefix = "[", postfix = "]")}" }
initialFiles()
if (Const.config.metrics.enable) {

View File

@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<included>
<define name="DATA_LOGS" class="net.lamgc.scalabot.LogDirectorySupplier"/>
<appender name="STD_OUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%d{HH:mm:ss.SSS} %5level][%logger{36}][%thread]: %msg%n</pattern>
@ -20,7 +22,7 @@
</appender>
<appender name="FILE_OUT" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>data/logs/latest.log</file>
<file>${DATA_LOGS}/latest.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>data/logs/%d{yyyy-MM-dd}.log.gz</fileNamePattern>
<maxHistory>30</maxHistory>