Mutating Variables
Recall from the Concepts Documentation that every Node
can have zero or more VariableMutation
s on it. A VariableMutation
changes the value of a ThreadRun
's Variable
s.
You can add a VariableMutation
at any point in your Thread Function by using the WfRunVariable#assign()
method or function.
Basic Structure
The WfRunVariable::assign()
functions/methods take one argument:
- A
WfRunVariable
,NodeOutput
, Object/interface/struct, or primitive type to serve as the RHS for the mutation.
The valid Mutation Types come from the VariableMutationType
enum and are:
ASSIGN
ADD
SUBTRACT
DIVIDE
MULTIPLY
EXTEND
REMOVE_IF_PRESENT
REMOVE_KEY
REMOVE_INDEX
A description of each VariableType
can be found on the protobuf documentation.
Examples
Here are some examples of mutating variables inside a WfSpec
.
Hard-Coded Literal Value
Let's assign our variable foo
to the hard-coded value of 3
.
- Java
- Go
- Python
- C#
public void threadFunction(WorkflowThread thread) {
WfRunVariable foo = thread.declareInt("foo");
// ... optionally execute some tasks
foo.assign(3);
}
func someThreadFunction(thread *littlehorse.WorkflowThread) {
foo := thread.DeclareInt("foo")
// ... optionally execute some tasks
foo.Assign(3)
}
def thread_function(thread: WorkflowThread) -> None:
foo = thread.declare_int("foo")
# ... optionally execute some tasks
foo.assign(3)
public void ThreadFunction(WorkflowThread thread)
{
WfRunVariable foo = thread.DeclareInt("foo");
// ... optionally execute some tasks
foo.Assign(3);
}
Using a NodeOutput
Let's say we have a TaskDef
which returns an INT
value, and we want to add that value to our WfRunVariable
. To do that, we use the NodeOutput
as the RHS
.
This is analogous to the following pseudocode.
int myInt = 1;
myInt += doTask1();
- Java
- Go
- Python
- C#
public void threadFunction(WorkflowThread thread) {
WfRunVariable foo = thread.declareInt("foo").withDefault(3);
NodeOutput intOutput = thread.execute("some-task-that-returns-int");
foo.assign(foo.add(intOutput));
}
func someThreadFunction(thread *littlehorse.WorkflowThread) {
foo := thread.DeclareInt("foo").WithDefault(3)
taskOutput := thread.Execute("some-task-that-returns-int")
foo.Assign(foo.Add(taskOutput))
}
def thread_function(thread: WorkflowThread) -> None:
foo = thread.declare_int("foo").with_default(3)
int_output = thread.execute("some-task-that-returns-int")
foo.assign(foo.add(int_output))
static void ThreadFunction(WorkflowThread thread)
{
WfRunVariable foo = thread.DeclareInt("foo").WithDefault(3);
NodeOutput intOutput = thread.Execute("some-task-that-returns-int");
foo.Assign(foo.Add(intOutput));
}
Using other WfRunVariables
We can also use another WfRunVariable
as the RHS
. For example, if our LHS
is a JSON_ARR
, we can append another JSON_ARR
to it as follows:
- Java
- Go
- Python
- C#
public void threadFunction(WorkflowThread thread) {
WfRunVariable listToAppend = thread.declareJsonArr("list-to-append").withDefault(Arrays.asList("testN"));
WfRunVariable myList = thread.declareJsonArr("my-list").withDefault(Arrays.asList("test1", "test2"));
// ... execute some tasks
myList.assign(myList.extend(listToAppend));
}
func someThreadFunction(thread *littlehorse.WorkflowThread) {
listToAppend := thread.DeclareJsonArr("list-to-append").WithDefault([]string{"testN"})
myList := thread.DeclareJsonArr("my-list").WithDefault([]string{"test1", "test2"})
// ... execute a few tasks
myList.Assign(myList.Extend(listToAppend))
}
def thread_function(thread: WorkflowThread) -> None:
list_to_append = thread.declare_json_arr("list-to-append").with_default(["testN"])
my_list = thread.declare_json_arr("my-list").with_default(["test1", "test2", "test3"])
# ... execute a few tasks
my_list.assign(my_list.extend(list_to_append))
public void ThreadFunction(WorkflowThread thread)
{
WfRunVariable listToAppend = thread.DeclareJsonArr("list-to-append").WithDefault(new List<string> { "testN" });
WfRunVariable myList = thread.DeclareJsonArr("my-list").WithDefault(new List<string> { "test1","test2" });
// ... execute some tasks
myList.Assign(myList.Extend(listToAppend));
}
Using JsonPath
Both NodeOutput
and WfRunVariable
have a #jsonPath()
method.
If your LHS
variable is of type JSON_ARR
or JSON_OBJ
, you can use WfRunVariable#jsonPath()
to allow you to mutate a specific sub-field of your object or list. For example, if I have a my-var
variable as follows:
{
"foo": "bar",
"counter": 123
}
and I want to increment the counter
field, I can do so as follows:
- Java
- Go
- Python
- C#
public void threadFunction(WorkflowThread thread) {
WfRunVariable myVar = thread.declareJsonObj("my-var");
WfRunVariable counterPath = myVar.jsonPath("$.counter");
// ... execute some tasks
counterPath.assign(counterPath.add(1));
}
func someThread(thread *littlehorse.WorkflowThread) {
myVar := thread.DeclareJsonObj("my-var")
counterPath := myVar.JsonPath("$.counter")
// ... execute some tasks
counterPath.Assign(counterPath.Add(1))
}
def thread_function(thread: WorkflowThread) -> None:
my_var = thread.declare_json_obj("my-var")
counter_path = my_var.with_json_path("$.counter")
# ... execute some tasks
counter_path.assign(counter_path.add(1))
static void ThreadFunction(WorkflowThread thread)
{
WfRunVariable myVar = thread.DeclareJsonObj("my-var");
WfRunVariable counterPath = myVar.WithJsonPath("$.counter");
// ... execute some tasks
counterPath.Assign(counterPath.Add(1));
}
You can also use .jsonPath()
on the RHS to pick out a specific field of your RHS
value.