Control Flow
Branches
The pipeline structure can be dynamically altered based on the output of other tasks. Create the following two files in the main project directory:
from sdag import Elif, Else, If, pipeline
@pipeline
def control_flow():
with If(condition1()):
option1()
with Elif(condition2()):
option2()
with Else():
option3()
@control_flow.task("submit.sh")
def condition1() -> bool:
return False
@control_flow.task("submit.sh")
def condition2() -> bool:
return True
@control_flow.task("submit.sh")
def option1():
print("Option 1 selected")
@control_flow.task("submit.sh")
def option2():
print("Option 2 selected")
@control_flow.task("submit.sh")
def option3():
print("Option 3 selected")
condition1 and condition2 are tasks that must return a Boolean value. Run:
to execute the example. The expected flow is:
condition1is executed and returnsFalse.- Because the output is
False,option1is skipped andcondition2is evaluated. - The output of
condition2isTrue, sooption2is executed whileoption3is skipped.
OneOf
One might expect the following snippet to work as expected:
Unfortunately, it's not! t in the example will always refer to option2. The oneof node is inspired by Kubeflow and it can be used to reference tasks running on separate branches. Add the following snippet to the same control_flow.py module:
from sdag import oneof
@pipeline
def oneof_example():
with If(condition()):
t1 = first_alternative()
with Else():
t2 = second_alternative()
t = oneof(t1, t2)
final_task(t)
@oneof_example.task("submit.sh")
def condition() -> bool:
return False
@oneof_example.task("submit.sh")
def first_alternative():
print("alternative 1 selected")
@oneof_example.task("submit.sh")
def second_alternative():
print("alternative 2 selected")
@oneof_example.task("submit.sh")
def final_task():
print("final task")
Here, final_task will only run if at least one between first_alternative and second_alternative executes successfully. You can run the example through:
You can also use oneof when multiple concurrent tasks executed. It will become the first task of the pool that completes the execution without errors.
@pipeline
def dag():
t_fail = will_fail()
t_slow = slow_task()
t_fast = fast_task()
# Likely equal to t_fast
first_to_complete = oneof(t_fail, t_slow, t_fast)
Info
To run these examples with Slurm, turn submit.sh into a sbatch script as explained in the Hello World section and execute pipelines without the --local option.