[ENT-1843]: Not properly caught exception when node starts first time without migration (fix). (#879)

This commit is contained in:
Michele Sollecito 2018-05-24 16:29:22 +01:00 committed by GitHub
parent ee094ef129
commit 6ec394b6be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 5 deletions

View File

@ -6,6 +6,7 @@ release, see :doc:`upgrade-notes`.
Unreleased
==========
* Introduced a hierarchy of ``DatabaseMigrationException``s, allowing ``NodeStartup`` to gracefully inform users of problems related to database migrations before exiting with a non-zero code.
* ``WireTransaction.Companion.createComponentGroups`` has been marked as ``@CordaInternal``. It was never intended to be
public and was already internal for Kotlin code.

View File

@ -23,7 +23,9 @@ import liquibase.resource.ClassLoaderResourceAccessor
import net.corda.core.internal.MigrationHelpers.getMigrationResource
import net.corda.core.schemas.MappedSchema
import net.corda.core.utilities.contextLogger
import java.io.*
import java.io.ByteArrayInputStream
import java.io.InputStream
import java.io.Writer
import javax.sql.DataSource
class SchemaMigration(
@ -85,9 +87,9 @@ class SchemaMigration(
val resource = getMigrationResource(mappedSchema, classLoader)
when {
resource != null -> resource
failOnMigrationMissing -> throw IllegalStateException("No migration defined for schema: ${mappedSchema.name} v${mappedSchema.version}")
failOnMigrationMissing -> throw MissingMigrationException(mappedSchema)
else -> {
logger.warn("No migration defined for schema: ${mappedSchema.name} v${mappedSchema.version}")
logger.warn(MissingMigrationException.errorMessageFor(mappedSchema))
null
}
}
@ -133,7 +135,7 @@ class SchemaMigration(
check && !run -> {
val unRunChanges = liquibase.listUnrunChangeSets(Contexts(), LabelExpression())
if (unRunChanges.isNotEmpty()) {
throw IllegalStateException("There are ${unRunChanges.size} outstanding database changes that need to be run. Please use the advanced migration tool. See: https://docs.corda.r3.com/database-migration.html")
throw OutstandingDatabaseChangesException(unRunChanges.size)
}
}
(outputWriter != null) && !check && !run -> liquibase.update(Contexts(), outputWriter)
@ -161,3 +163,19 @@ class SchemaMigration(
return if (liquibaseDbImplementation is MSSQLDatabase) AzureDatabase(conn) else liquibaseDbImplementation
}
}
open class DatabaseMigrationException(message: String) : IllegalArgumentException(message) {
override val message: String = super.message!!
}
class MissingMigrationException(@Suppress("MemberVisibilityCanBePrivate") val mappedSchema: MappedSchema) : DatabaseMigrationException(errorMessageFor(mappedSchema)) {
internal companion object {
fun errorMessageFor(mappedSchema: MappedSchema): String = "No migration defined for schema: ${mappedSchema.name} v${mappedSchema.version}"
}
}
class OutstandingDatabaseChangesException(@Suppress("MemberVisibilityCanBePrivate") private val count: Int) : DatabaseMigrationException(errorMessageFor(count)) {
internal companion object {
fun errorMessageFor(count: Int): String = "There are $count outstanding database changes that need to be run. Please use the advanced migration tool. See: https://docs.corda.r3.com/database-migration.html"
}
}

View File

@ -12,8 +12,8 @@ package net.corda.node.internal
import com.jcabi.manifests.Manifests
import io.netty.channel.unix.Errors
import net.corda.core.crypto.Crypto
import net.corda.core.cordapp.Cordapp
import net.corda.core.crypto.Crypto
import net.corda.core.internal.Emoji
import net.corda.core.internal.concurrent.thenMatch
import net.corda.core.internal.createDirectories
@ -35,6 +35,7 @@ import net.corda.node.utilities.registration.HTTPNetworkRegistrationService
import net.corda.node.utilities.registration.NodeRegistrationHelper
import net.corda.nodeapi.internal.addShutdownHook
import net.corda.nodeapi.internal.config.UnknownConfigurationKeysException
import net.corda.nodeapi.internal.persistence.DatabaseMigrationException
import net.corda.nodeapi.internal.persistence.oracleJdbcDriverSerialFilter
import net.corda.tools.shell.InteractiveShell
import org.fusesource.jansi.Ansi
@ -134,6 +135,9 @@ open class NodeStartup(val args: Array<String>) {
try {
cmdlineOptions.baseDirectory.createDirectories()
startNode(conf, versionInfo, startTime, cmdlineOptions)
} catch (e: DatabaseMigrationException) {
logger.error(e.message)
return false
} catch (e: Exception) {
if (e is Errors.NativeIoException && e.message?.contains("Address already in use") == true) {
logger.error("One of the ports required by the Corda node is already in use.")