When things go wrong, LittleHorse has got you covered. That's where Failure Handling comes into play.
0.5.0 release introduced a new value for the
LHStatus enum (used in
What Are Failures?
A Failure in LittleHorse is like an Exception in programming. It means that A Bad Thing® has happened. However, we should note that LittleHorse is at its core a Workflow Engine. Therefore, there are two potential sources of Failure:
- A technical process, such as an external API call, fails.
- Something goes wrong at the business process level; for example, a credit card has insufficient funds.
Exception Handling in LittleHorse is a fully separate concept from
0.3.0 introduced the
EXCEPTION status to LittleHorse (it was made stable in
0.5.0). This was because initial feedback from users was that when a
NodeRun is in the
ERROR status, it is difficult to know whether the failure was caused by a technical outage or by business logic. Often, we want to handle such cases differently.
EXCEPTION status fills this gap by offering a status to represent a specific business process failure. The user provides the name of the
EXCEPTION and must explicitly throw such an exception by calling
WorkflowThread#fail() in any
This is similar to
throw new FooException() in java.
ERROR in LittleHorse means that some technical process has failed. Causes of an
- An unexpected exception thrown by the Task Worker when processing a
- Casting errors when attempting to serialize inputs for a
- Casting errors when processing the outputs of a
WfSpec SDK does not surface the ability to throw an
ERROR; however, the SDK does allow users to catch and handle
ERRORs in the same manner as
Every Failure (either
ERROR) has a name. This is useful for two reasons:
- It allows users to define different handlers for specific Failure types.
- It provides better visibility into just what went wrong in a
ERROR names are in
UPPER_UNDERSCORE_CASE, and they are pre-defined by LittleHorse. They are as follows:
CHILD_FAILURE: A Child
ThreadRunfailed with an uncaught
VAR_SUB_ERROR: Failed to assign an input variable (whether to a
NodeRunof some sort or a child
VAR_MUTATION_ERROR: Failed mutating the value of a variable.
TIMEOUT: Some timeout occurred. Usually, this is thrown by a
TASK_FAILURE: Some uncaught exception was thrown by the Task Worker while executing a
INTERNAL_ERROR: An unknown problem occurred. This is exceedingly rare.
VAR_ERROR: This is a super-type of
TASK_ERROR: This is a super-type of
In contrast, all
EXCEPTION names are in
dns-subdomain-format, and they are specified by you, the user!
Failure names are important both when handling and throwing Failures, so stay tuned.
In programming, exceptions often have some content or values to them. For example, the grpc
StatusRuntimeException in Java contains a
Code and a
String description. Likewise, a Failure in LittleHorse has content in the form of a single
VariableValue, which is of type
NULL if there is no content. Any Failure Handler can access the content of the failure using the special reserved
How can you recover when things go wrong? That's where Failure Handler's come into play. In programming, you can define a block of code (exception handler) that runs to handle a certain exception. In LittleHorse, you specify a
ThreadSpec that runs when a Failure of a certain type occurs.
There are three methods on the
WorkflowThread which allow this to happen:
WorkflowThread#handleException()is used to handle business failures (
WorkflowThread#handleError()is used to handle technical failures (
WorkflowThread#handleAnyFailure()registers a handler for any Failure, whether it's an
handleError, you can optionally pass in a specific
name of the Exception or Error that you wish to handle.
You can throw an exception using the