ENT-1968: Add RPC for refreshing network map cache (#3552)

ENT-1968: Add RPC for refreshing network map cache
This commit is contained in:
Katarzyna Streich
2018-07-12 13:40:33 +01:00
committed by GitHub
parent f4a248f81f
commit b275f4349a
4 changed files with 42 additions and 8 deletions

View File

@ -34,13 +34,13 @@ import java.time.Instant
*/ */
@CordaSerializable @CordaSerializable
data class StateMachineInfo @JvmOverloads constructor( data class StateMachineInfo @JvmOverloads constructor(
/** A univerally unique ID ([java.util.UUID]) representing this particular instance of the named flow. */ /** A universally unique ID ([java.util.UUID]) representing this particular instance of the named flow. */
val id: StateMachineRunId, val id: StateMachineRunId,
/** The JVM class name of the flow code. */ /** The JVM class name of the flow code. */
val flowLogicClassName: String, val flowLogicClassName: String,
/** /**
* An object representing information about the initiator of the flow. Note that this field is * An object representing information about the initiator of the flow. Note that this field is
* superceded by the [invocationContext] property, which has more detail. * superseded by the [invocationContext] property, which has more detail.
*/ */
@Deprecated("There is more info available using 'context'") val initiator: FlowInitiator, @Deprecated("There is more info available using 'context'") val initiator: FlowInitiator,
/** A [DataFeed] of the current progress step as a human readable string, and updates to that string. */ /** A [DataFeed] of the current progress step as a human readable string, and updates to that string. */
@ -368,9 +368,24 @@ interface CordaRPCOps : RPCOps {
*/ */
fun nodeInfoFromParty(party: AbstractParty): NodeInfo? fun nodeInfoFromParty(party: AbstractParty): NodeInfo?
/** Clear all network map data from local node cache. */ /**
* Clear all network map data from local node cache. Notice that after invoking this method your node will lose
* network map data and effectively won't be able to start any flow with the peers until network map is downloaded
* again on next poll - from `additional-node-infos` directory or from network map server. It depends on the
* polling interval when it happens. You can also use [refreshNetworkMapCache] to force next fetch from network map server
* (not from directory - it will happen automatically).
* If you run local test deployment and want clear view of the network, you may want to clear also `additional-node-infos`
* directory, because cache can be repopulated from there.
*/
fun clearNetworkMapCache() fun clearNetworkMapCache()
/**
* Poll network map server if available for the network map. Notice that you need to have `compatibilityZone`
* or `networkServices` configured. This is normally done automatically on the regular time interval, but you may wish to
* have the fresh view of network earlier.
*/
fun refreshNetworkMapCache()
/** Sets the value of the node's flows draining mode. /** Sets the value of the node's flows draining mode.
* If this mode is [enabled], the node will reject new flows through RPC, ignore scheduled flows, and do not process * If this mode is [enabled], the node will reject new flows through RPC, ignore scheduled flows, and do not process
* initial session messages, meaning that P2P counterparties will not be able to initiate new flows involving the node. * initial session messages, meaning that P2P counterparties will not be able to initiate new flows involving the node.

View File

@ -1,6 +1,7 @@
package net.corda.node.internal package net.corda.node.internal
import net.corda.client.rpc.notUsed import net.corda.client.rpc.notUsed
import net.corda.core.CordaRuntimeException
import net.corda.core.concurrent.CordaFuture import net.corda.core.concurrent.CordaFuture
import net.corda.core.context.InvocationContext import net.corda.core.context.InvocationContext
import net.corda.core.context.InvocationOrigin import net.corda.core.context.InvocationOrigin
@ -48,6 +49,7 @@ import net.corda.nodeapi.exceptions.NonRpcFlowException
import net.corda.nodeapi.exceptions.RejectedCommandException import net.corda.nodeapi.exceptions.RejectedCommandException
import rx.Observable import rx.Observable
import java.io.InputStream import java.io.InputStream
import java.net.ConnectException
import java.security.PublicKey import java.security.PublicKey
import java.time.Instant import java.time.Instant
@ -232,6 +234,17 @@ internal class CordaRPCOpsImpl(
services.networkMapCache.clearNetworkMapCache() services.networkMapCache.clearNetworkMapCache()
} }
override fun refreshNetworkMapCache() {
try {
services.networkMapUpdater.updateNetworkMapCache()
} catch (e: Exception) {
when (e) {
is ConnectException -> throw CordaRuntimeException("There is connection problem to network map. The possible causes are incorrect configuration or network map service being down")
else -> throw e
}
}
}
override fun <T : ContractState> vaultQuery(contractStateType: Class<out T>): Vault.Page<T> { override fun <T : ContractState> vaultQuery(contractStateType: Class<out T>): Vault.Page<T> {
return vaultQueryBy(QueryCriteria.VaultQueryCriteria(), PageSpecification(), Sort(emptySet()), contractStateType) return vaultQueryBy(QueryCriteria.VaultQueryCriteria(), PageSpecification(), Sort(emptySet()), contractStateType)
} }

View File

@ -36,8 +36,6 @@ internal class ExceptionSerialisingRpcOpsProxy(private val delegate: CordaRPCOps
val result = super.invoke(proxy, method, arguments) val result = super.invoke(proxy, method, arguments)
return result?.let { ensureSerialisable(it) } return result?.let { ensureSerialisable(it) }
} catch (exception: Exception) { } catch (exception: Exception) {
// In this special case logging and re-throwing is the right approach.
log(exception)
throw ensureSerialisable(exception) throw ensureSerialisable(exception)
} }
} }
@ -80,7 +78,13 @@ internal class ExceptionSerialisingRpcOpsProxy(private val delegate: CordaRPCOps
private fun ensureSerialisable(error: Throwable): Throwable { private fun ensureSerialisable(error: Throwable): Throwable {
val serialisable = (superclasses(error::class.java) + error::class.java).any { it.isAnnotationPresent(CordaSerializable::class.java) || it.interfaces.any { it.isAnnotationPresent(CordaSerializable::class.java) } } val serialisable = (superclasses(error::class.java) + error::class.java).any { it.isAnnotationPresent(CordaSerializable::class.java) || it.interfaces.any { it.isAnnotationPresent(CordaSerializable::class.java) } }
val result = if (serialisable) error else CordaRuntimeException(error.message, error) val result = if (serialisable) {
error
} else {
log(error)
CordaRuntimeException(error.message, error)
}
if (result is CordaThrowable) { if (result is CordaThrowable) {
result.stackTrace = arrayOf<StackTraceElement>() result.stackTrace = arrayOf<StackTraceElement>()
result.setCause(null) result.setCause(null)

View File

@ -1,6 +1,7 @@
package net.corda.node.services.network package net.corda.node.services.network
import com.google.common.util.concurrent.MoreExecutors import com.google.common.util.concurrent.MoreExecutors
import net.corda.core.CordaRuntimeException
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.SignedData import net.corda.core.crypto.SignedData
import net.corda.core.internal.copyTo import net.corda.core.internal.copyTo
@ -86,7 +87,7 @@ class NetworkMapUpdater(private val networkMapCache: NetworkMapCacheInternal,
executor.submit(object : Runnable { executor.submit(object : Runnable {
override fun run() { override fun run() {
val nextScheduleDelay = try { val nextScheduleDelay = try {
updateNetworkMapCache(networkMapClient) updateNetworkMapCache()
} catch (t: Throwable) { } catch (t: Throwable) {
logger.warn("Error encountered while updating network map, will retry in $defaultRetryInterval", t) logger.warn("Error encountered while updating network map, will retry in $defaultRetryInterval", t)
defaultRetryInterval defaultRetryInterval
@ -97,7 +98,8 @@ class NetworkMapUpdater(private val networkMapCache: NetworkMapCacheInternal,
}) // The check may be expensive, so always run it in the background even the first time. }) // The check may be expensive, so always run it in the background even the first time.
} }
private fun updateNetworkMapCache(networkMapClient: NetworkMapClient): Duration { fun updateNetworkMapCache(): Duration {
if (networkMapClient == null) throw CordaRuntimeException("Network map cache can be updated only if network map/compatibility zone URL is specified")
val (globalNetworkMap, cacheTimeout) = networkMapClient.getNetworkMap() val (globalNetworkMap, cacheTimeout) = networkMapClient.getNetworkMap()
globalNetworkMap.parametersUpdate?.let { handleUpdateNetworkParameters(networkMapClient, it) } globalNetworkMap.parametersUpdate?.let { handleUpdateNetworkParameters(networkMapClient, it) }
val additionalHashes = extraNetworkMapKeys.flatMap { val additionalHashes = extraNetworkMapKeys.flatMap {