PoolBoy is an RPC connection pool with support for multiple Corda nodes.
See complete documentation at https://manosbatsis.github.io/corda-rpc-poolboy
Note this is an early release. It is highly unstable but provided in hope it can be useful. Contributions are welcome.
Add PoolBoy to your Cordapp's Gradle dependencies:
dependencies{
// PoolBoy dependency
compile("com.github.manosbatsis.corda.rpc.poolboy:corda-rpc-poolboy:$poolboy_version")
// Corda dependencies etc.
// ...
}
To use PoolBoy you will have to implement a RpcConfigurationService
.
The service provides RPC pool and connection configuration.
Implementations can be "fixed" or fully dynamic, e.g. based on
a properties file or database connection etc. respectively.
A future release will provide a sample, properties-based implementation. In the meantime you can find an example in Corbeans' default
RpcConfigurationService.
The main configuration items provided by such a service are as follows:
getRpcPoolParams()
: APoolParams
instance, in each turn specifies:rpcClientsMode
: AnRpcClientsMode
value to control theCordaRPCClient
creation strategy, one ofSHARED
,POOLED
,DEDICATED
. Default isSHARED
.rpcClientPool
: The commons-pool2 keyed configuration to use ifrpcClientsMode
is set toPOOLED
, equivalent to aGenericKeyedObjectPoolConfig
.rpcOpsPool
: The commons-pool2 keyed configuration to use forNodeRpcConnection
instances - those start and wrap aCordaRPCOps
getRpcNodeParams(String)
: Provides the RPC connection configuration (i.e.NodeParams
) corresponding to the given node key per your configuration implementation, e.g. X500 name, application.properties key, database primary key etc. Note that the implementor is solely responsible for any caching.getGracefulReconnect(NodeParams)
: Override to change theGracefulReconnect
implementation to use whenNodeParams.disableGracefulReconnect
isfalse
.getCustomSerializers(List<String>)
: Custom serializer types found in the configured cordapp packages. Override to bypass classpath scanning and improve search discovery performance.buildPoolKey(String)
: Builds aPoolKey
for the given node name. Override to customisePoolKey.externalTrace
andPoolKey.impersonatedActor
, i.e. the equivalent parameters passed toCordaRPCClient.start()
Using a full PoolBoy
:
// Create the PoolBoy instance
val poolBoy = PoolBoy(myRpcConfigurationService)
// Obtain a pool key for the target node
val poolKey = myRpcConfigurationService.buildPoolKey(nodeName)
// Do something with the CordaRPCOps
// for the given node name
poolBoy.withConnection(poolKey){
// e.g. start a flow
it.proxy.startFlow(MyFlow::class.java, foo, bar, baz)
}
Using a PoolBoyConnection
, i.e. a pooled connection
handle to a target node directly:
// Create the PoolBoy instance
val poolBoy = PoolBoy(myRpcConfigurationService)
// Obtain a pool key for the target node
val poolKey = myRpcConfigurationService.buildPoolKey(nodeName)
// Get a pool-able connection handle
val pbCconn: PoolBoyConnection = poolBoy.forKey(poolKey)
// Do something with the CordaRPCOps
// for the target node
pbCconn.withConnection {
// e.g. start a flow
it.proxy.startFlow(MyFlow::class.java, foo, bar, baz)
}
Both PoolBoy
and PoolBoyConnection
have borrowConnection()
and returnConnection()
methods, but it's highly discouraged; you'd
better know what you're doing if you use them. The withConnection
approach is preferred.