Skip to content

Commit 7283354

Browse files
authored
Merge pull request #772 from oliver-sanders/graph-branching++
document graph branching with multiple optional outputs
2 parents 1b256d9 + 4838dad commit 7283354

File tree

1 file changed

+102
-0
lines changed

1 file changed

+102
-0
lines changed

src/user-guide/writing-workflows/scheduling.rst

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1909,6 +1909,108 @@ A more realistic example might have several tasks on each branch. The
19091909
``bar``, but configured differently to avoid the failure.
19101910

19111911

1912+
Dependencies With Multiple Optional Outputs
1913+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1914+
1915+
We might have a task that depends on multiple optional outputs.
1916+
1917+
For example, this workflow is like the "recovery task" example above, but in
1918+
this case we only want to run the recover task if both of the upstream tasks
1919+
fail.
1920+
1921+
.. digraph:: Example
1922+
:align: center
1923+
1924+
rankdir = "LR"
1925+
1926+
one -> run_if_both_fail [label=":fail?", color="red", "fontcolor"="red"]
1927+
two -> run_if_both_fail [label=":fail?", color="red", "fontcolor"="red"]
1928+
1929+
one -> always_run [label=":finish", color="orange", "fontcolor"="orange"]
1930+
two -> always_run [label=":finish", color="orange", "fontcolor"="orange"]
1931+
1932+
subgraph cluster_1 {
1933+
label = "one:failed AND two:failed"
1934+
color = "red"
1935+
fontcolor = "red"
1936+
style = "dashed"
1937+
1938+
run_if_both_fail
1939+
}
1940+
1941+
subgraph cluster_2 {
1942+
label = "both tasks finished"
1943+
color = "orange"
1944+
fontcolor = "orange"
1945+
style = "dashed"
1946+
1947+
always_run
1948+
}
1949+
1950+
We might try to write the graph like so:
1951+
1952+
.. code-block:: cylc-graph
1953+
1954+
# run irrespective of whether the tasks succeed or fail
1955+
one:finish & two:finish => always_run
1956+
1957+
# run if both tasks fail <-- ERROR
1958+
one:fail? & two:fail? => run_if_both_fail
1959+
1960+
However, there is a problem with this.
1961+
1962+
1. If both tasks fail, then ``run_if_both_fail`` will run.
1963+
2. If both tasks succeed, then ``run_if_both_fail`` will not run.
1964+
3. If one task succeeds and the other fails, then the task ``run_if_both_fail``
1965+
will be left with one satisfied and one unsatisfied dependency. This will
1966+
cause the workflow to :term:`stall`.
1967+
1968+
To prevent the workflow from stalling in the third case, it is necessary to use
1969+
:term:`suicide triggers <suicide trigger>` to remove the task
1970+
``run_if_both_fail``.
1971+
1972+
.. code-block:: cylc-graph
1973+
1974+
# run irrespective of whether the tasks succeed or fail
1975+
one:finish & two:finish => always_run
1976+
1977+
# run if both tasks fail
1978+
one:fail? & two:fail? => run_if_both_fail
1979+
one:succeeded? | two:succeeded? => !run_if_both_fail
1980+
1981+
Here's an example workflow showing how to trigger tasks with each possible
1982+
combination of success/failure for the two tasks:
1983+
1984+
.. code-block:: cylc
1985+
1986+
[scheduler]
1987+
allow implicit tasks = True
1988+
1989+
[scheduling]
1990+
[[graph]]
1991+
R1 = """
1992+
one:finish & two:finish => always_run
1993+
1994+
one:succeeded? | two:succeeded? => run_if_at_least_one_succeeds
1995+
1996+
one:failed? | two:failed? => run_if_at_least_one_fails
1997+
1998+
one:succeeded? & two:succeeded? => run_if_both_succeed
1999+
one:failed? | two:failed? => !run_if_both_succeed
2000+
2001+
one:fail? & two:fail? => run_if_both_fail
2002+
one:succeeded? | two:succeeded? => !run_if_both_fail
2003+
"""
2004+
2005+
[runtime]
2006+
[[one]]
2007+
script = true
2008+
[[two]]
2009+
script = false
2010+
2011+
Try editing the ``script`` in this example to see which tasks are run.
2012+
2013+
19122014
Custom Outputs
19132015
^^^^^^^^^^^^^^
19142016

0 commit comments

Comments
 (0)