DO-WHILE condition
Runs the ops nested underneath it, then checks a set of comparisons against the stash and goes round again while they hold true. The body always runs at least once, because the first check happens after it rather than before.
That is the only difference from WHILE condition, which checks first and can skip the body entirely. Pick this one when the first pass is what produces the value you are going to test: fetch a page then loop while there are more pages, process one item then loop while the queue is not empty.
Fields¶
The condition builder is the same one used by WHILE condition and IF var condition THEN.
When¶
How the condition rows combine. The combo offers Any, All and None: All needs every row true
to go round again, Any needs one, None needs no row to be true. None is the opposite of Any,
so a single true row ends the loop.
A newly dropped op has this field empty, and an empty setting gives a false answer whatever the rows contain. In this op that is not a no-op, it is exactly one pass: the body runs, the check comes back false, the loop ends. That looks like a working configuration in the log and is the most common way to get a loop that mysteriously processes only the first item.
Rows stop being evaluated once one settles the answer, and the order they are read in is not the order the form shows them. Do not lean on one row to guard another.
Stash Variable¶
The left side of the comparison, written as a bare name with no ${} wrapper. Dots walk into nested
data, and list positions take brackets: bar_items[0].name. A path that does not resolve produces an
empty value rather than an error. The field will not save blank.
Because the body runs first, this variable does not need to exist before the op starts. It only has to exist by the end of the first pass.
Operator¶
The comparison. A new row starts on IS TRUE. The choice reshapes the row: the four that inspect
only the left side hide the value field, and the checkboxes appear only where they apply.
| Operator | The row is true when | Value field |
|---|---|---|
IS TRUE |
the variable holds a non-empty, non-zero value; for a list, any entry does | hidden |
IS FALSE |
nothing in the variable is truthy | hidden |
IS EMPTY |
the variable is unset, an empty string, an empty list or an empty hash | hidden |
NOT EMPTY |
the variable holds something | hidden |
EQUALS =, NOT EQUALS != |
the two sides match, or differ | text |
GREATER THAN >, GREATER THAN OR EQUALS TO >= |
the ordering holds | text |
LESS THAN <, LESS THAN OR EQUALS TO <= |
the ordering holds | text |
LIKE (regular expression), NOT LIKE (regular expression) |
the pattern matches, or does not | regex |
IN, NOT IN |
the variable equals one of the entries on the right, or none of them | text |
HAS, NOT HAS |
the list in the variable contains the value, or does not | text |
NOT EMPTY on a work queue is the usual choice here, since the body is what shortens the queue.
HAS reads a hash as well as a list, and it matches on either side of the hash, so a row that finds
a key is indistinguishable from a row that finds a value.
Value¶
The right side. This field expands ${var} placeholders against the stash, unlike the variable
field, which takes a bare path. LIKE and NOT LIKE read it as a regular expression.
IN and NOT IN never split what you type on commas. Typing approved,scheduled compares the
variable against that one long string and matches nothing, giving a row that is always false and a
loop that runs the wrong number of times in whichever direction When points. The several values
have to arrive as several values, from a stash key that already holds a list:
${allowed_statuses}. For a fixed set typed into the form, use LIKE with
^(approved|scheduled)$.
Options¶
Ignore case lowercases both sides before comparing, or makes the pattern case-insensitive on the
two regular-expression operators. Numeric compares as numbers instead of text, which matters as
soon as a value passes 9. Numeric is offered on the six equality and ordering operators only.
Add condition and Remove¶
Rows sit in fieldsets titled Condition. Add condition appends one, Remove deletes the row it
sits in. All rows share the one When setting, so a single op cannot mix and-logic with or-logic.
Nest a second loop for that, or move the test into code.
Remove will take the last row away, and the op saves with no rows at all. Reopening the form hands
you a fresh empty row, so the rule looks configured while it is not. See
Ending the loop for what a rowless op does at run time.
Ending the loop¶
The body must change what the rows read, in the stash the check can see. A value written inside STASH LOCAL is gone by the time the rows are evaluated, and the loop never ends.
An op with no condition rows left on it is the other way to hang. All and None both come back
true when there is nothing to check, so the loop runs forever; Any comes back false and you get a
single pass.
There is no iteration cap. Set Timeout on the op's Options tab to put a wall behind the loop: it
arms a clock before the first pass and fails the job with a rule timeout when the seconds run out.
The clock is not cleared when the loop ends, so a generous timeout set here can still go off during
an op further down the rule.
A nested op that fails ends both the loop and the job, since this op catches nothing. The loop
writes nothing of its own into the stash, and Return Key on the Options tab has no effect here.
The op itself registers as a step once, before the first pass, so it appears in the job log a single time however many times the body runs. What repeats in the log is the nested ops. Each of those also checks for a cancel request as it starts, which is how you stop a loop that is not going to end on its own: cancel the job from the monitor and it stops at the next op inside the body.
The first pass is unconditional, which is the trap that comes with this op. If the body assumes
there is work to do, an empty input still gets one pass. Wrap the whole thing in
IF var condition THEN with a NOT EMPTY test when that pass
would do damage.
Combining with other ops¶
Put Sleep for a number of seconds at the end of the body when the loop polls something outside Clarive, otherwise it runs at full speed.
Build the list with PUSH VAR and shorten it in the body, or use SET VAR and SET EXPR to move the tested value along.
RETRY covers the other reason for repeating a block, where the repeat is driven by a failure rather than by a value.
Examples¶
Work through a list of leftover objects, one pass per object, with the body removing the one it just handled.
When: Any
pending_objects NOT EMPTY
-> Server CODE take the first entry off pending_objects
-> Run a Remote Script
Page through a paginated source: fetch, then keep going while a next-page marker came back.
When: All
next_page_token NOT EMPTY
-> Web Request fetch page ${next_page_token}