* [EG-438] First commit of error code interface
* [EG-438] Implement error reporter and a few error codes
* [EG-438] Add unit tests and default properties files
* [EG-438] Add the error table builder
* [EG-438] Update initial properties files
* [EG-438] Add some Irish tests and the build.gradle
* [EG-438] Fall back for aliases and use different resource strategy
* [EG-438] Define the URL using a project-specific context
* [EG-438] Tidy up initialization code
* [EG-438] Add testing to generator and tidy up
* [EG-438] Remove direct dependency on core and add own logging config
* [EG-438] Fix compiler warnings and tidy up logging
* [EG-438] Fix detekt warnings
* [EG-438] Improve error messages
* [EG-438] Address first set of review comments
* [EG-438] Use enums and a builder for the reporter
* [EG-438] Add kdocs for error resource static methods
* [EG-438] Handle enums defined with underscores
* [EG-438] Slight refactoring of startup code
* [EG-438] Port changes to error reporting code from future branch
* [EG-438] Also port test changes
* [EG-438] Suppress a deliberately unused parameter
* CORDA-3722 withEntityManager can rollback its session
## Summary
Improve the handling of database transactions when using
`withEntityManager` inside a flow.
Extra changes have been included to improve the safety and
correctness of Corda around handling database transactions.
This focuses on allowing flows to catch errors that occur inside an
entity manager and handle them accordingly.
Errors can be caught in two places:
- Inside `withEntityManager`
- Outside `withEntityManager`
Further changes have been included to ensure that transactions are
rolled back correctly.
## Catching errors inside `withEntityManager`
Errors caught inside `withEntityManager` require the flow to manually
`flush` the current session (the entity manager's individual session).
By manually flushing the session, a `try-catch` block can be placed
around the `flush` call, allowing possible exceptions to be caught.
Once an error is thrown from a call to `flush`, it is no longer possible
to use the same entity manager to trigger any database operations. The
only possible option is to rollback the changes from that session.
The flow can continue executing updates within the same session but they
will never be committed. What happens in this situation should be handled
by the flow. Explicitly restricting the scenario requires a lot of effort
and code. Instead, we should rely on the developer to control complex
workflows.
To continue updating the database after an error like this occurs, a new
`withEntityManager` block should be used (after catching the previous
error).
## Catching errors outside `withEntityManager`
Exceptions can be caught around `withEntityManager` blocks. This allows
errors to be handled in the same way as stated above, except the need to
manually `flush` the session is removed. `withEntityManager` will
automatically `flush` a session if it has not been marked for rollback
due to an earlier error.
A `try-catch` can then be placed around the whole of the
`withEntityManager` block, allowing the error to be caught while not
committing any changes to the underlying database transaction.
## Savepoints / Transactionality
To make `withEntityManager` blocks work like mini database transactions,
save points have been utilised. A new savepoint is created when opening
a `withEntityManager` block (along with a new session). It is then used
as a reference point to rollback to if the session errors and needs to
roll back. The savepoint is then released (independently from
completing successfully or failing).
Using save points means, that either all the statements inside the
entity manager are executed, or none of them are.
## Some implementation details
- A new session is created every time an entity manager is requested,
but this does not replace the flow's main underlying database session.
- `CordaPersistence.transaction` can now determine whether it needs
to execute its extra error handling code. This is needed to allow errors
escape `withEntityManager` blocks while allowing some of our exception
handling around subscribers (in `NodeVaultService`) to continue to work.
* CORDA-3762: Integration test exposing the problem reported
* CORDA-3726: Additional logging
* CORDA-3726: Prevent thread leaks
* CORDA-3726: New `journalBufferTimeout` parameter
* CORDA-3726: Override `journalBufferTimeout` parameter
* CORDA-3726: Making Detekt happier
* CORDA-3276: Account for extra thread user in MockNetwork
For real node this does not matter as `shutdown` can safely be called multiple times, which is not true for server thread provided by MockNetwork
* CORDA-3276: Do not make SMM shutdown "executor" as it belongs to AbstractNode
* CORDA-3276: Address input from @rick-r3
* CORDA-3276: Fix test after rebase
* CORDA-3701 Fix bugs in some iterator checkpoint serializers
* Added some more tests and tidied up implementation some more.
* Fix imports to be detekt compliant
* Add timeouts to tests
* adding blocked functions ro RestrictedEntityManager and creating RestrictedConnection class
* adding flow tests and fixing issues regarding the review
* adding quasar util to gradle
* updating flow tests
* adding space before } at .isThrownBy()
* adding spaces
the current code doesn't forward the exception to the logging system, this means that any cause inside the exception is lost as with all of the stacktraces (both the one of the thrown exception and the one belonging to its cause).
The correct way to log an exception is to pass both the message and the exception to the logging system.
* CORDA-3690: Changed algorithm name used in signature from ECDSA to EC. JDK11 checks with in key generation.
* CORDA-3690: Remove the SHA512WITHSPHINCS256 signature scheme from the generate key pair and sign test.
* CORDA-3690: Algorithm in SignatureScheme has changed to EC from ECDSA so change test to match.
Co-authored-by: Adel El-Beik <adelel-beik@19LDN-MAC108.local>
* Introduce CordaSessionFactoryFactory interface and the H2 implememntation
* Load SessionFactoryFactory via service loader
* Add Postgres SessionFactoryFactory
* Add extraConfiguration function for SessionFactoryFactory implementations to expose special config values.
* Run serialisation tests with both in-process and out-of-process nodes.
* Add custom serialisers and whitelists to Driver's AMQPServerSerializationScheme.
* Split out node-api tests that require test-utils/node-driver
* Add node-api test artefacts to publication list.
* Make test-common a transient dependency - downstream tests assume that it's available.
* Switch dependencies to java-library
* Fix magic package name for cordapp scanning in test
* Remove unused dependencies from test-common
* Explicit imports and formatting
* Add core-test-utils project
* Add dependency
* Move Kryo serialization context to node-api (not serialization as we do not want to pull kryo into the serialization lib)
* Move AMQP server serialization scheme to node api
* Move serialization tests to node-api
* Move internal test helpers without further dependencies.
* Move out some types from RPCClientProxyHandler to node-api in preparation for moving the AMQP scheme
* Move client AMQP context to node-api so we can move the test serialization rule out.
* Move InternalSerializationTestHelpers to core-test-utils
* Moved testing.core to core-test-utils
* Make detekt happy
* Add api-scanner to core-test-utils
* Remove inlined package names introduced by IntelliJ refactoring
* Update api-current.txt to account for reordering.
* Add core-test-utils to list of published artifacts.
* Add missing import
* Location of things in api text has moved again (publish name of artefact?)
* Revert all additions to the API, leaving just the reordering
* Code review: fix up core-test-utils build.gradle and introduce kryo version constant.
* Remove OpenSsl flag from ssl config stub (can't be used from node-api)
* Suppress detekt warning
* Move core test util tests to the right module
* Expose kotlin test as a transient dependency - projects have come to rely on that.
* Fix typo in package name
* CORDA-3565: `ServiceStateSupport` and supporting classes
* CORDA-3565:Plug `ServiceLifecycleSupport` into `MessagingService`
* CORDA-3565: Detekt baseline update
* CORDA-3565: React to MessagingServer going up and addition logging for up/down
Co-authored-by: Matthew Nesbit <matthew.nesbit@r3.com>
Observers registered on NodeVaultService#rawUpdates, if they throw an exception when called from serviceHub#recordTransactions and if this exception is not handled by the flow hospital, then this leads to the transaction not being recorded in the local vault. This could get the ledger in an out of sync state.
In the specific case this happens within FinalityFlow#notariseAndRecord this leads to the transaction being notarized but not recorded in the local vault nor broadcasted in any counter party. The -failed to be recorded locally- transaction and its output states are not visible to any vault, and its input states not able to consumed by a new transaction, since they are recorded as consumed within the Notary. In this specific case we need not loose, by any means, the current transaction.
We will handle all cases by catching all exceptions thrown from serviceHub#recordTransactions, wrapping them with a HospitalizeFlowException and throwing it instead. The flow will get to the hospital for observation to be retried from previous checkpoint on next node restart.
* CORDA-3549: Improve stability of `CordaServiceLifecycleFatalTests`
* CORDA-3549: Bump-up reps count to ensure that test is definitely not flaky when executed by CI
(once proved the number of reps will be reduced)
* CORDA-3549: Making Detekt happier
* CORDA-2942: Ensure `NodeLifecycleEventsDistributor` cleans-up smoothly when node shuts down
* CORDA-2942: Port minimal set of changes to make lifecycle events work
... and make codebase compile.
* CORDA-2942: Undo some changes which are not strictly speaking necessary
* CORDA-2942: Make `NodeServicesContext` leaner and delete `extensions-api` module
* CORDA-2942: Reduce even more number of files affected
* CORDA-2942: Integration test fix
* CORDA-2942: Make events `AfterStart` and `BeforeStop` generic w.r.t. `NodeServicesContext`
* CORDA-2942: `NodeLifecycleObserverService` and a set of integration tests.
Public API violations are expected as well as integration tests failing.
* CORDA-2942: Re-work to introduce `ServiceLifecycleObserver`
* CORDA-2942: Explicitly mention a type of exception that may be thrown for some events.
* CORDA-2942: Register `ServiceLifecycleObserver` through `AppServiceHub`
* CORDA-2942: Fix integration test + KDocs update
* CORDA-2942: Detekt and `api-current` update
* CORDA-2942: Improvement to `CordaServiceLifecycleFatalTests`
... or else it has side effects on other tests.
* CORDA-2942: Add an integration test for new API use in Java
Driver test is written in Kotlin, but services definition is written in Java.
Also KDocs improvements.
* CORDA-2942: Documentation and release notes update
* CORDA-2942: First set of changes following review by @mnesbit
* CORDA-2942: Second set of changes following review by @mnesbit
* CORDA-2942: Added multi-threaded test
* CORDA-2942: Fixes
* CORDA-2942: Undo changes to `api-current.txt`
* CORDA-2942: Bare mimimum change to `api-current.txt` for CI gate to pass.
* CORDA-2942: Address review feedback from @rick-r3
* CORDA-2942: Detekt update
* CORDA-2942: Delete `ServiceLifecycleObserverPriority` and replace it with `Int` after discussion with @mnesbit
* CORDA-2942: Introduce more `NodeLifecycleEvent` and switch services to listen for those events
* CORDA-2942: Few more changes after input from @rick-r3
* First stub on integration test
Unfinished - hang on issue and pay
* CORDA-2942: Switch to use out-of-process nodes for the inetgration test
Currently Alice and Notary stuck waiting to hear from each other.
* CORDA-2942: Extra log lines during event distribution
* CORDA-2942: Asynchronously distribute lifecycle events
* CORDA-2942: Await for complete P2P client start-up
Next step: Add vault query to integration test
* CORDA-2942: Asynchronously distribute lifecycle events
Next step: Improve integration test
* CORDA-2942: Fix test broken by recent changes and improve logging
* CORDA-2942: Improvement of the test to be able to monitor actions performed by @CordaService in the remote process
* CORDA-2942: Add node re-start step to the integration test
* CORDA-2942: Remove `CORDAPP_STOPPED` event for now
* CORDA-2942: s/CORDAPP_STARTED/STATE_MACHINE_STARTED/
* CORDA-2942: Inverse the meaning of `priority` as requested by @rick-r3
* CORDA-2942: Register `AppServiceHubImpl` for lifecycle events and put a warning when SMM is not ready.
* Harmonize serialization/core and deterministic counterparts
* Fix test for changed private alias key behaviour
* Detekt errors
* roll back project.xml
* CORDA-3471: Create `CordaTransactionSupport` and use wherever possible instead of `CordaPersistence`
* CORDA-3471: Address comments by @mnesbit
- Relocate `CordaTransactionSupport` to `core`
- Create a lighter version of transaction - `VaultTransaction` that gives access to `session` object only.
* CORDA-3471: More changes after discussion with @mnesbit
- Rename `VaultTransaction` into `SessionScope`.
* CORDA-3471: Revert changes to most of the files after conversation with @mnesbit and @rick-r3
* CORDA-3471: Introduce `CordaTransactionSupportImpl` and make it accessible via `AppServiceHub`.
* CORDA-3471: Minor change (comment).
* CORDA-3471: Address input from @mnesbit
* CORDA-3471: Address input from @rick-r3
* CORDA-3471: Make Detekt happier
* CORDA-3471: Add a new test that proves transactions can be started from client threads
As requested by @mnesbit
* CORDA-3471: Change log and documentation update.
As requested by @mnesbit
* Unwrap rx.OnErrorNotImplementedException so the hospital can handle the cause appropriately
* Add db failure cordapp
* Renamed folders to avoid ambiguity in gradle
* Add integration test for exception hospitalisation when thrown from an RX observable.
* Make the test slightly cleaner
* Fix the schema to actually match the requirements for my custom state. Thanks a bunch, H2.
* Switch test to use SqlException base class.
* Schedule error event if we detect that a commit or db flush has thrown (forcing the flow to error even if customer code then goes ahead to swallow the exception)
* Revert change to schedule extra error
* Add more tests for edge case with DB exceptions, changed CorDapp to suppor this an hook in the flow hospital
* Warning about unsubscribe
Check state transitioned from clean to error for hospital admission.
* Match the test to our actual expectations
* Revert "Revert change to schedule extra error"
This reverts commit 43d47937
* Prevent suppression of errors arising in `transaction()` and `jdbcConnection()`
* Test for SqlException caught trying to escape from recordTransaction and suppressed outside being intercepted.
* More tests for various error/catch combinations
* Clean up and comments
* Code reformat
* Fix test compilation