[CORDA-2627] Fail the custom vault state migration if any states were skipped (#4782)

* Fail the migration if any states were skipped

* Update test case to check running a second time
This commit is contained in:
JamesHR3 2019-02-18 15:39:37 +00:00 committed by Gavin Thomas
parent 626fa19769
commit 055aabe1bb
2 changed files with 18 additions and 9 deletions

View File

@ -50,8 +50,8 @@ class VaultStateMigration : CordaMigration() {
// This should only happen if there was no attachment that could be used to deserialise the output states, and the state was // This should only happen if there was no attachment that could be used to deserialise the output states, and the state was
// serialised such that the participants list cannot be accessed (participants is calculated and not marked as a // serialised such that the participants list cannot be accessed (participants is calculated and not marked as a
// SerializableCalculatedProperty. // SerializableCalculatedProperty.
throw VaultStateMigrationException("Cannot add state parties as state class is not on the classpath " + throw VaultStateMigrationException("Cannot add state parties for state ${stateAndRef.ref} as state class is not on the " +
"and participants cannot be synthesised") "classpath and participants cannot be synthesised")
} }
} }
@ -71,8 +71,8 @@ class VaultStateMigration : CordaMigration() {
override fun execute(database: Database?) { override fun execute(database: Database?) {
logger.info("Migrating vault state data to V4 tables") logger.info("Migrating vault state data to V4 tables")
if (database == null) { if (database == null) {
logger.warn("Cannot migrate vault states: Liquibase failed to provide a suitable database connection") logger.error("Cannot migrate vault states: Liquibase failed to provide a suitable database connection")
return throw VaultStateMigrationException("Cannot migrate vault states as liquibase failed to provide a suitable database connection")
} }
initialiseNodeServices(database, setOf(VaultMigrationSchemaV1, VaultSchemaV1)) initialiseNodeServices(database, setOf(VaultMigrationSchemaV1, VaultSchemaV1))
var statesSkipped = 0 var statesSkipped = 0
@ -98,13 +98,16 @@ class VaultStateMigration : CordaMigration() {
it.relevancyStatus = Vault.RelevancyStatus.NOT_RELEVANT it.relevancyStatus = Vault.RelevancyStatus.NOT_RELEVANT
} }
} catch (e: VaultStateMigrationException) { } catch (e: VaultStateMigrationException) {
logger.warn("An error occurred while migrating a vault state: ${e.message}. Skipping", e) logger.warn("An error occurred while migrating a vault state: ${e.message}. Skipping. This will cause the " +
"migration to fail.", e)
statesSkipped++ statesSkipped++
} }
} }
} }
if (statesSkipped > 0) { if (statesSkipped > 0) {
logger.error("$statesSkipped states could not be migrated as there was no class available for them.") logger.error("$statesSkipped states could not be migrated as there was no class available for them.")
throw VaultStateMigrationException("Failed to migrate $statesSkipped states in the vault. Check the logs for details of the " +
"error for each state.")
} }
logger.info("Finished performing vault state data migration for ${persistentStates.numStates - statesSkipped} states") logger.info("Finished performing vault state data migration for ${persistentStates.numStates - statesSkipped} states")
} }

View File

@ -53,6 +53,7 @@ import java.time.Clock
import java.time.Duration import java.time.Duration
import java.util.* import java.util.*
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import kotlin.test.assertFalse import kotlin.test.assertFalse
/** /**
@ -431,15 +432,20 @@ class VaultStateMigrationTest {
} }
@Test @Test
fun `State with corresponding transaction missing is skipped`() { fun `State with corresponding transaction missing fails migration`() {
val cash = Cash() val cash = Cash()
val unknownTx = createCashTransaction(cash, 100.DOLLARS, BOB) val unknownTx = createCashTransaction(cash, 100.DOLLARS, BOB)
createVaultStatesFromTransaction(unknownTx) createVaultStatesFromTransaction(unknownTx)
addCashStates(10, BOB) addCashStates(10, BOB)
val migration = VaultStateMigration() val migration = VaultStateMigration()
migration.execute(liquibaseDB) assertFailsWith<VaultStateMigrationException> { migration.execute(liquibaseDB) }
assertEquals(10, getStatePartyCount()) assertEquals(10, getStatePartyCount())
// Now add the missing transaction and ensure that the migration succeeds
storeTransaction(unknownTx)
migration.execute(liquibaseDB)
assertEquals(11, getStatePartyCount())
} }
@Test @Test
@ -453,8 +459,8 @@ class VaultStateMigrationTest {
assertEquals(10, getVaultStateCount(Vault.RelevancyStatus.RELEVANT)) assertEquals(10, getVaultStateCount(Vault.RelevancyStatus.RELEVANT))
} }
@Test @Test(expected = VaultStateMigrationException::class)
fun `Null database causes migration to be ignored`() { fun `Null database causes migration to fail`() {
val migration = VaultStateMigration() val migration = VaultStateMigration()
// Just check this does not throw an exception // Just check this does not throw an exception
migration.execute(null) migration.execute(null)