CORDA-3918: Port of ENT-5417: Allow exceptions to propagate when shutdown commands are called (#6516)

This commit is contained in:
Ryan Fowler 2020-07-27 14:09:26 +01:00 committed by Ryan Fowler
parent bfcd1d8791
commit a5a0c64e2d
2 changed files with 16 additions and 13 deletions

View File

@ -292,6 +292,7 @@ class ReconnectingCordaRPCOps private constructor(
} }
private class ErrorInterceptingHandler(val reconnectingRPCConnection: ReconnectingRPCConnection) : InvocationHandler { private class ErrorInterceptingHandler(val reconnectingRPCConnection: ReconnectingRPCConnection) : InvocationHandler {
private fun Method.isStartFlow() = name.startsWith("startFlow") || name.startsWith("startTrackedFlow") private fun Method.isStartFlow() = name.startsWith("startFlow") || name.startsWith("startTrackedFlow")
private fun Method.isShutdown() = name == "shutdown" || name == "gracefulShutdown" || name == "terminate"
private fun checkIfIsStartFlow(method: Method, e: InvocationTargetException) { private fun checkIfIsStartFlow(method: Method, e: InvocationTargetException) {
if (method.isStartFlow()) { if (method.isStartFlow()) {
@ -306,7 +307,7 @@ class ReconnectingCordaRPCOps private constructor(
* *
* A negative number for [maxNumberOfAttempts] means an unlimited number of retries will be performed. * A negative number for [maxNumberOfAttempts] means an unlimited number of retries will be performed.
*/ */
@Suppress("ThrowsCount", "ComplexMethod") @Suppress("ThrowsCount", "ComplexMethod", "NestedBlockDepth")
private fun doInvoke(method: Method, args: Array<out Any>?, maxNumberOfAttempts: Int): Any? { private fun doInvoke(method: Method, args: Array<out Any>?, maxNumberOfAttempts: Int): Any? {
checkIfClosed() checkIfClosed()
var remainingAttempts = maxNumberOfAttempts var remainingAttempts = maxNumberOfAttempts
@ -318,21 +319,21 @@ class ReconnectingCordaRPCOps private constructor(
log.debug { "RPC $method invoked successfully." } log.debug { "RPC $method invoked successfully." }
} }
} catch (e: InvocationTargetException) { } catch (e: InvocationTargetException) {
if (method.name.equals("shutdown", true)) {
log.debug("Shutdown invoked, stop reconnecting.", e)
reconnectingRPCConnection.notifyServerAndClose()
break
}
when (e.targetException) { when (e.targetException) {
is RejectedCommandException -> { is RejectedCommandException -> {
log.warn("Node is being shutdown. Operation ${method.name} rejected. Retrying when node is up...", e) log.warn("Node is being shutdown. Operation ${method.name} rejected. Retrying when node is up...", e)
reconnectingRPCConnection.reconnectOnError(e) reconnectingRPCConnection.reconnectOnError(e)
} }
is ConnectionFailureException -> { is ConnectionFailureException -> {
if (method.isShutdown()) {
log.debug("Shutdown invoked, stop reconnecting.", e)
reconnectingRPCConnection.notifyServerAndClose()
} else {
log.warn("Failed to perform operation ${method.name}. Connection dropped. Retrying....", e) log.warn("Failed to perform operation ${method.name}. Connection dropped. Retrying....", e)
reconnectingRPCConnection.reconnectOnError(e) reconnectingRPCConnection.reconnectOnError(e)
checkIfIsStartFlow(method, e) checkIfIsStartFlow(method, e)
} }
}
is RPCException -> { is RPCException -> {
rethrowIfUnrecoverable(e.targetException as RPCException) rethrowIfUnrecoverable(e.targetException as RPCException)

View File

@ -111,6 +111,8 @@ object InteractiveShell {
YAML YAML
} }
private fun isShutdownCmd(cmd: String) = cmd == "shutdown" || cmd == "gracefulShutdown" || cmd == "terminate"
fun startShell(configuration: ShellConfiguration, classLoader: ClassLoader? = null, standalone: Boolean = false) { fun startShell(configuration: ShellConfiguration, classLoader: ClassLoader? = null, standalone: Boolean = false) {
makeRPCConnection = { username: String, password: String -> makeRPCConnection = { username: String, password: String ->
val connection = if (standalone) { val connection = if (standalone) {
@ -623,6 +625,10 @@ object InteractiveShell {
throw e.rootCause throw e.rootCause
} }
} }
if (isShutdownCmd(cmd)) {
out.println("Called 'shutdown' on the node.\nQuitting the shell now.").also { out.flush() }
onExit.invoke()
}
} catch (e: StringToMethodCallParser.UnparseableCallException) { } catch (e: StringToMethodCallParser.UnparseableCallException) {
out.println(e.message, Decoration.bold, Color.red) out.println(e.message, Decoration.bold, Color.red)
if (e !is StringToMethodCallParser.UnparseableCallException.NoSuchFile) { if (e !is StringToMethodCallParser.UnparseableCallException.NoSuchFile) {
@ -634,10 +640,6 @@ object InteractiveShell {
InputStreamSerializer.invokeContext = null InputStreamSerializer.invokeContext = null
InputStreamDeserializer.closeAll() InputStreamDeserializer.closeAll()
} }
if (cmd == "shutdown") {
out.println("Called 'shutdown' on the node.\nQuitting the shell now.").also { out.flush() }
onExit.invoke()
}
return result return result
} }