Module executor

Source
Expand description

The logic for executing a job

When a job is being executed, logically it is separated into two different areas:

  1. retrieving the next node to be run
  2. running the current node(s)

§Get Next Node

The Job struct has a method defined on it called Job.next_node() which will return the next node or nodes. This works in an event based pattern whereby each node, on completion, will send a message to the Job struct informing it that the node has completed.

The Message that is sent returns a status to let the job know whether the node completed successfully. On successful completion, the executor will call job.next_node(msg.pointer) to fetch the next node(s) to be executed.

§Run the current node(s)

As each node is returned, it needs to be run. Every node implements the Node type which means that to run it we can simply call the run method. Each node is run in a new task so we can run multiple nodes in parallel. This is so we can accommodate for parallels and exclusives.

for node in job.next_node(...) {
    task::spawn(node.run().await) // executes in background, immediately returning
}

Functions§

execute_handler
The execute_handler function takes a workflow ID, gets the workflow and creates a Job struct from that workflow. Once we have a Job struct, the job is driven to completion by the run function.
run
Take ownership of a job and the jobs receiver and drive the job to completion by getting each node and running them as they can be run.