ReloadableConfig

A config that can be reloaded while the app runs. Every reload builds the sources again (so files are read again), loads and validates the config, and publishes it to config only if it is valid. A failed reload keeps the last good config and emits the error to failures. Reloads run one at a time, so a slow reload never overwrites a newer one.

val appConfig = ReloadableConfig.load(load = { loadAppConfig() }) {
sources {
+EnvSource()
+TomlSource.fromFile("config.toml")
}
}

scope.launch { appConfig.failures.collect { log.warn("Config reload skipped", it) } }
appConfig.reloadEvery(scope, 30.seconds)
appConfig.config.collect { config -> applyLogLevel(config.logLevel) }

Types

Link copied to clipboard
object Companion

Creates a ReloadableConfig with load.

Properties

Link copied to clipboard
val config: StateFlow<T>

The latest valid config. Collect it to react to updates.

Link copied to clipboard
val current: T

The latest valid config, the same as config.value.

Link copied to clipboard
val failures: SharedFlow<Throwable>

Errors from reloads that failed and were skipped, see ReloadResult.Failed.error. Nothing is replayed, so start collecting before starting reloads.

Functions

Link copied to clipboard
suspend fun reload(): ReloadResult<T>

Loads the config again and publishes it if it is valid and different. Never throws except for cancellation: a failure keeps the current config and is emitted to failures.

Link copied to clipboard
fun reloadEvery(scope: CoroutineScope, period: Duration): Job

Reloads every period, until scope or the returned job is cancelled.

Link copied to clipboard
fun reloadOn(scope: CoroutineScope, triggers: Flow<*>): Job

Reloads each time triggers emits, until scope or the returned job is cancelled.

Link copied to clipboard
fun watch(scope: CoroutineScope, vararg sources: ReloadableSource): Job

Reloads each time one of sources reports a change. Pass the same instances that the sources block adds, so the watched source is the one that is read: