Server CODE
Runs a block of JavaScript or Perl on the Clarive server, in the middle of the rule, with the stash in scope. This is the escape hatch for logic no other op covers: reshaping a list, calling a library, reading the database, building one value out of three others.
Reach for it after the palette runs out, not before. SET EXPR already covers a one-line calculation and the condition builder in IF var condition THEN already covers comparisons. Eval Remote is the op that runs code on a target machine; this one always runs on the server. Server CODE supersedes CODE and EVAL, both of which are marked deprecated in the palette.
Fields¶
Programming language¶
JavaScript or Perl. A freshly dropped op starts on JavaScript. Changing the selection
re-highlights the editor and shows or hides the help button next to it; it does not translate
anything you have already typed. The setting belongs to the op, so one rule can hold blocks in both
languages.
Code¶
The block itself, in an editor with syntax highlighting for the language above. There is no length
limit and no ${...} expansion: the text is handed to the language exactly as you typed it. In
JavaScript, backtick template strings work, so `build-${n}` interpolates a JavaScript variable,
never a stash variable.
JavaScript blocks run in strict mode, which is not optional and is not shown anywhere in the form.
Assigning to a name you never declared throws instead of quietly creating a global, and an octal
literal such as 0755 is rejected outright.
Whatever the block evaluates to last is its value. See the return value for the rules, which are less obvious than they look.
JS API Help¶
The small button beside the language selector, tooltip JS API Help. It opens the
JavaScript introduction in the help panel, which is the way into the module
reference. The button is there while the language is JavaScript and disappears when you switch to
Perl.
The return value¶
The block produces one value: whatever its last evaluated expression produced. Put a name in
Return Key on the op's Options tab and that value is stored in the stash under that name. Leave
Return Key empty and the value is thrown away.
Return Key takes a bare variable name with no ${} around it, and it has to be a single word. A
key with a space in it is dropped without a warning, so my key stores nothing at all.
Two traps, one per language:
- In JavaScript, a declaration is not an expression. A block ending in
var total = 7;returns nothing. End with a bare expression instead,total;. A top-levelreturnis a syntax error here, because your code is not wrapped in a function. - In Perl,
returndoes work, and it does more than you want: it ends the whole rule immediately. Every op after this one is skipped and nothing in the log says why. Finish the block with a plain expression instead.
Reading and writing the stash¶
In JavaScript the stash is reached through cla.stash. cla.stash('foo') reads a top-level key,
cla.stash('foo', 3) writes one, and cla.stash() with no argument hands back the whole stash as an
object. Nested values need a slash path, cla.stash('/topic/title'), not a dotted one; dots are path
separators inside ${...} templates, which is a different mechanism. The full interface is in
cla/stash, and the module list is in
the Clarive JavaScript DSL.
In Perl the stash arrives as $stash, an ordinary hash reference you index by key. Resources,
database access and the logging helpers are in scope too, the same ones available anywhere else in
rule code.
Values written to the stash by either language survive for the rest of the rule and, in a job, for
the rest of the job. Each JavaScript block runs in a brand new engine, so a variable set in one block
is gone by the next one and every require reloads from scratch. That fresh engine has a cost: a
JavaScript block inside a loop pays for engine startup on every iteration, so when the loop is long,
move the loop inside the block.
Perl leaks where JavaScript does not, and whether it leaks depends on Return Key. With the key
empty the block is dropped straight into the rule, so a my variable declared here is still in scope
in the next Perl block further down the same branch. Fill the key in and the block gets a scope of
its own, and that variable stops at the end of it. Write to the stash rather than relying on either
behaviour: adding a Return Key later will break code that leaned on the leak, with no warning.
When the code fails¶
A JavaScript error stops the rule and reports the message with a line number and a stack. A Perl
die at runtime does the same. Either way the ops after this one do not run, and in a job the step
ends in error.
The two languages fail at different moments. A Perl block is compiled together with the whole rule,
so a syntax error in it is caught the moment you save: the designer refuses with a
DSL validation failed message and offers Ignore and Save beside it. Save it anyway and no op in
the rule runs at all, not even the ones above the broken block. JavaScript is compiled only when the
op is reached and is never checked at save time, so a typo in a branch that rarely runs stays hidden
until the day it runs.
To survive a failure, set Error Handling on the op's Options tab to trap or ignore errors, or wrap
the op in TRY statement and
CATCH statement.
What shows in the job log¶
The op contributes one entry to the job log: its name. The code itself logs nothing, however much it computes. To report progress, call the logging module from JavaScript, described in cla/log, or drop a LOG Message op beside the block.
In JavaScript, console.warn, console.error and console.debug reach the job log. console.log
goes to the server output instead, where a job operator will never see it.
Rollback¶
The op runs in the forward pass and again during rollback, because
Run Forward and Run Rollback on the Options tab are both on by default. Code that changes
something outside Clarive should check the job mode before acting, or sit under an
IF ROLLBACK block. Nothing the block does is undone for you.
Combining with other ops¶
Use the block to prepare a value, then let ordinary ops act on it. A block that writes a list to the
stash pairs with FOREACH CI or
FOREACH file/item to walk it, and one that writes a flag pairs with
IF var condition THEN to branch on it. Both read better in the
tree than the equivalent if buried inside the block.
When the value is a single expression, SET EXPR does the same work in one line and shows the variable name in the tree.
To stop the rule on a verdict the block reached, write the verdict to the stash and let FAIL raise it. The message then lands in the log as a rule failure rather than as a code error.
Examples¶
Derive a tag from two stash values and hand it to later ops.
Programming language: JavaScript
Return Key: release_tag
var env = cla.stash('bl');
var version = cla.stash('version') || '0';
'rel-' + version + '-' + env.toLowerCase();
Decide whether the job is inside its maintenance window, and read the answer later with a condition op. Note the bare expression on the last line.
Programming language: Perl
Return Key: window_open
my $hour = (localtime)[2];
$hour >= 22 || $hour < 6 ? 1 : 0;
Build a list for a loop to consume. Nothing is returned, so Return Key stays empty and the block
writes to the stash itself.
Programming language: JavaScript
Return Key:
var log = require('cla/log');
var all = cla.stash('changesets') || [];
var urgent = all.filter(function(cs) {
return cs.category === 'hotfix';
});
log.info('hotfix changesets: ' + urgent.length);
cla.stash('urgent_changesets', urgent);