Merge remote-tracking branch 'remotes/open/master' into merges/march-13-14-55

# Conflicts:
#	build.gradle
#	docs/source/_static/versions
#	docs/source/running-a-node.rst
This commit is contained in:
sollecitom 2018-03-13 15:02:58 +00:00
commit f31afd1520
9 changed files with 91 additions and 30 deletions

View File

@ -326,6 +326,46 @@ class RPCStabilityTests {
} }
} }
interface NoOps : RPCOps {
fun subscribe(): Observable<Nothing>
}
@Test
fun `observables error when connection breaks`() {
rpcDriver {
val ops = object : NoOps {
override val protocolVersion = 0
override fun subscribe(): Observable<Nothing> {
return PublishSubject.create<Nothing>()
}
}
val serverFollower = shutdownManager.follower()
val serverPort = startRpcServer<NoOps>(ops = ops).getOrThrow().broker.hostAndPort!!
serverFollower.unfollow()
val clientConfiguration = RPCClientConfiguration.default.copy(connectionRetryInterval = 500.millis, maxReconnectAttempts = 1)
val clientFollower = shutdownManager.follower()
val client = startRpcClient<NoOps>(serverPort, configuration = clientConfiguration).getOrThrow()
clientFollower.unfollow()
var terminateHandlerCalled = false
var errorHandlerCalled = false
val subscription = client.subscribe()
.doOnTerminate{ terminateHandlerCalled = true }
.doOnError { errorHandlerCalled = true }
.subscribe()
serverFollower.shutdown()
Thread.sleep(100)
assertTrue(terminateHandlerCalled)
assertTrue(errorHandlerCalled)
assertTrue(subscription.isUnsubscribed)
clientFollower.shutdown() // Driver would do this after the new server, causing hang.
}
}
interface ThreadOps : RPCOps { interface ThreadOps : RPCOps {
fun sendMessage(id: Int, msgNo: Int): String fun sendMessage(id: Int, msgNo: Int): String
} }

View File

@ -418,6 +418,14 @@ class RPCClientProxyHandler(
when (event) { when (event) {
FailoverEventType.FAILURE_DETECTED -> { FailoverEventType.FAILURE_DETECTED -> {
log.warn("RPC server unavailable. RPC calls are being buffered.") log.warn("RPC server unavailable. RPC calls are being buffered.")
log.warn("Terminating observables.")
val m = observableContext.observableMap.asMap()
m.keys.forEach { k ->
observationExecutorPool.run(k) {
m[k]?.onError(RPCException("Connection failure detected."))
}
}
observableContext.observableMap.invalidateAll()
} }
FailoverEventType.FAILOVER_COMPLETED -> { FailoverEventType.FAILOVER_COMPLETED -> {
@ -432,8 +440,6 @@ class RPCClientProxyHandler(
"will throw an RPCException.") "will throw an RPCException.")
rpcReplyMap.forEach { id, replyFuture -> rpcReplyMap.forEach { id, replyFuture ->
replyFuture.setException(RPCException("Could not re-connect to RPC server. Failover failed.")) replyFuture.setException(RPCException("Could not re-connect to RPC server. Failover failed."))
val observable = observableContext.observableMap.getIfPresent(id)
observable?.onError(RPCException("Could not re-connect to RPC server. Failover failed."))
} }
outgoingRequestBuffer.clear() outgoingRequestBuffer.clear()
rpcReplyMap.clear() rpcReplyMap.clear()

View File

@ -118,8 +118,6 @@ dependencies {
// This may be temporary until we experiment with other ways to do on-the-fly contract specialisation via an API. // This may be temporary until we experiment with other ways to do on-the-fly contract specialisation via an API.
compile "org.apache.commons:commons-jexl3:3.0" compile "org.apache.commons:commons-jexl3:3.0"
compile 'commons-lang:commons-lang:2.6' compile 'commons-lang:commons-lang:2.6'
// For JSON
compile "com.fasterxml.jackson.core:jackson-databind:${jackson_version}"
// Java ed25519 implementation. See https://github.com/str4d/ed25519-java/ // Java ed25519 implementation. See https://github.com/str4d/ed25519-java/
compile "net.i2p.crypto:eddsa:$eddsa_version" compile "net.i2p.crypto:eddsa:$eddsa_version"

View File

@ -683,6 +683,12 @@ We then update the progress tracker's current step as we progress through the fl
:end-before: DOCEND 18 :end-before: DOCEND 18
:dedent: 12 :dedent: 12
HTTP and database calls
-----------------------
HTTP, database and other calls to external resources are allowed in flows. However, their support is currently limited:
* The call must be executed in a BLOCKING way. Flows don't currently support suspending to await the response to a call to an external resource
* The call must be idempotent. If the flow fails and has to restart from a checkpoint, the call will also be replayed
Concurrency, Locking and Waiting Concurrency, Locking and Waiting
-------------------------------- --------------------------------

View File

@ -105,7 +105,7 @@ will not be valid, and will not be accepted as inputs to subsequent transactions
Other transaction components Other transaction components
---------------------------- ----------------------------
As well as input states and output states, transactions may contain: As well as input states and output states, transactions contain:
* Commands * Commands
* Attachments * Attachments

View File

@ -8,29 +8,15 @@ Running nodes locally
There are several ways to run a Corda node locally for testing purposes. There are several ways to run a Corda node locally for testing purposes.
Starting all nodes at once Starting a Corda node using DemoBench
-------------------------- -------------------------------------
See the instructions in :doc:`demobench`.
.. note:: ``runnodes`` is a shell script (or batch file on Windows) that is generated by ``deployNodes`` to allow you
to quickly start up all nodes and their webservers. ``runnodes`` should only be used for testing purposes.
Start the nodes with ``runnodes`` by running the following command from the root of the project:
* Linux/macOS: ``build/nodes/runnodes``
* Windows: ``call build\nodes\runnodes.bat``
.. warning:: On macOS, do not click/change focus until all the node terminal windows have opened, or some processes may
fail to start.
If you receive an ``OutOfMemoryError`` exception when interacting with the nodes, you need to increase the amount of
Java heap memory available to them, which you can do when running them individually. See
:ref:`starting-an-individual-corda-node`.
.. _starting-an-individual-corda-node: .. _starting-an-individual-corda-node:
Starting an individual Corda node Starting a Corda node from the command line
--------------------------------- -------------------------------------------
Run the node by opening a terminal window in the node's folder and running: Run a node by opening a terminal window in the node's folder and running:
.. code-block:: shell .. code-block:: shell
@ -57,8 +43,8 @@ Optionally run the node's webserver as well by opening a terminal window in the
.. warning:: The node webserver is for testing purposes only and will be removed soon. .. warning:: The node webserver is for testing purposes only and will be removed soon.
Starting a node with remote debugging enabled Enabling remote debugging
--------------------------------------------- ~~~~~~~~~~~~~~~~~~~~~~~~~
To enable remote debugging of the node, run the following from the terminal window: To enable remote debugging of the node, run the following from the terminal window:
``java -Dcapsule.jvm.args="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005" -jar corda.jar`` ``java -Dcapsule.jvm.args="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005" -jar corda.jar``
@ -74,3 +60,17 @@ To enable export of JMX metrics over HTTP via `Jolokia <https://jolokia.org/>`_,
This command line will start the node with JMX metrics accessible via HTTP on port 7005. This command line will start the node with JMX metrics accessible via HTTP on port 7005.
See :ref:`Monitoring your node <jolokia_ref>` for further details. See :ref:`Monitoring your node <jolokia_ref>` for further details.
Starting all nodes at once from the command line
------------------------------------------------
If you created your nodes using ``deployNodes``, a ``runnodes`` shell script (or batch file on Windows) will have been
generated to allow you to quickly start up all nodes and their webservers. ``runnodes`` should only be used for testing
purposes.
Start the nodes with ``runnodes`` by running the following command from the root of the project:
* Linux/macOS: ``build/nodes/runnodes``
* Windows: ``call build\nodes\runnodes.bat``
.. warning:: On macOS, do not click/change focus until all the node terminal windows have opened, or some processes may
fail to start.

View File

@ -42,6 +42,9 @@ dependencies {
// TODO Remove this once we have app configs // TODO Remove this once we have app configs
compile "com.typesafe:config:$typesafe_config_version" compile "com.typesafe:config:$typesafe_config_version"
// For JSON
compile "com.fasterxml.jackson.core:jackson-databind:${jackson_version}"
testCompile project(':test-utils') testCompile project(':test-utils')
testCompile project(path: ':core', configuration: 'testArtifacts') testCompile project(path: ':core', configuration: 'testArtifacts')
testCompile "junit:junit:$junit_version" testCompile "junit:junit:$junit_version"
@ -72,6 +75,12 @@ artifacts {
jar { jar {
baseName 'corda-finance' baseName 'corda-finance'
exclude "META-INF/*.DSA"
exclude "META-INF/*.RSA"
exclude "META-INF/*.SF"
exclude "META-INF/*.MF"
exclude "META-INF/LICENSE"
exclude "META-INF/NOTICE"
} }
publish { publish {

View File

@ -61,6 +61,8 @@ dependencies {
// Pure-Java Snappy compression // Pure-Java Snappy compression
compile 'org.iq80.snappy:snappy:0.4' compile 'org.iq80.snappy:snappy:0.4'
compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version"
// Unit testing helpers. // Unit testing helpers.
testCompile "junit:junit:$junit_version" testCompile "junit:junit:$junit_version"
testCompile "org.assertj:assertj-core:$assertj_version" testCompile "org.assertj:assertj-core:$assertj_version"