← Return to Top Page 日本語

Gravio Action Flow Control Guide

Table of Contents

1. Basic Concepts of Action Flow

1.1 Component Operation Model

Gravio actions are flows composed of multiple connected components that define a sequence of data processing. Each component operates in parallel in its own thread, retrieving input Payload from its queue, processing it, generating output Payload, and posting it to the next component’s queue.

The action execution model progresses as follows:

  1. Component retrieves input Payload from its queue
  2. Executes processing based on input Payload
  3. Generates output Payload as processing result
  4. Posts output Payload to the next component’s queue
  5. Waits to retrieve the next input Payload from its queue

This sequence can be understood as a bucket relay where data is passed along. However, in reality, the same Payload isn’t passed along; each component generates a new Payload after applying its own processing.

1.2 Payload Transfer Mechanism

In a simple action flow where components are arranged in series, it can be represented by the following flow diagram:

C01 -> C02 -> C03 -> [END]

In this case, the components operate as follows:

  1. C01 component receives Payload from the trigger in its queue and begins processing
  2. C01 generates output Payload and posts it to C02’s queue
  3. C01 waits for the next Payload in its queue but typically ends as there is no next Payload
  4. C02 retrieves the posted Payload and begins processing
  5. Similarly, C02 posts output Payload to C03’s queue after processing
  6. C03’s output Payload becomes the action’s overall output as there is no next component

While each component operates in parallel in its own thread, the order is maintained by Payload dependencies, making it appear as if C01, C02, and C03 are operating in sequence.

2. Parallel Processing and Flow Branching

2.1 Traditional Action Flow

In traditional action flows, components were connected in series, and it might not have appeared that they were operating in parallel threads. However, in reality, while one component was waiting for I/O, other components could operate, making efficient use of CPU resources across the entire action.

2.2 Parallel Execution Model

In the new version, explicit branching can be introduced into action flows. For example, using the Parallel component, you can clone one input Payload and distribute it to multiple processing lines:

        +-> C11 -> C12
        |
C01 -> Parallel -> C03 -> [END]

In this example, C01’s output Payload is cloned by the Parallel component and posted to both C03’s and C11’s queues. This allows the C03 processing line and the C11→C12 processing line to execute in parallel.

In parallel processing, we need to decide how to handle the output Payload from the C11 line. In the current implementation, the output Payload from the C11 line is discarded at the end, and the output Payload from the C03 line reaches the action’s END (final output). This prevents system behavior from becoming ambiguous when multiple Payloads reach [END].

2.3 Branch Components

Branch components allow you to transfer Payloads to different components based on conditions. Here’s a basic example of branching:

C01 -> If -> C02 -> [END]
       |
       +-----------> C03

In this case, if the If component’s condition expression is true, the output Payload is transferred to C02; if false, it’s transferred to C03. Using branching allows for efficient implementation of condition-based processing.

3. Flow Control Components

3.1 If Component

The If component is used to implement conditional branching.

3.2 Jump/JumpIf Component

Jump/JumpIf components provide functionality to call other actions.

3.3 Call/CallIf Component

Call/CallIf components also call other actions but, unlike Jump, control returns to the caller.

The choice between Call/Jump and CallIf/JumpIf depends on the flow of processing. Using Call/CallIf connects to C03 after C12, while using Jump/JumpIf connects to a virtual [END] after C12, making the output Payload the action’s output.

        +-> C11 -> C12
        |
C01 -> C02 -> C03 -> [END]

3.4 Parallel Component

The Parallel component is used to clone input Payload and transfer it to multiple processing paths.

4. Multiple Action Coordination

4.1 Handling Action Instances

When actions are instantiated from the same branch component, if they have the same ActionId, the same action instance is used. This ensures that when the same action is called from different paths, the action’s state is shared.

For example, in the following case, even when the same action with ActionId(A1) is called from two branches, processing remains organized:

       (A1)
       +-> C11 -> C12
       |  (A1)
       +-> C11 -> C12
       |
Split -> Call -> C03 -> [END]

When multiple output Payloads reach a branch component, the action is instantiated when the first Payload arrives, and the same action instance is used for subsequent arrivals.

4.2 Payload Transfer Methods

Different branch components generate separate action instances even with the same ActionId. This allows the same action to be executed independently in different contexts:

        (A2)
        +-> C21 -> C22
        |  (A1)
        +-> C11 -> C12
        |        (A1)
        |        +-> C11 -> C12
        |
Split -> Jump -> Call -> [END]

This way, you can call the same action from different branch components when you want to use it in different contexts. You can also use the same action with Call in one place and Jump in another.

4.3 Complex Flow Control Patterns

When you want to call different actions after components that post multiple output Payloads (like Split or CSVRead/SensorDataDB), you can use patterns like this:

        (A1)
        +-> C11 -> C12
        |
        |  (A2)
        |  +-> C21 -> C22
        |
Split -> JumpIf -> JumpIf -> C03 -> [END]

By using JumpIf components to call different actions based on conditions, you can implement control flow similar to a programming language’s switch statement. You can also achieve similar control with a single component by changing the ActionId in PreMappings based on condition evaluation.

5. Advanced Examples

5.1 Conditional Branching (Switch-like Processing)

When you want to execute different actions based on conditions, you can utilize JumpIf components:

        (A1)
        +-> C11 -> C12
        |
        |  (A2)
        |  +-> C21 -> C22
        |
Split -> JumpIf -> JumpIf -> C03 -> [END]

By setting conditions in each JumpIf component’s Expr property and specifying the desired ActionId, you can implement processing branches for various conditions.

5.2 Parallel Execution of Multiple Actions

With C02 as a branch component, you can either post directly to C03 or to C11 of another action based on conditions:

        +-> C11 -> C12
        |
C01 -> C02 -> C03 -> [END]

In this case, you use flow control components like Jump or Call. Using Jump connects C12 to a virtual [END], while using Call connects C12 to C03.

Posting to components in other actions doesn’t stop the operation of the original action. All components operate in parallel, with thread scheduling dependent on the Go language runtime. For example, the first Payload goes to (A1) and ultimately to the virtual [END], while the second Payload goes to (A2).

By combining branching and inter-action coordination, you can efficiently implement complex business logic. You can improve overall processing efficiency by leveraging parallel processing characteristics while resolving bottlenecks caused by I/O waiting and other factors.