Querying flow data

As a node operator, you can query a node to retrieve flow checkpoint data which can help you in managing your node.

A checkpoint is a record of flow data taken at key points during a flow’s operation, typically whenever the flow is suspended and waiting for a response or message. Querying this checkpoint data enables you to inspect the status of any flows being executed on your node and can assist you in troubleshooting issues that may arise in relation to flows.

With Corda Enterprise, you can query flow data in the following ways:

Corda Enterprise exposes a number of custom, remote RPC interfaces, which enable you to interact with your node. For a list of all the remote interfaces that are available in Corda Enterprise, see Building a Multi RPC Client.

The net.corda.client.rpc.proxy.NodeFlowStatusRpcOps interface is an RPC extension which enables external applications to query and view the status of the flows which are currently being monitored by the Flow Hospital.

To use the net.corda.client.rpc.proxy.NodeFlowStatusRpcOps interface to query flow status via RPC, you need to complete the following steps:

  1. Build a Multi RPC client - see Building a Multi RPC Client.
  2. Specify the search criteria for the query - see Specifying the query criteria.

To be able to use the net.corda.client.rpc.proxy.NodeFlowStatusRpcOps interface to interact with your node and query flow status via RPC, you must build a Multi RPC Client that uses the NodeFlowStatusRpcOps::class.java interface class for communication. The following code snippet provides an example of how to do this:

val rpcAddress = NetworkHostAndPort("nodeAddress", 1000)
val client = MultiRPCClient(rpcAddress, NodeFlowStatusRpcOps::class.java, rpcUser.username, rpcUser.password)
val connFuture = client.start()
val conn = connFuture.get()
val flowStatusRPCOPs = conn.proxy

To view the full code sample, see NodeFlowStatusRpcOps.kt.

For details of how to build a Multi RPC Client, see Building a Multi RPC Client. See also MultiRPCClient in the API documentation.

To return flow checkpoint data via RPC, you must specify your search criteria.

Including one or more search criteria will enable you to identify flows that did not complete and where:

  • The flow is or is not compatible with the current Corda runtime environment.
  • The flow relates to a particular CorDapp.
  • The flow class name includes a particular string fragment.
  • The flow was executed within a specific time window.
  • The flow is in a particular state.
  • The flow did not proceed beyond a specific progress step.
  • The flow remained stuck at a checkpoint for a particular length of time.

The available search parameters and their required formats are outlined in the table below.

Parameter nameDescriptionFormat
flowClassThe name of the class that implements the flow. You do not need to enter the full name - providing a fragment of the class name is enough to identify the class. The * regex operator is applied to the start and end of the fragment.String
flowStateThe state of the flow at its latest checkpoint. The state is one of the following values: RUNNABLE, FAILED, COMPLETED, HOSPITALIZED, KILLED, PAUSED.Enum
progressStepIf the flow implements progress tracking, specifies the latest step that was encountered before checkpointing. A progressStep is a user-defined value which is defined by the CorDapp developer - you can specify the name of any progressStep defined in your CorDapp. The * regex operator is applied to the start and end of the fragment.String
cordappThe name of the CorDapp that contains the flow. You do not need to enter the full name - providing a fragment of the name is enough to identify the CorDapp. The * regex operator is applied to the start and end of the fragment.String
compatibleWithCurrentCordaRuntimeIndicates whether the suspended flow is compatible with and can be loaded on the current Corda runtime environment.Boolean String
suspensionDurationThe minimum duration for which a flow must have remained suspended (that is, “stuck”) at a checkpoint.java.time.Duration
flowStartUses the net.corda.core.contracts.TimeWindow class to define an open or closed time window for when the flow was first started. The start time of the time-window in which the flow was started. A start-open window will return all flows started before the Unix 0 Instant (that is, the time 00:00 on January 1, 1970). An end-open window will return all flows started after a given time and before the current Instant. All times specified are inclusive.net.corda.core.contracts.TimeWindow

The code example below shows how you can define a query that will return all flows that have not completed as expected and which meet the following criteria:

  • The flow belongs to the IssueToken flow class.
  • The flow’s state is RUNNABLE.
  • The flow is at the progress step called SIGNING.
  • The flow belongs to the tokens-workflows CorDapp.
  • The flow is compatible with and can be loaded on the current Corda runtime environment.
  • The flow has remained suspended for at least 10 minutes.
  • The flow started in the last 30 minutes.
val rpcAddress = NetworkHostAndPort("nodeAddress", 1000)
val client = MultiRPCClient(rpcAddress, NodeFlowStatusRpcOps::class.java, rpcUser.username, rpcUser.password)
val connFuture = client.start()
val conn = connFuture.get()
val flowStatusRPCOPs = conn.proxy

val matchingFlows: List<String>  = flowStatusRPCOPs.getFlowsMatching(FlowStatusQuery(
    flowClass = "IssueToken",
    flowState = FlowState.RUNNABLE,
    progressStep = "SIGNING",
    cordapp = "tokens-workflows",
    compatibleWithCurrentCordaRuntime = true,
    suspensionDuration = Duration.ofMinutes(10),
    flowStart = TimeWindow.between(Instant.now().minus(30, ChronoUnit.MINUTES), Instant.now())
    )
)
matchingFlows.forEach { flowId ->
    println(flowStatusRPCOPs.getFlowStatus(flowId))
}

NodeFlowStatusRpcOps.kt

When this query is executed, a list of the flow IDs for all flows that did not complete and which meet the search criteria is returned. For each flow ID, the status of the specified flow is also returned.

To query the node for flow data via the Node Shell, you must use the flowStatus query command.

You can use the flowStatus query command, in combination with one or more parameters, to retrieve various types of flow data from the node’s checkpoints.

You can use the flowStatus command to return a list of all flows on a node that have not completed. To do this, run the following query:

flowStatus queryFlows

A list consisting of the flow IDs of all flows on the node that have not completed is returned.

The flow ID belonging to each flow is listed on a separate line, as shown in the example below:

5da55b82-332f-4ecd-a20c-3b02be040bb7
4dc21e46-142g-7rbt-b56i-2k41mr701lb2

You can view a subset of all flows that did not complete by including specific search criteria in your query. You do this by combining the flowStatus queryFlows query command with one of more of the parameters shown in the table below.

Including one or more search criteria will enable you to identify flows that did not complete and where:

  • The flow is or is not compatible with the current Corda runtime environment.
  • The flow relates to a particular CorDapp.
  • The flow includes a particular flow class.
  • The flow was executed within a specific time window.
  • The flow is in a particular state.
  • The flow did not proceed beyond a specific progress step.
  • The flow remained stuck at a checkpoint for a particular length of time.

The available search parameters and their required formats are outlined in the table below.

Parameter nameDescriptionFormat
compatibleWithCurrentCordaRuntimeIndicates whether the suspended flow is compatible with and can be loaded on the current Corda runtime environment.Boolean String
cordappThe name of the CorDapp that contains the flow. You do not need to enter the full name - providing a fragment of the name is enough to identify the CorDapp.String
flowClassThe name of the class that implements the flow. You do not need to enter the full name - providing a fragment of the class name is enough to identify the class.String
flowStartFromThe start time of the time-window in which the flow was started. If you do not specify a start time value, the start time is taken to be a UNIX 0 timestamp (that is, the time 00:00 on January 1, 1970). If you specify a value for flowStartFrom but do not specify a value for flowStartUntil, the query will return a list of all flows that did not complete up until the time that the query was run.String in ISO8601 DateTime format*.
flowStartUntilThe end time of the time-window in which the flow was started. If you specify a value for flowStartUntil but do not specify a value for flowStartFrom, the query will return a list of all flows that did not complete since the node started up.String in ISO8601 DateTime format*.
flowStateThe state of the flow at its latest checkpoint. The state is one of the following values: RUNNABLE, FAILED, COMPLETED, HOSPITALIZED, KILLED, PAUSED.String
progressStepIf the flow implements progress tracking, specifies the latest step that was encountered before checkpointing. A progressStep is a user-defined value which is defined by the CorDapp developer - you can specify the name of any progressStep defined in your CorDapp.String
suspensionDurationThe minimum duration for which a flow must have remained suspended (that is, “stuck”) at a checkpoint. This is entered in the format "<value>, <unit>" where <value> is a numerical value and <unit> is the unit of time, specified as SECONDS, MINUTES, HOURS or DAYS).String

* See Sample query to view all suspended flows within a particular time-window.

To return specific information about a flow, a query must contain the following elements:

  • The query command: flowStatus queryFlows.
  • One or more parameters from the above table. These parameters define the data that is returned from each checkpoint.

If you run the query without including any specific search criteria, a list consisting only of the flow IDs of all flows on the node that have not completed is returned, as outlined under View all flows that have not completed.

To return a list of all flows that have not completed and are in a particular state (in this example, the HOSPITALIZED state), run the following query:

flowStatus queryFlows flowState: HOSPITALIZED

To return a list of all flows that have not completed and which relate to a particular flow class (in this example, the HospitalizerFlow class), run the following query:

flowStatus queryFlows flowClass: HospitalizerFlow

When specifying time-windows, all dates and times must be specified in accordance with the ISO 8601 standard as follows:

yyyy-MM-ddTHH:mm:ss

For example, to specify a flowStartFrom time of 08:45:56 on July 21, 2020, you must enter the time in the following format:

2020-07-21T08:45:56

You can create a query for an open or closed time-window.

To return a list of all flows that did not complete within a closed time-window, specify both a start time and end time for the time-window as follows:

flowStatus queryFlows flowStartFrom: 2020-05-16T09:30:00 flowStartUntil: 2020-05-17T09:30:00

The following query is an example of an open time-window, where only the start-time of the time-window is specified:

flowStatus queryFlows flowStartFrom: 2020-05-16T09:30:00

If running a query for an open-ended time-window, note the following:

  • If you specify a value for flowStartFrom but do not specify a value for flowStartUntil, the query will return a list of all flows that did not complete up until the time that the query was run.

  • If you specify a value for flowStartUntil but do not specify a value for flowStartFrom, the query will return a list of all flows that did not complete since the node started up.

To return a list of all flows that have been suspended (that is, “stuck”) for a certain minimum period of time, specify a value for suspensionDuration. Specifying a value for suspensionDuration filters out flows that have not been suspended for at least this duration.

This option is particularly useful if, for example, you want to identify all flows that have been stuck for a certain period of time or if you want to exclude flows that have been executed recently from the results returned. For example, if you know that a flow takes a certain amount of time to execute, you may wish to check for flows that have not completed that have been stuck for a period of time that is longer than the normal execution period.

To specify the suspensionDuration, enter the value in the format "<value>, <unit>" where <value> is a numerical value and <unit> is the unit of time, specified as SECONDS, MINUTES, HOURS or DAYS.

To return a list of all flows that have not completed and which have been stuck a certain minimum period of time (in this example, at least 2 hours), run the following query:

flowStatus queryFlows suspensionDuration: "2, HOURS"

You can combine multiple search criteria in a single query. For example, you could combine the two sample queries described in Sample query to view all suspended flows in a particular state and Sample query to view all suspended flows in a particular class into a single query as follows:

flowStatus queryFlows flowState: HOSPITALIZED flowClass: HospitalizerFlow

You can also construct more complex queries, such as the following:

flowStatus queryFlows compatibleWithCurrentCordaRuntime: true cordapp: custom-cordapp flowClass: Hospitalizer suspensionDuration: "5, MINUTES"

In this example, flow data will be returned for flows that have not completed and which also meet all of the following conditions:

  • The flow is compatible with the current Corda runtime environment.
  • The flow exists in the CorDapp called custom-cordapp.
  • The flow belongs to the Hospitalizer class.
  • The flow has been suspended for five minutes or more.

If you want to obtain a summary of checkpoint data relating to one or more suspended flows, you can use the flowStatus query command, in combination with the queryById field.

For example, to return summary data for the flow which has the flow ID 5da55b82-332f-4ecd-a20c-3b02be040bb7, you would structure your query as follows:

flowStatus queryById 5da55b82-332f-4ecd-a20c-3b02be040bb7

Running this query returns the following checkpoint data for the flow:

flowStatus queryById 5da55b82-332f-4ecd-a20c-3b02be040bb7
---
- flowId: "5da55b82-332f-4ecd-a20c-3b02be040bb7"
  flowClass: "net.corda.failingflows.workflows.HospitalizerFlow"
  flowState: "HOSPITALIZED"
  cordappContext:
    cordappName: "custom-cordapp_1_7_6732caa5-99b8-4b95-a935-bde44bc65172"
    cordaVersion: 7
  compatibleWithCurrentCordaRuntime: true
  progressStep: null
  invocationContext:
    invocationSource: "RPC"
    userName: null
    initiatingParty: null
    userSuppliedInformation: null
  suspensionMetadata: null
  flowStart: 1595323327.416000000
  lastCheckpoint: 1595323327.481000000

You can return summary data for one or more flows in a single query.

To return data for more than one flow, specify the flow IDs of the relevant flows in the following format:

flowStatus queryById flowId1 flowId2

For example, let’s say you want to return summary data for following two flows:

  • Flow ID of the first flow: 5da55b82-332f-4ecd-a20c-3b02be040bb7
  • Flow ID of the second flow: 4dc21e46-142g-7rbt-b56i-2k41mr701lb2

To do this, you would structure your query as follows, listing each flow ID, separated by a space:

flowStatus queryById 5da55b82-332f-4ecd-a20c-3b02be040bb7 4dc21e46-142g-7rbt-b56i-2k41mr701lb2

You can view a list of all arguments relating to the flowStatus command by entering the following command:

flowStatus --help

A list of all possible options is returned.

Was this page helpful?

Thanks for your feedback!

Chat with us

Chat with us on our #docs channel on slack. You can also join a lot of other slack channels there and have access to 1-on-1 communication with members of the R3 team and the online community.

Propose documentation improvements directly

Help us to improve the docs by contributing directly. It's simple - just fork this repository and raise a PR of your own - R3's Technical Writers will review it and apply the relevant suggestions.

We're sorry this page wasn't helpful. Let us know how we can make it better!

Chat with us

Chat with us on our #docs channel on slack. You can also join a lot of other slack channels there and have access to 1-on-1 communication with members of the R3 team and the online community.

Create an issue

Create a new GitHub issue in this repository - submit technical feedback, draw attention to a potential documentation bug, or share ideas for improvement and general feedback.

Propose documentation improvements directly

Help us to improve the docs by contributing directly. It's simple - just fork this repository and raise a PR of your own - R3's Technical Writers will review it and apply the relevant suggestions.