From acd2f8bce4dfaf63e28f749d0b15f43a413fb0e7 Mon Sep 17 00:00:00 2001 From: Shams Asari Date: Fri, 22 Mar 2019 14:46:02 +0000 Subject: [PATCH] CORDA-2683: Requests to start unknown flows can be deleted using killFlow (#4903) Normally, these requests are left unacknowledged in the MQ broker to allow recovery via installing the missing CorDapp. If this is not applicable then the request be dropped (and the other side informed of the error). --- .../kotlin/net/corda/node/internal/CordaRPCOpsImpl.kt | 2 +- .../node/services/statemachine/StaffedFlowHospital.kt | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/node/src/main/kotlin/net/corda/node/internal/CordaRPCOpsImpl.kt b/node/src/main/kotlin/net/corda/node/internal/CordaRPCOpsImpl.kt index ec15ef7b26..9019e0b7e3 100644 --- a/node/src/main/kotlin/net/corda/node/internal/CordaRPCOpsImpl.kt +++ b/node/src/main/kotlin/net/corda/node/internal/CordaRPCOpsImpl.kt @@ -136,7 +136,7 @@ internal class CordaRPCOpsImpl( return snapshot } - override fun killFlow(id: StateMachineRunId) = smm.killFlow(id) + override fun killFlow(id: StateMachineRunId): Boolean = if (smm.killFlow(id)) true else smm.flowHospital.dropSessionInit(id.uuid) override fun stateMachinesFeed(): DataFeed, StateMachineUpdate> { val (allStateMachines, changes) = smm.track() diff --git a/node/src/main/kotlin/net/corda/node/services/statemachine/StaffedFlowHospital.kt b/node/src/main/kotlin/net/corda/node/services/statemachine/StaffedFlowHospital.kt index bf5eaacbf1..48673989d8 100644 --- a/node/src/main/kotlin/net/corda/node/services/statemachine/StaffedFlowHospital.kt +++ b/node/src/main/kotlin/net/corda/node/services/statemachine/StaffedFlowHospital.kt @@ -55,6 +55,11 @@ class StaffedFlowHospital(private val flowMessaging: FlowMessaging, private val mutex.locked { if (outcome != Outcome.UNTREATABLE) { treatableSessionInits[id] = InternalSessionInitRecord(sessionMessage, event, record) + log.warn("$sender has sent a flow request for an unknown flow ${sessionMessage.initiatorFlowClassName}. Install the missing " + + "CorDapp this flow belongs to and restart.") + log.warn("If you know it's safe to ignore this flow request then it can be deleted permanently using the killFlow RPC and " + + "the UUID $id (from the node shell you can run 'flow kill $id'). BE VERY CAUTIOUS OF THIS SECOND APPROACH AS THE " + + "REQUEST MAY CONTAIN A NOTARISED TRANSACTION THAT NEEDS TO BE RECORDED IN YOUR VAULT.") } recordsPublisher.onNext(record) } @@ -78,12 +83,13 @@ class StaffedFlowHospital(private val flowMessaging: FlowMessaging, private val * to send back the relevant session error to the initiator party and acknowledge its receipt from the message broker * so that it never gets redelivered. */ - fun dropSessionInit(id: UUID) { + fun dropSessionInit(id: UUID): Boolean { val (sessionMessage, event, publicRecord) = mutex.locked { - requireNotNull(treatableSessionInits.remove(id)) { "$id does not refer to any session init message" } + treatableSessionInits.remove(id) ?: return false } log.info("Errored session-init permanently dropped: $publicRecord") sendBackError(publicRecord.error, sessionMessage, publicRecord.sender, event) + return true } /**