Event Driven Cycling
Get a copy of this example
$ cylc get-resources examples/event-driven-cycling
Cylc is good at orchestrating tasks to a schedule, e.g:
PT1H
- every hourP1D
- every dayP1M
- every monthPT1H ! (T00, T12)
- every hour, except midnight and midday.
But sometimes the things you want to run don’t have a schedule.
This example uses cylc ext-trigger
to establish a pattern where Cylc waits
for an external signal and starts a new cycle every time a signal is received.
The signal can carry data using the ext-trigger ID, this example sets the ID as a file path containing some data that we want to make available to the tasks that run in the cycle it triggers.
To use this example, first start the workflow as normal:
cylc vip event-driven-cycling
Then, when you’re ready, kick off a new cycle, specifying any environment variables you want to configure this cycle with:
./bin/trigger <workflow-id> WORLD=earth
Replacing <workflow-id>
with the ID you installed this workflow as.
Example - CI/CD
This pattern is good for CI/CD type workflows where you’re waiting on external events. This pattern is especially powerful when used with sub-workflows where it provides a solution to two-dimensional cycling problems.
Example - Polar satellite data processing
Polar satellites pass overhead at irregular intervals. This makes it tricky to schedule data processing because you don’t know when the satellite will pass over the receiver station. With the event driven cycling approach you could start a new cycle every time data arrives.
Note
The number of parallel cycles can be adjusted by changing the
[scheduling]runahead limit
.To avoid hitting the runahead limit, ensure that failures are handled in the graph.
[scheduling]
cycling mode = integer
initial cycle point = 1
runahead limit = P5 # max number of cycles which can run in parallel
[[special tasks]]
# register the external trigger, it must be given a name,
# here, 'trigger' is used as a placeholder, the bash script will
# need to be updated if this is changed
external-trigger = configure("trigger")
[[graph]]
P1 = """
# use a "?" to prevent failures causing runahead stalls
configure? => run
"""
[runtime]
[[configure]]
# this task reads in the broadcast file the trigger wrote
# and broadcasts any variables set to all tasks in this cycle
script = """
echo "received new ext-trigger ID=$CYLC_EXT_TRIGGER_ID"
TRIGGER_FILE="${CYLC_WORKFLOW_RUN_DIR}/triggers/${CYLC_EXT_TRIGGER_ID}.cylc"
cylc broadcast "${CYLC_WORKFLOW_ID}" \
-p "${CYLC_TASK_CYCLE_POINT}" \
-F "${TRIGGER_FILE}"
"""
[[run]]
# this task could be a sub-workflow
script = """
echo "Hello $WORLD!"
"""