@@ -1909,6 +1909,108 @@ A more realistic example might have several tasks on each branch. The
1909
1909
``bar ``, but configured differently to avoid the failure.
1910
1910
1911
1911
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
+
1912
2014
Custom Outputs
1913
2015
^^^^^^^^^^^^^^
1914
2016
0 commit comments