Architecture Principles
OOCANA is OOMOL's core workflow engine, providing the foundational runtime support for the entire OOMOL Studio.
OOCANA Overview
OOCANA is an orchestration tool designed for scheduling and executing sequences of task units. The architecture consists of:
- Scheduling logic stored in
flow.oo.yamlfiles (referred to asflow) - Task execution content stored in
block.oo.yamlfiles (referred to asblock) block.oo.yamlcontains references to execution code, which we call block functions
Block functions can be written in either Nodejs or Python, with a mandatory function name main. This function accepts two parameters:
- Input data
- Auxiliary functions provided by the block runtime
The function should return a dictionary object (or in Nodejs, a Promise that resolves to a dictionary), which becomes the block's output data.
The flow file defines the triggering sequence and data transfer relationships between blocks.
Block Orchestration and Execution
The execution sequence of blocks is determined by connections defined in the flow, following a data-flow driven model — when required data is ready, the corresponding block is automatically triggered for execution. This differs from event-driven step triggering in GitHub Actions (where the next step is triggered after the previous one completes), which is primarily used in CI/CD scenarios like compilation and packaging.
Runtime Environments and Executors
Currently, blocks support Nodejs and Python runtime environments. Each runtime environment has a corresponding Executor that loads and executes the block code.
Key execution characteristics:
- Same-language blocks run in the same runtime environment by default
- Same-process optimization: When consecutive blocks use the same language and belong to the same package, OOCANA places them in the same process to reduce overhead
- Independent processes: Blocks can be configured to run in independent processes for isolation or debugging purposes
For detailed information about executors and process management, see Executor Concepts.
Data Transfer Between Blocks
Data transfer between different language environments is transferred via JSON, while blocks in the same language environment can transfer data through JSON or directly via variables.
JSON Serialization (Cross-Language or Cross-Process):
- Universal compatibility across all supported languages
- Used when blocks run in different languages or independent processes
- Slight performance overhead for serialization/deserialization
- All Handle types except Variable can be cached
Direct Variable Passing (Same Language, Same Process):
- Maximum performance with zero serialization overhead
- Used via Variable type Handles
- Can pass complex objects that cannot be serialized
- Variables follow pass-by-reference semantics - modifying a variable value in one
blockaffects the same variable in otherblocks - Cannot be cached (upstream blocks will always re-execute)
When using Variable type Handles for maximum performance, be aware that the blocks become tightly coupled and can only work with blocks in the same language environment. This reduces block portability but provides significant performance benefits for complex object passing.
Block Data Transfer Specifications
Data formats are defined separately in block and flow. Currently, OOCANA runtime does not validate these data formats (some GUI components handle this validation). During execution, the actual data format returned by a block is not yet validated. Therefore, developers must ensure that returned data formats conform to the specifications defined by both flow and block.
Block Debugging and Acceleration Strategies
When a flow contains numerous blocks with time-consuming execution, debugging can be accelerated by specifying block execution strategies. Two acceleration methods are supported:
- Termination Point Strategy: Execution ends after reaching a specified
block - Cache Strategy: Utilizing previously executed data cache (JSON data only) to skip blocks that don't need re-execution, quickly reaching the specified
block