2018-07-12 13:39:17 +00:00
plugins {
id 'com.google.cloud.tools.jib' version '0.9.4'
}
2016-05-14 16:57:41 +00:00
apply plugin: 'kotlin'
2017-06-22 09:35:49 +00:00
// Java Persistence API support: create no-arg constructor
// see: http://stackoverflow.com/questions/32038177/kotlin-with-jpa-default-constructor-hell
apply plugin: 'kotlin-jpa'
2016-11-15 12:42:35 +00:00
apply plugin: 'java'
2016-11-18 14:41:06 +00:00
apply plugin: 'net.corda.plugins.quasar-utils'
apply plugin: 'net.corda.plugins.publish-utils'
2017-06-26 17:07:56 +00:00
apply plugin: 'com.jfrog.artifactory'
2016-05-14 16:57:41 +00:00
2016-12-06 10:49:46 +00:00
description 'Corda node modules'
2019-12-16 16:24:47 +00:00
ext {
Properties constants = new Properties ( )
file ( "$rootDir/constants.properties" ) . withInputStream { constants . load ( it ) }
jolokia_version = constants . getProperty ( 'jolokiaAgentVersion' )
}
2016-05-14 16:57:41 +00:00
//noinspection GroovyAssignabilityCheck
configurations {
2016-09-08 14:28:04 +00:00
integrationTestCompile . extendsFrom testCompile
2019-05-20 10:57:56 +00:00
integrationTestRuntimeOnly . extendsFrom testRuntimeOnly
2019-09-03 15:40:08 +00:00
slowIntegrationTestCompile . extendsFrom testCompile
slowIntegrationTestRuntimeOnly . extendsFrom testRuntimeOnly
2019-11-05 13:44:18 +00:00
2019-11-19 15:02:35 +00:00
jdkRt
2019-11-05 13:44:18 +00:00
deterministic
2016-05-14 16:57:41 +00:00
}
2016-07-21 12:55:40 +00:00
sourceSets {
2016-09-08 14:28:04 +00:00
integrationTest {
kotlin {
compileClasspath + = main . output + test . output
runtimeClasspath + = main . output + test . output
srcDir file ( 'src/integration-test/kotlin' )
}
2017-07-17 17:20:02 +00:00
java {
compileClasspath + = main . output + test . output
runtimeClasspath + = main . output + test . output
srcDir file ( 'src/integration-test/java' )
}
2017-04-21 15:26:35 +00:00
resources {
srcDir file ( 'src/integration-test/resources' )
}
2016-09-08 14:28:04 +00:00
}
2019-09-03 15:40:08 +00:00
slowIntegrationTest {
kotlin {
compileClasspath + = main . output + test . output
runtimeClasspath + = main . output + test . output
srcDir file ( 'src/integration-test-slow/kotlin' )
}
java {
compileClasspath + = main . output + test . output
runtimeClasspath + = main . output + test . output
srcDir file ( 'src/integration-test-slow/java' )
}
resources {
srcDir file ( 'src/integration-test-slow/resources' )
}
}
2016-07-21 12:55:40 +00:00
}
2018-07-12 13:39:17 +00:00
jib . container {
2019-09-18 09:26:26 +00:00
mainClass = "net.corda.node.Corda"
args = [ '--log-to-console' , '--no-local-shell' , '--config-file=/config/node.conf' ]
// The Groovy string needs to be converted to a `java.lang.String` below.
jvmFlags = [ '-Xmx1g' , "-javaagent:/app/libs/quasar-core-${quasar_version}.jar" . toString ( ) ]
2018-07-12 13:39:17 +00:00
}
2017-05-05 12:12:36 +00:00
// Use manual resource copying of log4j2.xml rather than source sets.
// This prevents problems in IntelliJ with regard to duplicate source roots.
processResources {
from file ( "$rootDir/config/dev/log4j2.xml" )
2017-12-08 16:27:12 +00:00
from file ( "$rootDir/config/dev/jolokia-access.xml" )
}
processTestResources {
from file ( "$rootDir/config/test/jolokia-access.xml" )
2017-05-05 12:12:36 +00:00
}
2016-05-14 16:57:41 +00:00
// To find potential version conflicts, run "gradle htmlDependencyReport" and then look in
// build/reports/project/dependencies/index.html for green highlighted parts of the tree.
dependencies {
2017-03-17 10:33:01 +00:00
compile project ( ':node-api' )
2017-03-22 15:52:54 +00:00
compile project ( ':client:rpc' )
2018-03-07 09:57:32 +00:00
compile project ( ':tools:shell' )
2018-09-06 08:37:04 +00:00
compile project ( ':tools:cliutils' )
2018-10-29 13:33:43 +00:00
compile project ( ':common-validation' )
2018-11-08 15:56:00 +00:00
compile project ( ':common-configuration-parsing' )
2019-04-09 19:14:37 +00:00
compile project ( ':common-logging' )
2019-09-03 15:40:08 +00:00
2019-02-17 11:47:38 +00:00
// Backwards compatibility goo: Apps expect confidential-identities to be loaded by default.
// We could eventually gate this on a target-version check.
compile project ( ':confidential-identities' )
2017-02-16 11:02:36 +00:00
2016-07-22 16:31:03 +00:00
// Log4J: logging framework (with SLF4J bindings)
2016-07-21 12:55:40 +00:00
compile "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_version}"
2016-09-01 10:12:59 +00:00
compile "org.apache.logging.log4j:log4j-web:${log4j_version}"
2017-04-21 15:26:35 +00:00
compile "org.slf4j:jul-to-slf4j:$slf4j_version"
2016-05-14 16:57:41 +00:00
2018-04-24 13:03:41 +00:00
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
2018-10-15 12:44:02 +00:00
runtimeOnly "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
2016-05-14 16:57:41 +00:00
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
2017-03-22 15:52:54 +00:00
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
2016-05-14 16:57:41 +00:00
2020-03-04 20:56:17 +00:00
compile "org.fusesource.jansi:jansi:$jansi_version"
2017-01-03 14:15:23 +00:00
compile "com.google.guava:guava:$guava_version"
2016-05-14 16:57:41 +00:00
2018-03-14 16:07:31 +00:00
// For caches rather than guava
compile "com.github.ben-manes.caffeine:caffeine:$caffeine_version"
2018-10-02 09:33:17 +00:00
// For async logging
compile "com.lmax:disruptor:$disruptor_version"
2016-05-14 16:57:41 +00:00
// Artemis: for reliable p2p message queues.
2017-10-26 11:16:57 +00:00
// TODO: remove the forced update of commons-collections and beanutils when artemis updates them
compile "org.apache.commons:commons-collections4:${commons_collections_version}"
compile "commons-beanutils:commons-beanutils:${beanutils_version}"
2016-05-14 16:57:41 +00:00
compile "org.apache.activemq:artemis-server:${artemis_version}"
compile "org.apache.activemq:artemis-core-client:${artemis_version}"
2019-09-03 15:40:08 +00:00
runtime ( "org.apache.activemq:artemis-amqp-protocol:${artemis_version}" ) {
2017-05-31 17:33:57 +00:00
// Gains our proton-j version from core module.
exclude group: 'org.apache.qpid' , module: 'proton-j'
}
2016-05-14 16:57:41 +00:00
2017-03-06 14:19:04 +00:00
// Manifests: for reading stuff from the manifest file
2018-05-24 17:26:55 +00:00
compile "com.jcabi:jcabi-manifests:$jcabi_manifests_version"
2017-03-06 14:19:04 +00:00
2016-05-14 16:57:41 +00:00
// Coda Hale's Metrics: for monitoring of key statistics
2019-06-20 15:19:16 +00:00
compile "io.dropwizard.metrics:metrics-jmx:$metrics_version"
2016-05-14 16:57:41 +00:00
// TypeSafe Config: for simple and human friendly config files.
2017-01-03 14:15:23 +00:00
compile "com.typesafe:config:$typesafe_config_version"
2016-05-14 16:57:41 +00:00
2019-11-05 13:44:18 +00:00
// Sandbox for deterministic contract verification
compile "net.corda.djvm:corda-djvm:$djvm_version"
compile project ( ':serialization-djvm' )
compile ( project ( ':node:djvm' ) ) {
transitive = false
}
2019-11-19 15:02:35 +00:00
jdkRt "net.corda:deterministic-rt:$deterministic_rt_version"
2019-11-05 13:44:18 +00:00
deterministic project ( path: ':core-deterministic' , configuration: 'deterministicArtifacts' )
deterministic project ( path: ':serialization-deterministic' , configuration: 'deterministicArtifacts' )
deterministic project ( ':serialization-djvm:deserializers' )
deterministic project ( ':node:djvm' )
deterministic "org.slf4j:slf4j-nop:$slf4j_version"
2019-05-15 15:40:12 +00:00
testImplementation "org.junit.jupiter:junit-jupiter-api:${junit_jupiter_version}"
2019-05-20 10:57:56 +00:00
testImplementation "junit:junit:$junit_version"
2019-05-15 15:40:12 +00:00
2019-05-20 10:57:56 +00:00
testRuntimeOnly "org.junit.vintage:junit-vintage-engine:${junit_vintage_version}"
2019-05-15 15:40:12 +00:00
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junit_jupiter_version}"
testRuntimeOnly "org.junit.platform:junit-platform-launcher:${junit_platform_version}"
2019-05-20 10:57:56 +00:00
2016-05-14 16:57:41 +00:00
// Unit testing helpers.
2016-07-04 14:34:45 +00:00
testCompile "org.assertj:assertj-core:${assertj_version}"
2019-07-09 09:09:21 +00:00
testCompile project ( ':node-driver' )
2017-01-06 09:42:04 +00:00
testCompile project ( ':test-utils' )
2017-03-21 19:45:12 +00:00
testCompile project ( ':client:jfx' )
2018-12-19 18:02:51 +00:00
testCompile project ( ':finance:contracts' )
testCompile project ( ':finance:workflows' )
2016-08-24 13:57:52 +00:00
2017-06-22 09:35:49 +00:00
// sample test schemas
2018-12-19 18:02:51 +00:00
testCompile project ( path: ':finance:contracts' , configuration: 'testArtifacts' )
2017-06-22 09:35:49 +00:00
2016-08-02 16:06:36 +00:00
// For H2 database support in persistence
2017-03-20 10:27:45 +00:00
compile "com.h2database:h2:$h2_version"
2016-08-02 16:06:36 +00:00
// SQL connection pooling library
2019-02-20 11:28:32 +00:00
compile "com.zaxxer:HikariCP:${hikari_version}"
2016-09-08 14:28:04 +00:00
2016-09-27 14:17:27 +00:00
// Hibernate: an object relational mapper for writing state objects to the database automatically.
2017-01-03 14:15:23 +00:00
compile "org.hibernate:hibernate-core:$hibernate_version"
compile "org.hibernate:hibernate-java8:$hibernate_version"
2016-09-27 14:17:27 +00:00
2017-01-12 14:35:40 +00:00
// OkHTTP: Simple HTTP library.
compile "com.squareup.okhttp3:okhttp:$okhttp_version"
2017-12-11 08:39:09 +00:00
// Apache Shiro: authentication, authorization and session management.
compile "org.apache.shiro:shiro-core:${shiro_version}"
2018-07-27 17:25:22 +00:00
//Picocli for command line interface
compile "info.picocli:picocli:$picocli_version"
2016-09-08 14:28:04 +00:00
// Integration test helpers
2017-01-03 14:15:23 +00:00
integrationTestCompile "junit:junit:$junit_version"
2017-06-14 13:26:06 +00:00
integrationTestCompile "org.assertj:assertj-core:${assertj_version}"
2020-07-02 08:20:23 +00:00
integrationTestCompile "org.apache.qpid:qpid-jms-client:${protonj_version}"
2019-01-09 15:52:42 +00:00
// BFT-Smart dependencies
compile 'com.github.bft-smart:library:master-v1.1-beta-g6215ec8-87'
2019-11-01 09:05:12 +00:00
compile 'commons-codec:commons-codec:1.13'
2019-01-09 15:52:42 +00:00
// Java Atomix: RAFT library
compile 'io.atomix.copycat:copycat-client:1.2.3'
compile 'io.atomix.copycat:copycat-server:1.2.3'
compile 'io.atomix.catalyst:catalyst-netty:1.1.2'
2017-10-23 10:46:24 +00:00
// Jetty dependencies for NetworkMapClient test.
// Web stuff: for HTTP[S] servlets
testCompile "org.eclipse.jetty:jetty-servlet:${jetty_version}"
testCompile "org.eclipse.jetty:jetty-webapp:${jetty_version}"
2019-06-13 09:15:13 +00:00
testCompile "javax.servlet:javax.servlet-api:${servlet_version}"
2017-10-23 10:46:24 +00:00
// Jersey for JAX-RS implementation for use in Jetty
testCompile "org.glassfish.jersey.core:jersey-server:${jersey_version}"
testCompile "org.glassfish.jersey.containers:jersey-container-servlet-core:${jersey_version}"
testCompile "org.glassfish.jersey.containers:jersey-container-jetty-http:${jersey_version}"
2017-12-08 16:27:12 +00:00
2018-03-08 09:06:12 +00:00
// Jolokia JVM monitoring agent, required to push logs through slf4j
2018-03-07 13:12:15 +00:00
compile "org.jolokia:jolokia-jvm:${jolokia_version}:agent"
2018-08-09 07:11:17 +00:00
// Optional New Relic JVM reporter, used to push metrics to the configured account associated with a newrelic.yml configuration. See https://mvnrepository.com/artifact/com.palominolabs.metrics/metrics-new-relic
2018-08-09 17:17:20 +00:00
compile "com.palominolabs.metrics:metrics-new-relic:${metrics_new_relic_version}"
2019-12-18 16:54:39 +00:00
// Adding native SSL library to allow using native SSL with Artemis and AMQP
compile "io.netty:netty-tcnative-boringssl-static:$tcnative_version"
2019-09-18 09:26:26 +00:00
// Required by JVMAgentUtil (x-compatible java 8 & 11 agent lookup mechanism)
compile files ( "${System.properties['java.home']}/../lib/tools.jar" )
CORDA-3194 Wrap state transition exceptions and add flow hospital error handling for them (#2542)
Wrap exceptions that occur in state machine transitions with a custom exception type which is
then handled inside of the flow hospital. As part of this change, a number of side negative side
effects have been addressed.
General summary:
- `StateTransitionException` wraps exceptions caught in `TransitionExecutorImpl`
- `StateTransitionExceptions` are handled in the flow hospital, retried 3 times and then kept in
for observation if errors persist (assuming conditions below are false)
- Exceptions that occur in `FlowAsyncOperation` events are wrapped in
`AsyncOperationTransitionException` and ignored by the flow hospital transition staff member
- `InterruptException`s are given a `TERMINAL` diagnosis by the flow hospital transition staff
member (can occur due to `killFlow`)
- Allow flows which have not persisted their original checkpoint to still retry by replaying their
start flow messages
- Swallow exceptions in `AcknowledgeMessages` actions
Detailed summary:
* CORDA-3194 Add state machine transition error handling to flow hospital
Wrap exceptions that are caught in `TransitionExecutorImpl` (coming from
new errors) with `StateTransitionException`. This exception is then
handled explicitly by the flow hospital.
Add `TransitionErrorGeneralPractitioner` to `StaffedFlowHospital`. This
staff member handles errors that mention `StateTransitionException`.
Errors are retried and then kept in the hospital if the errors persist.
* CORDA-3194 Remove a fiber from the `hospitalisedFlows` if its previous state was clean
If the fiber's previous state was clean then remove it from
`HospitalisingInterceptor.hospitalisedFlows`. This allows flows that are
being retried to clean themselves. Doing this allows them to re-enter
the flow hospital after executing the fiber's transition (if an error
occurs).
This is important for retrying a flow that has errored during a
transition.
* CORDA-3194 Set `isAnyCheckpointPersisted` to true when retrying a flow
Added to prevent a single flow from creating multiple checkpoints when
a failure occurs during `Action.AcknowledgeMessages`.
More specifically, to `isAnyCheckpointPersisted` is false when retrying
the flow, even though a checkpoint has actually been saved. Due to this
a brand new flow is started with a new flow id (causing duplication).
Setting `isAnyCheckpointPersisted` to true specifically when retrying a
flow resolves this issue.
* CORDA-3194 Add Byteman test to verify transition error handling
Add `StatemachineErrorHandlingTest` to verify transition error handling.
Byteman allows exceptions to be injected at certain points in the code's
execution. Therefore exceptions can be thrown when needed inside of the
state machine.
The current tests check errors in events:
- `InitiateFlow`
- `AcknowledgeMessages`
* CORDA-3194 Swallow all exceptions in `ActionExecutorImpl.executeAcknowledgeMessages`
Swallow the exceptions that occur in the `DeduplicationHandler`s when
inside of `ActionExecutorImpl.executeAcknowledgeMessages`.
The side effects of the failures that can happen in the handlers are
not serious enough to put the transition into a failure state.
Therefore they are now caught. This allows the transition to continue
as normal, even if an error occurs in one any of the handlers.
* CORDA-3194 Wrap unexpected exceptions thrown in async operation transitions
Exceptions thrown inside of `FlowAsyncOperation.execute` implementations
that are not returned as part of the future, are caught, wrapped and
rethrown. This prevents unexpected exceptions thrown by (most likely)
user code from being handled by the hospital by the transition
staff member.
This handling might change moving forward, but it allows the async
operation to continue working as it was before transition error handling
was added.
* CORDA-3194 Verify that errors inside of `AcknowledgeMessages` work as expected
Update `StatemachineErrorHandlingTest` to correctly test errors that
occur when executing the `AcknowledgeMessages` action.
* CORDA-3194 Retry flows that failed to persist their original checkpoint
Allow a flow that failed when creating their original checkpoint (for
example - failing to commit the db transaction) to retry.
The flow will create a brand new checkpoint (as the original did not
saved).
This required adding `flowId` to `ExternalStartFlowEvent` to allow the
event to keep a record of the flow's id. When the flow is retried, the
events are replayed which trigger a flow to be started that has the
id stored in the event.
To allow this change, code was removed from `retryFlowFromSafePoint` to
allow the function to continue, even if no checkpoint matches the passed
in flow id.
* CORDA-3194 Correct `FlowFrameworkTests` test due to error handling
Test assumed that errors in transitions are not retried, this has now
been updated so the test passes with the flow succeeding after an
exception is thrown.
* CORDA-3194 Remove unneeded import
* CORDA-3194 Make the state transition exceptions extend `CordaException`
`StateTransitionException` and `AsyncOperationTransitionException` now
extend `CordaException` instead of `Exception`.
* CORDA-3194 Improve log messages
* CORDA-3194 Remove unneeded code in `HospitalisingInterceptor`
Due to a previous change, a section of code that removes a flow id
from the `hospitalisedFlows` map is no longer required. This code has
been removed.
* CORDA-3194 Constraint violations are given `TERMINAL` diagnosis
Add `Diagnosis.TERMINAL` to `StaffedFlowHospital` to allow an error
to be ignored and left to die a quick and painful death.
`StateTransitionException` changed so it does not cause serialisation
errors when propagated from a flow.
* CORDA-3194 `InterruptedExceptions` are given `TERMINAL` diagnosis
2019-09-23 08:31:38 +00:00
// Byteman for runtime (termination) rules injection on the running node
// Submission tool allowing to install rules on running nodes
2020-05-04 13:08:38 +00:00
slowIntegrationTestCompile "org.jboss.byteman:byteman-submit:4.0.11"
CORDA-3194 Wrap state transition exceptions and add flow hospital error handling for them (#2542)
Wrap exceptions that occur in state machine transitions with a custom exception type which is
then handled inside of the flow hospital. As part of this change, a number of side negative side
effects have been addressed.
General summary:
- `StateTransitionException` wraps exceptions caught in `TransitionExecutorImpl`
- `StateTransitionExceptions` are handled in the flow hospital, retried 3 times and then kept in
for observation if errors persist (assuming conditions below are false)
- Exceptions that occur in `FlowAsyncOperation` events are wrapped in
`AsyncOperationTransitionException` and ignored by the flow hospital transition staff member
- `InterruptException`s are given a `TERMINAL` diagnosis by the flow hospital transition staff
member (can occur due to `killFlow`)
- Allow flows which have not persisted their original checkpoint to still retry by replaying their
start flow messages
- Swallow exceptions in `AcknowledgeMessages` actions
Detailed summary:
* CORDA-3194 Add state machine transition error handling to flow hospital
Wrap exceptions that are caught in `TransitionExecutorImpl` (coming from
new errors) with `StateTransitionException`. This exception is then
handled explicitly by the flow hospital.
Add `TransitionErrorGeneralPractitioner` to `StaffedFlowHospital`. This
staff member handles errors that mention `StateTransitionException`.
Errors are retried and then kept in the hospital if the errors persist.
* CORDA-3194 Remove a fiber from the `hospitalisedFlows` if its previous state was clean
If the fiber's previous state was clean then remove it from
`HospitalisingInterceptor.hospitalisedFlows`. This allows flows that are
being retried to clean themselves. Doing this allows them to re-enter
the flow hospital after executing the fiber's transition (if an error
occurs).
This is important for retrying a flow that has errored during a
transition.
* CORDA-3194 Set `isAnyCheckpointPersisted` to true when retrying a flow
Added to prevent a single flow from creating multiple checkpoints when
a failure occurs during `Action.AcknowledgeMessages`.
More specifically, to `isAnyCheckpointPersisted` is false when retrying
the flow, even though a checkpoint has actually been saved. Due to this
a brand new flow is started with a new flow id (causing duplication).
Setting `isAnyCheckpointPersisted` to true specifically when retrying a
flow resolves this issue.
* CORDA-3194 Add Byteman test to verify transition error handling
Add `StatemachineErrorHandlingTest` to verify transition error handling.
Byteman allows exceptions to be injected at certain points in the code's
execution. Therefore exceptions can be thrown when needed inside of the
state machine.
The current tests check errors in events:
- `InitiateFlow`
- `AcknowledgeMessages`
* CORDA-3194 Swallow all exceptions in `ActionExecutorImpl.executeAcknowledgeMessages`
Swallow the exceptions that occur in the `DeduplicationHandler`s when
inside of `ActionExecutorImpl.executeAcknowledgeMessages`.
The side effects of the failures that can happen in the handlers are
not serious enough to put the transition into a failure state.
Therefore they are now caught. This allows the transition to continue
as normal, even if an error occurs in one any of the handlers.
* CORDA-3194 Wrap unexpected exceptions thrown in async operation transitions
Exceptions thrown inside of `FlowAsyncOperation.execute` implementations
that are not returned as part of the future, are caught, wrapped and
rethrown. This prevents unexpected exceptions thrown by (most likely)
user code from being handled by the hospital by the transition
staff member.
This handling might change moving forward, but it allows the async
operation to continue working as it was before transition error handling
was added.
* CORDA-3194 Verify that errors inside of `AcknowledgeMessages` work as expected
Update `StatemachineErrorHandlingTest` to correctly test errors that
occur when executing the `AcknowledgeMessages` action.
* CORDA-3194 Retry flows that failed to persist their original checkpoint
Allow a flow that failed when creating their original checkpoint (for
example - failing to commit the db transaction) to retry.
The flow will create a brand new checkpoint (as the original did not
saved).
This required adding `flowId` to `ExternalStartFlowEvent` to allow the
event to keep a record of the flow's id. When the flow is retried, the
events are replayed which trigger a flow to be started that has the
id stored in the event.
To allow this change, code was removed from `retryFlowFromSafePoint` to
allow the function to continue, even if no checkpoint matches the passed
in flow id.
* CORDA-3194 Correct `FlowFrameworkTests` test due to error handling
Test assumed that errors in transitions are not retried, this has now
been updated so the test passes with the flow succeeding after an
exception is thrown.
* CORDA-3194 Remove unneeded import
* CORDA-3194 Make the state transition exceptions extend `CordaException`
`StateTransitionException` and `AsyncOperationTransitionException` now
extend `CordaException` instead of `Exception`.
* CORDA-3194 Improve log messages
* CORDA-3194 Remove unneeded code in `HospitalisingInterceptor`
Due to a previous change, a section of code that removes a flow id
from the `hospitalisedFlows` map is no longer required. This code has
been removed.
* CORDA-3194 Constraint violations are given `TERMINAL` diagnosis
Add `Diagnosis.TERMINAL` to `StaffedFlowHospital` to allow an error
to be ignored and left to die a quick and painful death.
`StateTransitionException` changed so it does not cause serialisation
errors when propagated from a flow.
* CORDA-3194 `InterruptedExceptions` are given `TERMINAL` diagnosis
2019-09-23 08:31:38 +00:00
// The actual Byteman agent which should only be in the classpath of the out of process nodes
2020-05-04 13:08:38 +00:00
slowIntegrationTestCompile "org.jboss.byteman:byteman:4.0.11"
CORDA-3194 Wrap state transition exceptions and add flow hospital error handling for them (#2542)
Wrap exceptions that occur in state machine transitions with a custom exception type which is
then handled inside of the flow hospital. As part of this change, a number of side negative side
effects have been addressed.
General summary:
- `StateTransitionException` wraps exceptions caught in `TransitionExecutorImpl`
- `StateTransitionExceptions` are handled in the flow hospital, retried 3 times and then kept in
for observation if errors persist (assuming conditions below are false)
- Exceptions that occur in `FlowAsyncOperation` events are wrapped in
`AsyncOperationTransitionException` and ignored by the flow hospital transition staff member
- `InterruptException`s are given a `TERMINAL` diagnosis by the flow hospital transition staff
member (can occur due to `killFlow`)
- Allow flows which have not persisted their original checkpoint to still retry by replaying their
start flow messages
- Swallow exceptions in `AcknowledgeMessages` actions
Detailed summary:
* CORDA-3194 Add state machine transition error handling to flow hospital
Wrap exceptions that are caught in `TransitionExecutorImpl` (coming from
new errors) with `StateTransitionException`. This exception is then
handled explicitly by the flow hospital.
Add `TransitionErrorGeneralPractitioner` to `StaffedFlowHospital`. This
staff member handles errors that mention `StateTransitionException`.
Errors are retried and then kept in the hospital if the errors persist.
* CORDA-3194 Remove a fiber from the `hospitalisedFlows` if its previous state was clean
If the fiber's previous state was clean then remove it from
`HospitalisingInterceptor.hospitalisedFlows`. This allows flows that are
being retried to clean themselves. Doing this allows them to re-enter
the flow hospital after executing the fiber's transition (if an error
occurs).
This is important for retrying a flow that has errored during a
transition.
* CORDA-3194 Set `isAnyCheckpointPersisted` to true when retrying a flow
Added to prevent a single flow from creating multiple checkpoints when
a failure occurs during `Action.AcknowledgeMessages`.
More specifically, to `isAnyCheckpointPersisted` is false when retrying
the flow, even though a checkpoint has actually been saved. Due to this
a brand new flow is started with a new flow id (causing duplication).
Setting `isAnyCheckpointPersisted` to true specifically when retrying a
flow resolves this issue.
* CORDA-3194 Add Byteman test to verify transition error handling
Add `StatemachineErrorHandlingTest` to verify transition error handling.
Byteman allows exceptions to be injected at certain points in the code's
execution. Therefore exceptions can be thrown when needed inside of the
state machine.
The current tests check errors in events:
- `InitiateFlow`
- `AcknowledgeMessages`
* CORDA-3194 Swallow all exceptions in `ActionExecutorImpl.executeAcknowledgeMessages`
Swallow the exceptions that occur in the `DeduplicationHandler`s when
inside of `ActionExecutorImpl.executeAcknowledgeMessages`.
The side effects of the failures that can happen in the handlers are
not serious enough to put the transition into a failure state.
Therefore they are now caught. This allows the transition to continue
as normal, even if an error occurs in one any of the handlers.
* CORDA-3194 Wrap unexpected exceptions thrown in async operation transitions
Exceptions thrown inside of `FlowAsyncOperation.execute` implementations
that are not returned as part of the future, are caught, wrapped and
rethrown. This prevents unexpected exceptions thrown by (most likely)
user code from being handled by the hospital by the transition
staff member.
This handling might change moving forward, but it allows the async
operation to continue working as it was before transition error handling
was added.
* CORDA-3194 Verify that errors inside of `AcknowledgeMessages` work as expected
Update `StatemachineErrorHandlingTest` to correctly test errors that
occur when executing the `AcknowledgeMessages` action.
* CORDA-3194 Retry flows that failed to persist their original checkpoint
Allow a flow that failed when creating their original checkpoint (for
example - failing to commit the db transaction) to retry.
The flow will create a brand new checkpoint (as the original did not
saved).
This required adding `flowId` to `ExternalStartFlowEvent` to allow the
event to keep a record of the flow's id. When the flow is retried, the
events are replayed which trigger a flow to be started that has the
id stored in the event.
To allow this change, code was removed from `retryFlowFromSafePoint` to
allow the function to continue, even if no checkpoint matches the passed
in flow id.
* CORDA-3194 Correct `FlowFrameworkTests` test due to error handling
Test assumed that errors in transitions are not retried, this has now
been updated so the test passes with the flow succeeding after an
exception is thrown.
* CORDA-3194 Remove unneeded import
* CORDA-3194 Make the state transition exceptions extend `CordaException`
`StateTransitionException` and `AsyncOperationTransitionException` now
extend `CordaException` instead of `Exception`.
* CORDA-3194 Improve log messages
* CORDA-3194 Remove unneeded code in `HospitalisingInterceptor`
Due to a previous change, a section of code that removes a flow id
from the `hospitalisedFlows` map is no longer required. This code has
been removed.
* CORDA-3194 Constraint violations are given `TERMINAL` diagnosis
Add `Diagnosis.TERMINAL` to `StaffedFlowHospital` to allow an error
to be ignored and left to die a quick and painful death.
`StateTransitionException` changed so it does not cause serialisation
errors when propagated from a flow.
* CORDA-3194 `InterruptedExceptions` are given `TERMINAL` diagnosis
2019-09-23 08:31:38 +00:00
2018-09-14 13:37:52 +00:00
testCompile ( project ( ':test-cli' ) )
2019-01-04 15:42:11 +00:00
testCompile ( project ( ':test-utils' ) )
2019-09-03 15:40:08 +00:00
slowIntegrationTestCompile sourceSets . main . output
slowIntegrationTestCompile sourceSets . test . output
slowIntegrationTestCompile configurations . compile
slowIntegrationTestCompile configurations . testCompile
slowIntegrationTestRuntime configurations . runtime
slowIntegrationTestRuntime configurations . testRuntime
2019-10-02 08:46:33 +00:00
testCompile project ( ':testing:cordapps:dbfailure:dbfworkflows' )
2016-05-14 16:57:41 +00:00
}
2018-09-13 09:55:52 +00:00
tasks . withType ( JavaCompile ) {
// Resolves a Gradle warning about not scanning for pre-processors.
2019-05-20 15:16:49 +00:00
options . compilerArgs < < '-proc:none'
2018-09-13 09:55:52 +00:00
}
2019-09-18 09:26:26 +00:00
tasks . withType ( Test ) {
2019-11-05 13:44:18 +00:00
if ( JavaVersion . current ( ) = = JavaVersion . VERSION_11 ) {
2019-09-18 09:26:26 +00:00
jvmArgs '-Djdk.attach.allowAttachSelf=true'
2019-11-05 13:44:18 +00:00
}
systemProperty 'deterministic-rt.path' , configurations . jdkRt . asPath
systemProperty 'deterministic-sources.path' , configurations . deterministic . asPath
2019-09-18 09:26:26 +00:00
}
2016-09-08 14:28:04 +00:00
task integrationTest ( type: Test ) {
2017-08-24 15:46:54 +00:00
testClassesDirs = sourceSets . integrationTest . output . classesDirs
2016-09-08 14:28:04 +00:00
classpath = sourceSets . integrationTest . runtimeClasspath
2019-09-03 15:40:08 +00:00
maxParallelForks = ( System . env . CORDA_NODE_INT_TESTING_FORKS = = null ) ? 1 : "$System.env.CORDA_NODE_INT_TESTING_FORKS" . toInteger ( )
}
task slowIntegrationTest ( type: Test ) {
testClassesDirs = sourceSets . slowIntegrationTest . output . classesDirs
classpath = sourceSets . slowIntegrationTest . runtimeClasspath
maxParallelForks = 1
2017-01-03 14:15:23 +00:00
}
2017-06-06 14:05:47 +00:00
2019-05-30 09:09:11 +00:00
// quasar exclusions upon agent code instrumentation at run-time
quasar {
2019-11-05 13:44:18 +00:00
excludeClassLoaders . addAll (
2020-03-18 13:59:10 +00:00
'net.corda.djvm.**' ,
'net.corda.core.serialization.internal.**'
2019-11-05 13:44:18 +00:00
)
2019-05-30 09:09:11 +00:00
excludePackages . addAll (
"antlr**" ,
"com.codahale**" ,
"com.fasterxml.**" ,
"com.github.benmanes.caffeine.**" ,
"com.google.**" ,
"com.lmax.**" ,
"com.zaxxer.**" ,
2019-11-05 13:44:18 +00:00
"djvm**" ,
2019-05-30 09:09:11 +00:00
"net.bytebuddy**" ,
"io.github.classgraph**" ,
"io.netty*" ,
"liquibase**" ,
2019-11-05 13:44:18 +00:00
"net.corda.djvm**" ,
2019-05-30 09:09:11 +00:00
"net.i2p.crypto.**" ,
"nonapi.io.github.classgraph.**" ,
"org.apiguardian.**" ,
"org.bouncycastle**" ,
"org.codehaus.**" ,
"org.h2**" ,
"org.hibernate**" ,
"org.jboss.**" ,
"org.objenesis**" ,
"org.w3c.**" ,
"org.xml**" ,
"org.yaml**" ,
"rx**" )
}
2017-06-06 14:05:47 +00:00
jar {
baseName 'corda-node'
2020-05-26 14:46:29 +00:00
exclude 'sandbox/java/**'
exclude 'sandbox/org/**'
exclude 'sandbox/net/corda/core/crypto/SecureHash.class'
exclude 'sandbox/net/corda/core/crypto/SignatureScheme.class'
exclude 'sandbox/net/corda/core/crypto/TransactionSignature.class'
2019-11-05 13:44:18 +00:00
manifest {
attributes ( 'Corda-Deterministic-Runtime' : configurations . jdkRt . singleFile . name )
attributes ( 'Corda-Deterministic-Classpath' : configurations . deterministic . collect { it . name } . join ( ' ' ) )
}
2017-06-06 14:05:47 +00:00
}
publish {
2017-07-18 11:34:56 +00:00
name jar . baseName
2019-05-16 14:15:38 +00:00
}
2019-09-03 15:40:08 +00:00
test {
maxHeapSize = "3g"
maxParallelForks = ( System . env . CORDA_NODE_TESTING_FORKS = = null ) ? 1 : "$System.env.CORDA_NODE_TESTING_FORKS" . toInteger ( )
2019-11-05 13:44:18 +00:00
}