Skip to main content

Your First Task Worker


In LittleHorse, Task Workers are the building blocks of your WfSpecs. They do the actual "work" when a WfRun schedules a TaskRun to be executed. In this guide, we'll learn how to create your first Task Worker.

What is a Task Worker?

A Task Worker is a program that uses the LittleHorse SDK to poll TaskRuns from the queue in the LittleHorse Server. Every time the LittleHorse Server tells it to, the Task Worker executes a function or method that you write. That method invocation becomes a TaskRun in a WfRun; when it is executed the result is reported automatically back to the LittleHorse Server so the engine can decide what happens next in that particular WfRun.

Task Worker Architecture

The TaskDef

LittleHorse needs to keep track of all of the available types of TaskDefs that you can execute. This is done with the TaskDef. Before you can create a WfSpec that refers to a TaskDef, you must first register the TaskDef that you want to refer to. The TaskDef stores useful information such as the name and input / output types of the TaskDef.

info

A TaskDef is like a method signature. It tells LittleHorse the method's name, what inputs it needs, and what output it gives back.

Creating a Task Worker

In this section, we will write the code for the Task Worker from the quickstart which executes the simple greet() method.

Project Setup

First, make sure you have the LittleHorse Server running in your local environment:

docker run --name littlehorse --rm -d -p 2023:2023 -p 8080:8080 ghcr.io/littlehorse-enterprises/littlehorse/lh-standalone:latest

Next, you can either choose to use the Quickstart or create a java project using your build tool of choice. Make sure to include the littlehorse-client dependency. For example, in Gradle, you should add the following to the dependencies section in build.gradle:

  implementation 'io.littlehorse:littlehorse-client:0.12.1'

For the purposes of this tutorial, we will be using the Quickstart project.

Writing the Task Method

Let's create a simple greeting TaskDef implementation:

info

In real life, your imagination is the limit as to what you can do inside a LittleHorse Task Method. Make an API call, talk to a database, call an LLM, whatever you want!

src/main/java/io/littlehorse/quickstart/Greeter.java
package io.littlehorse.quickstart;

import io.littlehorse.sdk.worker.LHTaskMethod;

public class Greeter {
@LHTaskMethod("greet")
public String greet(String name) {
return "Hello, " + name + "!";
}
}

The important part of the above code is the @LHTaskMethod("greet") annotation, which tells the LittleHorse SDK that the greet() method should be called when we encounter the TaskDef called greet. Other than that line, everything else is just Plain Old Java.

Registering the Task Worker

Before we can use our Task Worker in workflows, we need to register it with the LittleHorse Server by creating a TaskDef. The LittleHorse SDK ships with a useful LHTaskWorker object that makes it easy to do that. The following executable Main file acccomplishes that:

src/main/java/io/littlehorse/quickstart/Main.java
package io.littlehorse.quickstart;

import io.littlehorse.sdk.common.config.LHConfig;
import io.littlehorse.sdk.worker.LHTaskWorker;

public class Main {
public static void main(String[] args) {
// Create configuration from environment variables, which tells the SDK where to talk to LittleHorse.
LHConfig config = new LHConfig();

// Create and register the worker
LHTaskWorker worker = new LHTaskWorker(new GreetingWorker(), config);

// Create the Task Definition (`TaskDef`) in LittleHorse.
worker.registerTaskDef();
}
}

When you call LHTaskWorker#registerTaskDef(), the LittleHorse SDK inspects your @LHTaskMethod annotation and the method signature to automatically create a TaskDef in the LittleHorse Server. This registration process:

  • Creates a unique identifier for your TaskDef (greet in this case)
  • Records the input parameters and their types (String name in our example)
  • Records the return type (String)
  • Stores this information in the LittleHorse Server so it can be referenced by workflows

This registration only needs to be done once for each unique TaskDef. After registration, you can use this TaskDef in any number of WfSpecs, and multiple worker instances can process TaskRuns of this type.

Run this code using:

./gradlew run

If you navigate to your LittleHorse dashboard, you should see the greet TaskDef.

A TaskDef in LH Dashboard

Running the Worker

The last thing that remains is to run the Task Worker so that it can start listening for TaskRuns to execute. The following executable Main file can do that:

src/main/java/io/littlehorse/quickstart/Main.java
package io.littlehorse.quickstart;

import io.littlehorse.sdk.common.config.LHConfig;
import io.littlehorse.sdk.worker.LHTaskWorker;

public class Main {
public static void main(String[] args) {
LHConfig config = new LHConfig();
LHTaskWorker worker = new LHTaskWorker(new GreetingWorker(), config);
worker.start();
}
}

Run this code using:

./gradlew run

This will start the Task Worker and begin polling for TaskRuns to execute. Right now, it's not doing anything because we don't have any TaskRuns in the queue. TaskRuns will be added to the queue when we run a workflow that references the greet task and that TaskRun is the next step in the workflow.

Wrapping Up

In this tutorial, you learned about the basic building blocks used in a WfSpec: TaskDefs and Task Workers. Now that you have created your first Task Worker, continue on to the next lesson to learn how to use it inside a WfSpec.

In the meantime, if you haven't done so already: