Skip to content

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.

run the nested ops check the rows When: all / any / none true false next op

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}