diff --git a/client/rpc/src/main/kotlin/net/corda/client/rpc/CordaRPCClient.kt b/client/rpc/src/main/kotlin/net/corda/client/rpc/CordaRPCClient.kt index a6c97c3e3a..199cdd6d67 100644 --- a/client/rpc/src/main/kotlin/net/corda/client/rpc/CordaRPCClient.kt +++ b/client/rpc/src/main/kotlin/net/corda/client/rpc/CordaRPCClient.kt @@ -9,10 +9,12 @@ import net.corda.nodeapi.ConnectionDirection import net.corda.nodeapi.config.SSLConfiguration import java.time.Duration +/** @see RPCClient.RPCConnection */ class CordaRPCConnection internal constructor( connection: RPCClient.RPCConnection ) : RPCClient.RPCConnection by connection +/** @see RPCClientConfiguration */ data class CordaRPCClientConfiguration( val connectionMaxRetryInterval: Duration ) { @@ -29,6 +31,7 @@ data class CordaRPCClientConfiguration( } } +/** @see RPCClient */ class CordaRPCClient( hostAndPort: HostAndPort, sslConfiguration: SSLConfiguration? = null, diff --git a/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClient.kt b/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClient.kt index 60d50928bd..93b7d52107 100644 --- a/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClient.kt +++ b/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClient.kt @@ -114,9 +114,9 @@ class RPCClient( * * The [RPCOps] defines what client RPCs are available. If an RPC returns an [Observable] anywhere in the object * graph returned then the server-side observable is transparently forwarded to the client side here. - * *You are expected to use it*. The server will begin buffering messages immediately that it will expect you to - * drain by subscribing to the returned observer. You can opt-out of this by simply calling the - * [net.corda.client.rpc.notUsed] method on it. You don't have to explicitly close the observable if you actually + * *You are expected to use it*. The server will begin sending messages immediately that will be buffered on the + * client, you are expected to drain by subscribing to the returned observer. You can opt-out of this by simply + * calling the [net.corda.client.rpc.notUsed] method on it. You don't have to explicitly close the observable if you actually * subscribe to it: it will close itself and free up the server-side resources either when the client or JVM itself * is shutdown, or when there are no more subscribers to it. Once all the subscribers to a returned observable are * unsubscribed or the observable completes successfully or with an error, the observable is closed and you can't diff --git a/docs/make-docsite.sh b/docs/make-docsite.sh index 36865fdcd1..8c2488ca04 100755 --- a/docs/make-docsite.sh +++ b/docs/make-docsite.sh @@ -11,4 +11,4 @@ else source virtualenv/Scripts/activate fi -make html \ No newline at end of file +make html diff --git a/docs/source/clientrpc.rst b/docs/source/clientrpc.rst index 1b1a44803e..98eeaee197 100644 --- a/docs/source/clientrpc.rst +++ b/docs/source/clientrpc.rst @@ -6,14 +6,15 @@ compatible language the easiest way to do so is using the client library. The li node using a message queue protocol and then provides a simple RPC interface to interact with it. You make calls on a Java object as normal, and the marshalling back and forth is handled for you. -The starting point for the client library is the `CordaRPCClient`_ class. This provides a ``proxy`` method that -returns an implementation of the `CordaRPCOps`_ interface. A timeout parameter can be specified, and observables that -are returned by RPCs can be subscribed to in order to receive an ongoing stream of updates from the node. More -detail on how to use this is provided in the docs for the proxy method. +The starting point for the client library is the `CordaRPCClient`_ class. This provides a ``start`` method that +returns a `CordaRPCConnection`_, holding an implementation of the `CordaRPCOps`_ interface named ``proxy``. +Observables that are returned by RPCs can be subscribed to in order to receive an ongoing stream of updates from +the node. More detail on how to use this is provided in the docs for the proxy method. -.. warning:: The returned object is somewhat expensive to create and consumes a small amount of server side - resources. When you're done with it, cast it to ``Closeable`` or ``AutoCloseable`` and close it. Don't create - one for every call you make - create a proxy and reuse it. +.. warning:: The returned `CordaRPCConnection`_ is somewhat expensive to create and consumes a small amount of + server side resources. When you're done with it, call ``close`` on it. Alternatively you may use the ``use`` + method on `CordaRPCClient`_ which cleans up automatically after the passed in lambda finishes. Don't create + a new proxy for every call you make - reuse an existing one. For a brief tutorial on how one can use the RPC API see :doc:`tutorial-clientrpc-api`. @@ -34,25 +35,21 @@ The returned observable may even emit object graphs with even more observables i would expect. This feature comes with a cost: the server must queue up objects emitted by the server-side observable until you -download them. Therefore RPCs that use this feature are marked with the ``@RPCReturnsObservables`` annotation, and -you are expected to subscribe to all the observables returned. If you don't want an observable then subscribe -then unsubscribe immediately to clear the buffers and indicate that you aren't interested. If your app quits then -server side resources will be freed automatically. +download them. Note that the server side observation buffer is bounded, once it fills up the client is considered +slow and kicked. You are expected to subscribe to all the observables returned, otherwise client-side memory starts +filling up as observations come in. If you don't want an observable then subscribe then unsubscribe immediately to +clear the client-side buffers and to stop the server from streaming. If your app quits then server side resources +will be freed automatically. -When all the observables returned by an RPC are unsubscribed on the client side, that unsubscription propagates -through to the server where the corresponding server-side observables are also unsubscribed. - -.. warning:: If you leak an observable or proxy on the client side and it gets garbage collected, you will get - a warning printed to the logs and the proxy will be closed for you. But don't rely on this, as garbage - collection is non-deterministic. +.. warning:: If you leak an observable on the client side and it gets garbage collected, you will get a warning + printed to the logs and the observable will be unsubscribed for you. But don't rely on this, as garbage collection + is non-deterministic. Futures ------- A method can also return a ``ListenableFuture`` in its object graph and it will be treated in a similar manner to -observables, including needing to mark the RPC with the ``@RPCReturnsObservables`` annotation. Unlike for an observable, -once the single value (or an exception) has been received all server-side resources will be released automatically. Calling -the ``cancel`` method on the future will unsubscribe it from any future value and release any resources. +observables. Calling the ``cancel`` method on the future will unsubscribe it from any future value and release any resources. Versioning ---------- @@ -66,13 +63,9 @@ of, an ``UnsupportedOperationException`` is thrown. If you want to know the vers Thread safety ------------- -A proxy is thread safe, blocking, and will only allow a single RPC to be in flight at once. Any observables that -are returned and you subscribe to will have objects emitted on a background thread. Observables returned as part -of one RPC and observables returned from another may have their callbacks invoked in parallel, but observables -returned as part of the same specific RPC invocation are processed serially and will not be invoked in parallel. - -If you want to make multiple calls to the server in parallel you can do that by creating multiple proxies, but -be aware that the server itself may *not* process your work in parallel even if you make your requests that way. +A proxy is thread safe, blocking, and allows multiple RPCs to be in flight at once. Any observables that are returned and +you subscribe to will have objects emitted in order on a background thread pool. Each Observable stream is tied to a single +thread, however note that two separate Observables may invoke their respective callbacks on different threads. Error handling -------------- @@ -85,8 +78,7 @@ side as if it was thrown from inside the called RPC method. These exceptions can Wire protocol ------------- -The client RPC wire protocol is not currently documented. To use it you must use the client library provided. -This is likely to change in a future release. +The client RPC wire protocol is defined and documented in ``net/corda/client/rpc/RPCApi.kt``. Whitelisting classes with the Corda node ---------------------------------------- @@ -98,5 +90,6 @@ with the annotation ``@CordaSerializable``. See :doc:`creating-a-cordapp` or :d .. warning:: We will be replacing the use of Kryo in the serialization framework and so additional changes here are likely. -.. _CordaRPCClient: api/kotlin/corda/net.corda.client.rpc/-corda-r-p-c-client/index.html -.. _CordaRPCOps: api/kotlin/corda/net.corda.core.messaging/-corda-r-p-c-ops/index.html +.. _CordaRPCClient: api/javadoc/net/corda/client/rpc/CordaRPCClient.html +.. _CordaRPCOps: api/javadoc/net/corda/core/messaging/CordaRPCOps.html +.. _CordaRPCConnection: api/javadoc/net/corda/client/rpc/CordaRPCConnection.html