Tips, Pointers, and FAQ
We do our best to make our documentation easy to navigate; however, LittleHorse has a lot of features and it may not always be easy to find what you are looking for.
Think of this page as an "index" that will help you find what you need to make your project a success.
Workflow Basics
Read here for how to get started.
What is a WfSpec
and WfRun
?
The core concept of LittleHorse is a Workflow, which defines a series of tasks to execute and events to wait for. A WfSpec
defines a workflow specification. A WfRun
is a running instance of that WfSpec
.
workflow specification is the configuration, or metadata object, that tells the engine what Tasks to run,
what order to run the tasks,
how to handle exceptions or failures,
what variables are to be passed from task to task,
and what inputs and outputs are required to run the workflow.
In LittleHorse the Workflow Spec is submitted to and held by the LittleHorse server.
It is a written in Code, using the LittleHorse SDK.
In the background LittleHorse server takes the submitted spec from the SDK, and compiles a protobuf object that is submitted to the LittleHorse server.
Example:
public class QuickstartWorkflow {
public static final String WF_NAME = "quickstart";
public static final String GREET = "greet";
/*
* This method defines the logic of our workflow
*/
public void quickstartWf(WorkflowThread wf) {
// Create an input variable, make it searchable
WfRunVariable name = wf.addVariable("input-name", VariableType.STR).searchable();
// Execute a task and pass in the variable.
wf.execute(GREET, name);
}
/*
* This method returns a LittleHorse `Workflow` wrapper object that can be
* used to register the WfSpec to the LH Server.
*/
public Workflow getWorkflow() {
return Workflow.newWorkflow(WF_NAME, this::quickstartWf);
}
}
How do I create a WfSpec
?
Check out our WfSpec
development docs! In short, you can use our Java, Python, or Go SDK's to define the WfSpec
logic and then register them to the LH Server.
Tasks
Tasks are the unit of work for a work flow engine.
It's best to think in examples:
- Change lower case letters to upper case letters.
- Call an API with an input variable and pass along the output.
- Wait for user input or an event to happen.
What is a Task Worker?
A Task Worker is a program that opens a connection to a LittleHorse Cluster and listens to a task queue for a specific TaskDef
. When a WfRun
arrives at a point where it needs to execute that specific type of TaskRun
, then the scheduled Task will be dispatched to the Task Worker. The Task Worker executes it and reports the result to the LH Server.
A task worker can be a bare metal machine, Virtual Machine, cloud instance, Kubernetes pod, or anywhere that can execute Java/Python/Golang or C# code.
How do I write a Task Worker?
Check out our Task Worker Development Docs!
How do I run a Workflow?
You can run a workflow in two ways:
- On the command line by using
lhctl
. This method is best suited for testing, development, or debugging. - Programmatically by using one of our SDK's. Under the covers, the SDKs call the GRPC endpoint on the LittleHorse server. Programmatic execution is ideal for incorporating into your dashboards, and operational tools.
Variables and Control Flow
How do I pass information from one task to another?
Variables are how you pass info from one task to another. Take the output of one task and ASSIGN
it to a variable, then pass that variable into the next task. Check out our mutating variables documentation.
How do I define variables in a Workflow?
Check out the Variables Section of our WfSpec
docs.
Can I search for workflows by their variables?
Yes, you can. To do that, mark the variable as searchable()
and then use `rpc SearchVariable to search for it.
How do I do if/else in a Workflow?
Check out the Conditionals Section of our WfSpec
docs.
Can a workflow have loops?
Yes, check out the loops section.
External Events
What is an ExternalEvent
?
External Events in LittleHorse represent events that occur outside of the context of a single WfRun
. For example, you might use an ExternalEvent
to notify a WfRun
when someone signs a DocuSign document, or when a text message is replied to.
An ExternalEvent
is an instance of an ExternalEventDef
.
How do I make a WfRun
wait for an event?
Check out the External Events section of our WfSpec
docs. What you want is an ExternalEventNode
, which blocks until an ExternalEvent
arrives.
How do I interrupt a WfRun
?
Check out the Interrupts section of our WfSpec
docs. What you want to do is register an Interrupt Handler for a certain ExternalEventDef.
What happens when a WfRun
is interrupted?
The interrupted ThreadRun
is HALTED
, and a child ThreadRun
is created to act as the Interrupt Handler. For info, check out our concept docs and our WfSpec
development docs.
You may want to interrupt a WfRun for various reasons including: A user cancels an order in on an e-commerce site, A business request is Denied or an external API returns a back off or denied status.
How can I access the content of an ExternalEvent
inside my workflow?
You can use the output of an ExternalEventNode
just like any other node in our SDK. Check out these docs
How do I post an ExternalEvent
?
You need to know the WfRunId
of the WfRun
you want to notify, and you need to know the ExternalEventDefId
.
Can I make ExternalEvent
s idempotent?
Yes, just pass the guid
parameter in the PutExternalEventRequest
when making the rpc PutExternalEvent
.
Workflow Threading
Can I run tasks in parallel?
To run tasks in parallel within a single WfRun
, you need to create a Child Thread.
Can different threads share variables?
A child ThreadRun
can read and write the variables of its parent. A parent cannot view the variables of its child.
What happens when a child fails?
When a child fails, the failure propagates to the parent either at:
- The
WaitForThreadsNode
, or - The
ExitNode
.
See the Child Thread Docs for info on how to handle these failures.
What happens to the child when a parent fails?
When a parent ThreadRun
fails (ERROR
or EXCEPTION
) or moves to HALTED
, the child will move to HALTED
.
In order to recover from a failed Parent thread you can either catch the exception, and programmatically handle it. Or require that a human restarts the workflow.
User Tasks
What are User Tasks?
User Tasks allow a workflow to wait for input from a human.
How do I add a user task to my workflow?
A userTask
is to manage tasks involving humans alongside standard computer tasks in your LittleHorse Workflow. Check out the User Tasks page of our WfSpec
docs.
Do User Tasks support users and user groups?
Yes, user tasks can be assigned to either a user_id or a user_group. Note that user and group identities are not managed by the LH Server. User and group identies are managed by an external identity provider(IDP), for example any oAUTH provider.
How do I complete User Tasks?
For testing purposes, you can do it using lhctl
. For production applications, check out our docs on managing User Tasks with grpc.
How do I create a UserTaskDef
?
Check out our Managing Metadata docs.
Exception Handling
What is the difference between ERROR
and EXCEPTION
?
As per our Failure Handling Concepts Docs, an ERROR
represents a technical failure such as a type error, network outage, timeout, or unexpected exception thrown by a task worker. An EXCEPTION
represents something going wrong at the business process level, such as an invalid credit card or an item being out of stock.
How do I catch a failure in a workflow?
Check out our Failure Handling WfSpec
docs.
How do I throw an EXCEPTION
?
You can throw an EXCEPTION
from a Task Worker. You can also make a ThreadRun
fail with the WorkflowThread.fail()
method.
Reliability
Is LittleHorse Fault-Tolerant?
Yes, it was built into the core DNA of our system. Every component of the LittleHorse tech stack is highly available and fault tolerant. At the workflow layer LittleHorse provides the primitives to handle faults in a way to suit the business needs.
Does LittleHorse scale?
Yes, in our internal benchmarks a moderately resourced, single instance, of LittleHorse server can execute 30,000 tasks per second in a moderately complex workflow.
How do I make Workflows idempotent?
You can pass the WfRunId
when running a WfRun
. Only one WfRun
can exist with a given Id, so this makes the request idempotent.
How do I make Tasks idempotent?
You can use the WorkerContext
to get an idempotency key.
About the Project
Who Holds the Copyright?
The source code for LittleHorse is copyright of LittleHorse Enterprises LLC, a Nevada LLC.
Can I use LittleHorse for free in production?
LittleHorse is covered by the SSPL 1.0 License. You may run LittleHorse in production for free and with no restrictions so long as you are not offering LittleHorse-as-a-Service. Basically, if your customers are not using the LittleHorse GRPC clients to interact with LittleHorse directly, you can run LittleHorse for free in production.
The SSPL license was originally created by Mongo DB, who has an excellent FAQ about the license terms.
Can I get enterprise support?
Yes. LittleHorse Enterprises LLC, which is the company behind the LittleHorse workflow engine, offers three forms of support for LittleHorse:
- 24/7 enterprise support for LittleHorse OSS.
- LittleHorse Cloud, which is a fully-managed SaaS service for LittleHorse.
- LittleHorse for Kubernetes, which is an enterprise distribution of LittleHorse delivered through Kubernetes Operator into your K8s cluster.
You can reach LittleHorse Enterprises LLC via their website.
Do you accept contributions?
Yes, we do accept contributions. Check out our GitHub for tips on how to contribute.