flyaway

class FlywayConfig(
    private val dataSource: DataSource,
    private val locations: Array<String> = arrayOf("classpath:db/migration"),
    private val baselineOnMigrate: Boolean = true,
    private val baselineVersion: String = "0",
    private val table: String = "flyway_schema_history",
    private val validateOnMigrate: Boolean = true,
    private val cleanDisabled: Boolean = true,
    private val configure: FluentConfiguration.() -> Unit = {}
) {

    private val logger = LoggerFactory.getLogger(FlywayConfig::class.java)

    private val flyway: Flyway by lazy {
        Flyway.configure()
            .dataSource(dataSource)
            .locations(*locations)
            .baselineOnMigrate(baselineOnMigrate)
            .baselineVersion(baselineVersion)
            .table(table)
            .validateOnMigrate(validateOnMigrate)
            .cleanDisabled(cleanDisabled)
            .apply(configure)
            .load()
    }

    fun migrate(): MigrateResult {

        logger.info("Starting database migration...")

        return runCatching { flyway.migrate() }
            .onSuccess { result ->

                when {
                    result.migrationsExecuted > 0 ->
                        logger.info(
                            "Applied ${result.migrationsExecuted} migration(s), current version: ${result.targetSchemaVersion}"
                        )

                    else ->
                        logger.info(
                            "Database is up to date, current version: ${result.targetSchemaVersion}"
                        )
                }
            }
            .onFailure { ex ->
                logger.error("Database migration failed", ex)
            }
            .getOrElse {
                throw IllegalStateException("Database migration failed", it)
            }
    }

    fun validate() = flyway.validate()

    fun info() = flyway.info()

    fun repair() = flyway.repair()
}