[ENT-1281]: Disable database.runMigration by default and enforce database version on startup. (#264)

* [ENT-1281]: set database.runMigration=false by default and add state check at startup

* [ENT-1281]: attempt to fix tests

* [ENT-1281]: attempt to fix tests

* [ENT-1281]: set runMigration=true in the cordformation plugin

* [ENT-1281]: attempt to fix tests

* [ENT-1281]: attempt to fix tests

* [ENT-1281]: attempt to fix tests

* [ENT-1281]: fix formatting

* [ENT-1281]: typo and javadocs

* [ENT-1281]: small refactoring and added test for SchemaMigration

* [ENT-1281]: update documentation to reflect changes

* [ENT-1281]: fix tests after merge

* [ENT-1339]: for h2, allow schemas without migrations to run (#294)

* [ENT-1339]: for h2, allow schemas without migrations to run

* [ENT-1339]: fix various migration issues and change author name

* [ENT-1339]: add naming convention for migrations

* [ENT-1339]: change naming convention to use hyphens

* [ENT-1339]: change mapping of participants to be able to control the table name

* [ENT-1339]: change FK names to <=30 for oracle 11g compatibility

* [ENT-1339]: cmd line argument for migrations made consistent

* [ENT-1339]: revert abstract state superclasses

* Update db integration test setup - new tables.

* Update db integration test setup - new tables.

* [ENT-1339]: remove final from participants to allow table name config

* [ENT-1339]: shortened pk

* [ENT-1339]: revert constructor

* [ENT-1339]: change getMigrationResource api to Nullable

* fix compile error

* [ENT-1281]: fix tests after merge

* [ENT-1281]: fix tests after merge
This commit is contained in:
Tudor Malene
2018-01-10 11:32:24 +00:00
committed by GitHub
parent 3c8ebdedae
commit 12546c0a7c
31 changed files with 135 additions and 40 deletions

View File

@ -18,7 +18,7 @@ const val NODE_DATABASE_PREFIX = "node_"
// This class forms part of the node config and so any changes to it must be handled with care
data class DatabaseConfig(
val runMigration: Boolean = true,
val runMigration: Boolean = false,
val transactionIsolationLevel: TransactionIsolationLevel = TransactionIsolationLevel.REPEATABLE_READ,
val schema: String? = null,
val exportHibernateJMXStatistics: Boolean = false

View File

@ -2,6 +2,7 @@ package net.corda.nodeapi.internal.persistence
import com.fasterxml.jackson.databind.ObjectMapper
import liquibase.Contexts
import liquibase.LabelExpression
import liquibase.Liquibase
import liquibase.database.Database
import liquibase.database.DatabaseFactory
@ -14,17 +15,34 @@ import net.corda.core.utilities.contextLogger
import java.io.*
import javax.sql.DataSource
class SchemaMigration(val schemas: Set<MappedSchema>, val dataSource: DataSource, val failOnMigrationMissing: Boolean, private val schemaName: String? = null) {
class SchemaMigration(val schemas: Set<MappedSchema>, val dataSource: DataSource, val failOnMigrationMissing: Boolean, private val databaseConfig: DatabaseConfig) {
companion object {
private val logger = contextLogger()
}
fun generateMigrationScript(outputFile: File) = doRunMigration(PrintWriter(outputFile))
/**
* Main entry point to the schema migration.
* Called during node startup.
*/
fun nodeStartup() = if (databaseConfig.runMigration) runMigration() else checkState()
fun runMigration() = doRunMigration()
/**
* will run the liquibase migration on the actual database
*/
fun runMigration() = doRunMigration(run = true, outputWriter = null, check = false)
private fun doRunMigration(outputWriter: Writer? = null) {
/**
* will write the migration to the outputFile
*/
fun generateMigrationScript(outputFile: File) = doRunMigration(run = false, outputWriter = PrintWriter(outputFile), check = false)
/**
* ensures that the database is up to date with the latest migration changes
*/
fun checkState() = doRunMigration(run = false, outputWriter = null, check = true)
private fun doRunMigration(run: Boolean, outputWriter: Writer?, check: Boolean) {
// virtual file name of the changelog that includes all schemas
val dynamicInclude = "master.changelog.json"
@ -65,6 +83,7 @@ class SchemaMigration(val schemas: Set<MappedSchema>, val dataSource: DataSource
val liquibase = Liquibase(dynamicInclude, customResourceAccessor, getLiquibaseDatabase(JdbcConnection(connection)))
val schemaName: String? = databaseConfig.schema
if (!schemaName.isNullOrBlank()) {
if (liquibase.database.defaultSchemaName != schemaName) {
logger.debug("defaultSchemaName=${liquibase.database.defaultSchemaName} changed to $schemaName")
@ -79,10 +98,16 @@ class SchemaMigration(val schemas: Set<MappedSchema>, val dataSource: DataSource
logger.info("liquibaseSchemaName=${liquibase.database.liquibaseSchemaName}")
logger.info("outputDefaultSchema=${liquibase.database.outputDefaultSchema}")
if (outputWriter != null) {
liquibase.update(Contexts(), outputWriter)
} else {
liquibase.update(Contexts())
when {
run && !check -> liquibase.update(Contexts())
check && !run -> {
val unRunChanges = liquibase.listUnrunChangeSets(Contexts(), LabelExpression())
if (unRunChanges.isNotEmpty()) {
throw Exception("There are ${unRunChanges.size} outstanding database changes that need to be run. Please use the provided tools to update the database.")
}
}
(outputWriter != null) && !check && !run -> liquibase.update(Contexts(), outputWriter)
else -> throw IllegalStateException("Invalid usage.")
}
}
}