### Clone LittleHorse examples repository and navigate to quickstart Source: https://littlehorse.io/docs/getting-started/quickstart This command clones the LittleHorse examples repository from GitHub and then changes the current directory into the 'quickstart' folder, which contains language-specific quickstart projects. ```Shell git clone https://github.com/littlehorse-enterprises/lh-examples.git cd lh-examples/quickstart ``` -------------------------------- ### Navigate to Python quickstart directory and set up virtual environment Source: https://littlehorse.io/docs/getting-started/quickstart Changes the current directory to the 'python' quickstart folder. It then creates a Python virtual environment, activates it, and installs required dependencies from 'requirements.txt' to prepare the environment for running the quickstart. ```Shell cd python python -m venv .venv source .venv/bin/activate # On Windows: .venv\Scripts\activate pip install -r requirements.txt ``` -------------------------------- ### Install LittleHorse CLI (lhctl) via Homebrew Source: https://littlehorse.io/docs/getting-started/quickstart This command uses Homebrew to install the LittleHorse Command Line Interface (CLI) tool, 'lhctl', which is used to interact with the LittleHorse Kernel. ```shell brew install littlehorse-enterprises/lh/lhctl ``` -------------------------------- ### Start LittleHorse Task Workers Source: https://littlehorse.io/docs/getting-started/quickstart Provides commands to start task workers in different programming languages (Java, Python, Go, C#) to process TaskRuns from LittleHorse's Task Queue. These workers are essential for WfRuns to progress. ```Java ./gradlew run --args workers ``` ```Python python -m quickstart.workers ``` ```Go go run ./src workers ``` ```C# dotnet run workers -f net9.0 ``` -------------------------------- ### Navigate to Go quickstart directory Source: https://littlehorse.io/docs/getting-started/quickstart Changes the current directory to the 'go' quickstart folder, which contains the Go-specific quickstart files for LittleHorse, including the executable entrypoint, workflow specification, and task workers. ```Shell cd go ``` -------------------------------- ### Navigate to C# quickstart directory Source: https://littlehorse.io/docs/getting-started/quickstart Changes the current directory to the 'csharp' quickstart folder, which contains the C#-specific quickstart files for LittleHorse, including the executable entrypoint, workflow specification, and task workers. ```Shell cd csharp ``` -------------------------------- ### Execute LittleHorse Workflow Run with lhctl Source: https://littlehorse.io/docs/getting-started/quickstart Demonstrates how to initiate a WfRun using the lhctl run command, passing initial arguments like first-name, last-name, and ssn to the quickstart WfSpec. ```bash lhctl run quickstart first-name Obi-Wan last-name Kenobi ssn 123456789 ``` -------------------------------- ### C#: Comprehensive LHConfig Setup Example Source: https://littlehorse.io/docs/server/developer-guide/client-configuration Provides a C# example demonstrating multiple ways to initialize LHConfig: from environment variables, a file path, or a dictionary. It also shows how to integrate a logger factory for logging. ```C# private static LHConfig GetLHConfig(string[] args, ILoggerFactory loggerFactory) { // LHConfig setup from LittleHorse env variables var config = new LHConfig(loggerFactory); // LHConfig setup from path file var userProfilePath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); string filePath = Path.Combine(userProfilePath, ".config/littlehorse.config"); if (File.Exists(filePath)) config = new LHConfig(filePath, loggerFactory); // LHConfig setup from dictionary if (args.Length > 0) { var lhConfigs = GetDictionaryFromMainArgs(args); config = new LHConfig(lhConfigs, loggerFactory); } return config; } ``` -------------------------------- ### Navigate to Java quickstart directory Source: https://littlehorse.io/docs/getting-started/quickstart Changes the current directory to the 'java' quickstart folder, which contains the Java-specific quickstart files for LittleHorse, including the executable entrypoint, workflow specification, and task workers. ```Shell cd java ``` -------------------------------- ### Run LittleHorse Kernel and Dashboard with Docker Source: https://littlehorse.io/docs/getting-started/quickstart This command starts a LittleHorse Kernel and dashboard in a Docker container for local development. It pulls the latest 'lh-standalone' image, names the container, removes it on exit, and maps ports 2023 (Kernel) and 8080 (Dashboard) to the host. ```shell docker run --pull always --name lh-standalone --rm -d -p 2023:2023 -p 8080:8080 \ ghcr.io/littlehorse-enterprises/littlehorse/lh-standalone:latest ``` -------------------------------- ### Create and Start a LittleHorse Task Worker in Go Source: https://littlehorse.io/docs/server/developer-guide/task-worker-development This Go example illustrates how to create and run a LittleHorse Task Worker. It defines a `Greet` function as the task handler and then uses `littlehorse.NewConfigFromEnv()` to configure, `littlehorse.NewTaskWorker()` to create the worker, and finally `RegisterTaskDef()` and `Start()` to register the task definition and begin task execution. ```Go package main import ( "github.com/littlehorse-enterprises/littlehorse/sdk-go/littlehorse" ) func Greet(firstName string) string { return "Hello there, " + firstName + "!" } func main() { config := littlehorse.NewConfigFromEnv() worker, _ := littlehorse.NewTaskWorker(config, Greet, "greet") worker.RegisterTaskDef() worker.Start() } ``` -------------------------------- ### Run Registered WfSpec using lhctl Command Source: https://littlehorse.io/docs/server/developer-guide/wfspec-development/basics This command-line example shows how to execute a previously registered `WfSpec` named 'my-wfspec' using the `lhctl` tool, providing a value for the 'first-name' input variable. This command initiates a workflow run. ```bash lhctl run my-wfspec first-name Obi-Wan ``` -------------------------------- ### Install LittleHorse Kubernetes Operator with Helm Source: https://littlehorse.io/docs/for-kubernetes/littlehorse/quickstart Updates Helm repositories and installs the LittleHorse Kubernetes Operator, bundling Strimzi for Kafka management. This command specifies the operator version, namespace, image repository, tag, enables Strimzi deployment, and references the image pull secret. ```bash helm repo update helm upgrade --install lh \ --version 0.13.0 \ --namespace littlehorse \ --set image.repository=quay.io/littlehorse/lh-operator \ --set image.tag=0.13.0 \ --set strimzi.deploy=true \ --set strimzi.enabled=true \ --set 'imagePullSecrets[0].name=littlehorse-pull-secret' \ littlehorse/lh-operator ``` -------------------------------- ### Create and Start a LittleHorse Task Worker in Java Source: https://littlehorse.io/docs/server/developer-guide/task-worker-development This Java example demonstrates how to set up a LittleHorse Task Worker. It defines a `MyWorker` class with an `@LHTaskMethod("greet")` annotated method that takes a string and returns a greeting. The `main` method initializes `LHConfig`, creates an `LHTaskWorker`, registers the `greet` TaskDef, and starts the worker to poll for tasks. It also includes a shutdown hook. ```Java package io.littlehorse.quickstart; import java.io.IOException; import io.littlehorse.sdk.common.config.LHConfig; import io.littlehorse.sdk.worker.LHTaskMethod; import io.littlehorse.sdk.worker.LHTaskWorker; class MyWorker { @LHTaskMethod("greet") public String greeting(String firstName) { String result = "Hello there, " + firstName + "!"; System.out.println(result); return result; } } public class Main { public static void main(String[] args) throws IOException, InterruptedException { LHConfig config = new LHConfig(); MyWorker executable = new MyWorker(); LHTaskWorker greetWorker = new LHTaskWorker(executable, "greet", config); Runtime.getRuntime().addShutdownHook(new Thread(greetWorker::close)); greetWorker.registerTaskDef(); greetWorker.start(); } } ``` -------------------------------- ### Define and Register a LittleHorse Task Worker in C# Source: https://littlehorse.io/docs/server/developer-guide/task-worker-development This C# example demonstrates how to define a task method using the `[LHTaskMethod]` attribute and how to set up and register an `LHTaskWorker` with the LittleHorse SDK. It illustrates the basic steps to create a worker that can execute a 'greet' task, including configuration and starting the worker. ```csharp using LittleHorse.Sdk.Worker; namespace Examples.BasicExample { public class MyWorker { [LHTaskMethod("greet")] public string Greeting(string name) { var message = $"Hello there {name}!"; Console.WriteLine($"Executing task greet: " + message); return message; } } public class Program { static void Main(string[] args) { var config = new LHConfig(); MyWorker executable = new MyWorker(); var worker = new LHTaskWorker(executable, "greet", config); worker.RegisterTaskDef(); Thread.Sleep(1000); worker.Start(); } } } ``` -------------------------------- ### LittleHorse Kernel and lhctl Installation Source: https://littlehorse.io/docs/server/concepts/user-tasks Commands to install the LittleHorse command-line interface (`lhctl`) and run a local LittleHorse Kernel instance using Docker. These steps are prerequisites for executing the provided code examples. ```bash brew install littlehorse-enterprises/lh/lhctl ``` ```bash docker run --rm -d --name littlehorse --pull always -p 2023:2023 -p 8080:8080 ghcr.io/littlehorse-enterprises/littlehorse/lh-standalone:latest ``` -------------------------------- ### Add LittleHorse Helm Repository Source: https://littlehorse.io/docs/for-kubernetes/littlehorse/quickstart Adds the LittleHorse Operator's Helm chart repository to your local Helm configuration, enabling you to fetch and install LittleHorse charts for Kubernetes deployments. ```bash helm repo add littlehorse https://littlehorse-enterprises.github.io/lh-helm-charts/ ``` -------------------------------- ### Configuring and Accessing LittleHorse with lhctl Source: https://littlehorse.io/docs/for-kubernetes/littlehorse/quickstart This section provides the necessary configuration for lhctl to connect to your LittleHorse cluster, including an example littlehorse.config file. It also includes the kubectl command to port-forward the LittleHorse server service and a lhctl command to test connectivity. ```Text LHC_API_HOST=localhost LHC_API_PORT=2023 ``` ```Bash kubectl port-forward svc/quickstart-server -n littlehorse 2023:2023 ``` ```Bash lhctl whoami ``` -------------------------------- ### Clone and Navigate LittleHorse Quickstart Projects Source: https://littlehorse.io/docs/getting-started/your-first-task-worker Provides commands to clone and navigate into the LittleHorse quickstart repositories for various programming languages, preparing the environment for Task Worker development. ```Bash git clone https://github.com/littlehorse-enterprises/lh-quickstart-java.git cd lh-quickstart-java ``` ```Bash git clone https://github.com/littlehorse-enterprises/lh-quickstart-python.git cd lh-quickstart-python ``` ```Bash git clone https://github.com/littlehorse-enterprises/lh-quickstart-go.git cd lh-quickstart-go ``` ```Bash git clone https://github.com/littlehorse-enterprises/lh-quickstart-dotnet.git cd lh-quickstart-dotnet ``` -------------------------------- ### Register LittleHorse Workflow Specification and Task Definitions Source: https://littlehorse.io/docs/getting-started/quickstart These commands register the Workflow Specification (WfSpec) and Task Definitions (TaskDef) with LittleHorse. This process creates an 'identity_verified' ExternalEventDef, 'verify_identity', 'notify_customer_verified', and 'notify_customer_not_verified' TaskDefs, and a 'quickstart' WfSpec, which acts as a blueprint for a business process. ```Shell ./gradlew run --args register ``` ```Shell python -m quickstart.register ``` ```Shell go run ./src register ``` ```Shell # Use either `net8.0` or `net9.0` dotnet run register -f net9.0 ``` -------------------------------- ### Create and Start a LittleHorse Task Worker in Python Source: https://littlehorse.io/docs/server/developer-guide/task-worker-development This Python example demonstrates how to implement an asynchronous LittleHorse Task Worker. It defines an `async` `greeting` function as the task handler. The `main` function initializes `LHConfig`, creates an `LHTaskWorker`, registers the task definition, and then uses `asyncio` to start the worker, allowing it to poll for and execute tasks. ```Python import asyncio import littlehorse from littlehorse.config import LHConfig from littlehorse.worker import LHTaskWorker async def greeting(first_name: str) -> str: msg = f"Hello there, {first_name}!" print(msg) return msg async def main() -> None: config = LHConfig() worker = LHTaskWorker(greeting, "greet", config) worker.register_task_def() await asyncio.sleep(1.0) await littlehorse.start(worker) if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Verify LittleHorse Kernel Connectivity with lhctl Source: https://littlehorse.io/docs/getting-started/quickstart This command verifies connectivity to the running LittleHorse Kernel using 'lhctl'. A successful response, like the JSON output shown, indicates that the CLI can communicate with the Kernel. ```shell >lhctl whoami { "id": { "id": "anonymous" }, "createdAt": "2024-12-17T00:12:10.693Z", "perTenantAcls": {}, "globalAcls": { "acls": [ { "resources": [ "ACL_ALL_RESOURCES" ], "allowedActions": [ "ALL_ACTIONS" ], "name": "" } ] } } ``` -------------------------------- ### Python Example: Create and Get UserTaskDef Source: https://littlehorse.io/docs/server/developer-guide/grpc/managing-metadata This Python example illustrates how to manually build a `PutUserTaskDefRequest` with `UserTaskField` objects to define a `UserTaskDef`. It then demonstrates creating the `UserTaskDef` and retrieving it using its name and version. ```Python from littlehorse import create_external_event_def from littlehorse.config import LHConfig from littlehorse.model import * from google.protobuf.json_format import MessageToJson from time import sleep if __name__ == '__main__': # Get the grpc client config = LHConfig() client = config.stub() # Manually construct the PutUserTaskDefRequest, specifying the fields we want # the UserTaskRun's to have. put_user_task_def_req = PutUserTaskDefRequest( name="my-user-task-def", fields=[ UserTaskField( name="isApproved", description="Is the request Approved?", display_name="Approved?", required=True, ), UserTaskField( name="explanation", description="Explanation or comments for decision.", required=False, display_name="Comments", ) ] ) # Create the UserTaskDef client.PutUserTaskDef(put_user_task_def_req); # Wait for metadata to propagate sleep(0.5) # Get the UserTaskDef user_task_def_id = UserTaskDefId(name="my-user-task-def", version=0) ``` -------------------------------- ### OpenID Connect (OIDC) Provider Configuration Example Source: https://littlehorse.io/docs/user-tasks-bridge/backend/configuration Example YAML configuration for setting up multiple OpenID Connect (OIDC) identity providers with the User Tasks Bridge. It defines issuer URLs, login labels, username/user ID claims, authority paths, vendor, tenant ID, client ID claims, and associated client IDs for each provider. ```YAML com: c4-soft: springaddons: oidc: ops: # First OIDC provider configuration - iss: label-name: username-claim: user-id-claim: authorities: - path: $.jsonPath1WhereRolesAre - path: $.jsonPath2WhereRolesAre vendor: tenant-id: client-id-claim: clients: - - # Second OIDC provider configuration - iss: label-name: username-claim: user-id-claim: authorities: - path: $.jsonPath1WhereRolesAre - path: $.jsonPath2WhereRolesAre vendor: tenant-id: client-id-claim: clients: - ``` -------------------------------- ### Iterate Through Paginated TaskRuns Source: https://littlehorse.io/docs/server/developer-guide/grpc/basics This example demonstrates how to fetch and process paginated lists of `TaskRun`s. It uses the `bookmark` from a previous response to retrieve the next page of results, ensuring all available TaskRuns are processed in batches defined by `limit`. ```Java package io.littlehorse.quickstart; import java.io.IOException; import io.littlehorse.sdk.common.LHLibUtil; import io.littlehorse.sdk.common.config.LHConfig; import io.littlehorse.sdk.common.proto.LittleHorseGrpc.LittleHorseBlockingStub; import io.littlehorse.sdk.common.proto.SearchTaskRunRequest; import io.littlehorse.sdk.common.proto.TaskRunId; import io.littlehorse.sdk.common.proto.TaskRunIdList; public class Main { public static void main(String[] args) throws IOException { LHConfig config = new LHConfig(); LittleHorseBlockingStub client = config.getBlockingStub(); TaskRunIdList results = client.searchTaskRun(SearchTaskRunRequest.newBuilder() .setTaskDefName("greet") .setLimit(5) .build()); processTaskRuns(results); while (results.hasBookmark()) { results = client.searchTaskRun(SearchTaskRunRequest.newBuilder() .setTaskDefName("greet") .setLimit(5) .setBookmark(results.getBookmark()) .build()); processTaskRuns(results); } } private static void processTaskRuns(TaskRunIdList taskRuns) { System.out.println("Processing a batch of size: " + taskRuns.getResultsCount()); for (TaskRunId taskRun : taskRuns.getResultsList()) { System.out.println(LHLibUtil.protoToJson(taskRun)); } } } ``` ```Go package main import ( "context" "fmt" "strconv" "github.com/littlehorse-enterprises/littlehorse/sdk-go/littlehorse" "github.com/littlehorse-enterprises/littlehorse/sdk-go/lhproto" // Use the gRPC utilities to inspect gRPC errors ) func main() { // Get a client config := littlehorse.NewConfigFromEnv() client, _ := config.GetGrpcClient() limit := int32(5) req := lhproto.SearchTaskRunRequest{ TaskDefName: "greet", Limit: &limit, } results, _ := (*client).SearchTaskRun(context.Background(), &req) processTaskRuns(results) // For some reason GoLang decided to use `for` instead of `while`... for results.Bookmark != nil { req.Bookmark = results.Bookmark results, _ = (*client).SearchTaskRun(context.Background(), &req) processTaskRuns(results) } } func processTaskRuns(taskRuns *lhproto.TaskRunIdList) { fmt.Println("Processing a batch of size " + strconv.Itoa(len(taskRuns.Results))) for _, taskRunId := range taskRuns.Results { littlehorse.PrintProto(taskRunId) } } ``` ```Python from littlehorse.config import LHConfig from littlehorse.model import * from google.protobuf.json_format import MessageToJson def process_task_runs(task_run_ids: TaskRunIdList): print("Processing a batch of size " + str(len(task_run_ids.results))) for task_run_id in task_run_ids.results: print(MessageToJson(task_run_id)) if __name__ == '__main__': config = LHConfig() client = config.stub() results: TaskRunIdList = client.SearchTaskRun(SearchTaskRunRequest( task_def_name="greet", limit=5, )) process_task_runs(results) # the `HasField()` method is the proper way to check for presence of an # `optional` field in python Protobuf. while results.HasField("bookmark"): new_request = SearchTaskRunRequest( task_def_name="greet", limit=5, # pass in the bookmark from the previous call bookmark=results.bookmark, ) results = client.SearchTaskRun(new_request) process_task_runs(results) ``` ```C# using LittleHorse.Sdk; using LittleHorse.Sdk.Common.Proto; public class Program { static void Main(string[] args) ``` -------------------------------- ### Example JSON Output for lhctl WfRun Execution Source: https://littlehorse.io/docs/getting-started/executing-a-wfrun Shows the typical JSON response received after executing a `WfRun` using `lhctl`, detailing the `WfRun`'s ID, `WfSpec` details, current status, start time, and thread run information. ```json { "id": { "id": "69881bf9aaf84c2f84bdde7ceb2dd105" }, "wfSpecId": { "name": "quickstart", "majorVersion": 0, "revision": 0 }, "oldWfSpecVersions": [], "status": "RUNNING", "greatestThreadrunNumber": 0, "startTime": "2025-01-07T01:53:47.212Z", "threadRuns": [ { "wfSpecId": { "name": "quickstart", "majorVersion": 0, "revision": 0 }, "number": 0, "status": "RUNNING", "threadSpecName": "entrypoint", "startTime": "2025-01-07T01:53:47.296Z", "childThreadIds": [], "haltReasons": [], "currentNodePosition": 1, "handledFailedChildren": [], "type": "ENTRYPOINT" } ], "pendingInterrupts": [], "pendingFailures": [] } ``` -------------------------------- ### Confluent Cloud API Key File Example Source: https://littlehorse.io/docs/server/operations/docker-compose/confluent-cloud An example of the content found in a downloaded Confluent Cloud API key file. This file contains the API key, API secret, and the bootstrap server address necessary for connecting to your Confluent Cloud cluster. ```plaintext === Confluent Cloud API key: lkc-0595zp === API key: XXXXXXXXXXXXXXXX API secret: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Bootstrap server: pkc-n98pk.us-west-2.aws.confluent.cloud:9092 ``` -------------------------------- ### Create and Start a LittleHorse Task Worker in C# Source: https://littlehorse.io/docs/server/developer-guide/task-worker-development This section outlines the steps to create a LittleHorse Task Worker in C#. It involves creating an `LHConfig`, defining a Task Worker class with an `LHTaskMethod` attribute, instantiating `LHTaskWorker`, registering the `TaskDef`, and finally starting the worker to process tasks. Note: The provided code snippet is incomplete. ```C# using LittleHorse.Sdk; ``` -------------------------------- ### Install `lhctl` CLI on Mac/Linux via Homebrew Source: https://littlehorse.io/docs/cloud/accessing-littlehorse-cloud-orchestrator This command installs the LittleHorse command-line interface (`lhctl`) on macOS and Linux systems using the Homebrew package manager, simplifying the setup process. ```bash brew install littlehorse-enterprises/lh/lhctl ``` -------------------------------- ### Throwing LittleHorse Business Exception with Content Source: https://littlehorse.io/docs/server/developer-guide/task-worker-development This example demonstrates how to throw an `LHTaskException` that includes additional content, such as the number of days until an item is back in stock. This content can be accessed by Failure Handlers, providing more context for specific business failures. ```Java package io.littlehorse.quickstart; import io.littlehorse.sdk.common.exception.LHTaskException; import io.littlehorse.sdk.worker.LHTaskMethod; class MyWorker { @LHTaskMethod("ship-item") public String shipItem(String itemSku) { if (isOutOfStock(itemSku)) { int daysUntilBackInStock = calculateDaysUntilBackInStock(itemSku); // The `content` of the `Failure` that is thrown will be an INT variable containing // the number of days until the item is expected to be back in stock. throw new LHTaskException( "out-of-stock", "Some human readable message", daysUntilBackInStock); } return "Item " + itemSku + " successfully shipped!"; } } ``` ```Go package quickstart import ( "github.com/littlehorse-enterprises/littlehorse/sdk-go/lhproto" "github.com/littlehorse-enterprises/littlehorse/sdk-go/littlehorse" ) ``` -------------------------------- ### Post External Event to LittleHorse Workflow with lhctl Source: https://littlehorse.io/docs/getting-started/quickstart Illustrates how to post an external event, identity-verified, to a running WfRun using the lhctl postEvent command. This unblocks workflows waiting for specific external triggers. ```bash lhctl postEvent identity-verified BOOL true ``` -------------------------------- ### Define and Register WfSpec with Greet TaskDef Source: https://littlehorse.io/docs/server/developer-guide/wfspec-development/basics This code demonstrates how to define a `WfSpec` named 'my-wfspec' that declares a required 'first-name' string variable and executes the 'greet' TaskDef with this variable as an argument. It includes the necessary steps to compile and register the `WfSpec` with the LittleHorse cluster. Ensure the 'greet' `TaskDef` is pre-registered. ```Java package io.littlehorse.quickstart; import java.io.IOException; import io.littlehorse.sdk.common.config.LHConfig; import io.littlehorse.sdk.wfsdk.WfRunVariable; import io.littlehorse.sdk.wfsdk.Workflow; import io.littlehorse.sdk.wfsdk.WorkflowThread; import io.littlehorse.sdk.common.proto.VariableType; public class Main { public static void main(String[] args) throws IOException, InterruptedException { LHConfig config = new LHConfig(); // The `Workflow` object uses the DSL to compile the WfSpec Workflow workflowGenerator = Workflow.newWorkflow("my-wfspec", Main::wfLogic); // Convenience method to register the `WfSpec` automatically. workflowGenerator.registerWfSpec(config.getBlockingStub()); } // NOTE: this can be static or non-static. static void wfLogic(WorkflowThread wf) { // Required input variable. WfRunVariable firstName = wf.declareStr("first-name").required(); // Execute the `greet` Task and pass in `first-name` as an argument. wf.execute("greet", firstName); } } ``` ```Go package main import ( "context" "log" "github.com/littlehorse-enterprises/littlehorse/sdk-go/littlehorse" "github.com/littlehorse-enterprises/littlehorse/sdk-go/lhproto" ) func wfLogic(wf *littlehorse.WorkflowThread) { firstName := wf.DeclareStr("first-name").Required() wf.Execute("greet", firstName) } func main() { // Get a client config := littlehorse.NewConfigFromEnv() client, _ := config.GetGrpcClient() workflowGenerator := littlehorse.NewWorkflow(wfLogic, "my-wfspec") request, err := workflowGenerator.Compile() if err != nil { log.Fatal(err) } (*client).PutWfSpec(context.Background(), request) } ``` ```Python from littlehorse.workflow import WorkflowThread, WfRunVariable, Workflow from littlehorse.config import LHConfig from littlehorse.model import VariableType, PutWfSpecRequest def workflow_logic(wf: WorkflowThread) -> None: first_name: WfRunVariable = wf.declare_str("first-name").required() wf.execute("greet", first_name) if __name__ == '__main__': config = LHConfig() client = config.stub() workflow_generator = Workflow("my-wfspec", workflow_logic) request: PutWfSpecRequest = workflow_generator.compile() client.PutWfSpec(request) ``` ```C# using LittleHorse.Sdk; using LittleHorse.Sdk.Common.Proto; using LittleHorse.Sdk.Workflow.Spec; public class Program { static void Main(string[] args) { var config = new LHConfig(); var lhClient = config.GetGrpcClientInstance(); var workflow = new Workflow("my-wfspec", WfLogic); workflow.RegisterWfSpec(lhClient); } // NOTE: this can be static or non-static. static void WfLogic(WorkflowThread wf) { // Required input variable. WfRunVariable firstName = wf.DeclareStr("first-name").Required(); // Execute the `greet` Task and pass in `first-name` as an argument. wf.Execute("greet", firstName); } } ``` -------------------------------- ### CLI: Example littlehorse.config File Source: https://littlehorse.io/docs/server/developer-guide/client-configuration Illustrates the structure of a `littlehorse.config` file used by the `lhctl` CLI, specifying the API host and port for connection. ```INI LHC_API_HOST=localhost LHC_API_PORT=2023 ``` -------------------------------- ### lhctl Run Workflow - Second User ID Example Source: https://littlehorse.io/docs/server/concepts/variables An additional example of running the `variables-example` workflow with a different user ID (`obiwan`) to create more data for demonstrating variable searching capabilities. ```lhctl lhctl run variables-example user-id obiwan ``` -------------------------------- ### Pass WfRunVariables as Task Inputs Source: https://littlehorse.io/docs/server/developer-guide/wfspec-development/basics Shows how to declare `WfRunVariable` instances (string and integer) and then use these variables as inputs when executing a task. ```Java public void threadFunction(WorkflowThread thread) { WfRunVariable myStr = thread.declareStr("my-str"); WfRunVariable myInt = thread.declareInt("my-int"); thread.execute("foo", myStr, myInt); } ``` ```Go func threadFunction(thread *littlehorse.WorkflowThread) { myStr := thread.DeclareStr("my-str") myInt := thread.DeclareInt("my-int") thread.Execute("foo", myStr, myInt) } ``` ```Python def thread_function(thread: WorkflowThread) -> None: my_str = thread.declare_str("my-str") my_int = thread.declare_str("my-int") thread.execute("foo", my_str, my_int) ``` ```C# public void ThreadFunction(WorkflowThread thread) { WfRunVariable myStr = thread.DeclareStr("my-str"); WfRunVariable myInt = thread.DeclareStr("my-int"); thread.Execute("foo", myStr, myInt); } ``` -------------------------------- ### Initialize and Start LittleHorse Task Worker in Go Source: https://littlehorse.io/docs/getting-started/your-first-task-worker This Go code snippet demonstrates how to set up and run a LittleHorse Task Worker. It creates a new TaskWorker using a configuration derived from environment variables, registers its task definition, and then starts the worker. ```Go package main import ( "github.com/littlehorse-enterprises/littlehorse/sdk-go/littlehorse" ) var config = littlehorse.NewConfigFromEnv() func main() { greetingWorker, _ := littlehorse.NewTaskWorker(config, NormalGoMethod, "greet") greetingWorker.RegisterTaskDef() greetingWorker.Start() } ``` -------------------------------- ### Verify LittleHorse Operator Pods Status Source: https://littlehorse.io/docs/for-kubernetes/littlehorse/quickstart Checks the status of the deployed LittleHorse Operator and Strimzi Cluster Operator pods within the 'littlehorse' namespace, confirming they are running successfully after installation. ```bash kubectl get pods -nlittlehorse NAME READY STATUS RESTARTS AGE lh-lh-operator-676687bff8-jdl56 1/1 Running 0 24s strimzi-cluster-operator-6948497896-w7cx7 1/1 Running 0 38s ``` -------------------------------- ### Verify LittleHorse CLI and Kernel Server Status Source: https://littlehorse.io/docs/server/developer-guide/install After the `lh-standalone` Docker container is running, execute this command to check the version of the `lhctl` utility and confirm that the LittleHorse Kernel server is active and reporting its version. Note that the server might take 20-40 seconds to start. ```Shell lhctl version ``` -------------------------------- ### Install User Tasks Bridge API Client Source: https://littlehorse.io/docs/user-tasks-bridge/api-client Commands to install the User Tasks Bridge API Client using various package managers like npm, yarn, pnpm, and bun. ```sh npm install @littlehorse-enterprises/user-tasks-bridge-api-client ``` ```sh yarn add @littlehorse-enterprises/user-tasks-bridge-api-client ``` ```sh pnpm add @littlehorse-enterprises/user-tasks-bridge-api-client ``` ```sh bun add @littlehorse-enterprises/user-tasks-bridge-api-client ``` -------------------------------- ### Run LittleHorse Java Task Worker with Gradle Source: https://littlehorse.io/docs/getting-started/your-first-task-worker This command executes the LittleHorse Java Task Worker using Gradle. It assumes a standard Gradle project setup where `gradlew run` is configured to start the main application. ```Shell ./gradlew run ``` -------------------------------- ### Pass Hard-coded Input Variables to a Task Source: https://littlehorse.io/docs/server/developer-guide/wfspec-development/basics Demonstrates how to pass hard-coded string and integer values directly as input arguments when executing a task using `thread.execute()`. ```Java String inputStrVal = "input string value!"; int inputIntVal = 54321; thread.execute("foo", inputStrVal, inputIntVal); ``` ```Go inputStrVal := "input string value!" inputIntVal := 54321 thread.Execute("foo", inputStrVal, inputIntVal) ``` ```Python str_val = "input string value!" int_val = 54321 thread.execute("foo", str_val, int_val) ``` ```C# string inputStrVal = "input string value!"; int inputIntVal = 54321; thread.Execute("foo", inputStrVal, inputIntVal); ``` -------------------------------- ### Run LittleHorse Kernel for Local Development using Docker Source: https://littlehorse.io/docs/server/developer-guide/install This Docker command starts a `lh-standalone` container, which includes the LittleHorse Kernel. It's designed for local development, pulling the latest image and mapping necessary ports for access. ```Shell docker run --pull always --name littlehorse -d -p 2023:2023 -p 8080:8080 ghcr.io/littlehorse-enterprises/littlehorse/lh-standalone:latest ``` -------------------------------- ### Go Example: Create UserTaskDef Source: https://littlehorse.io/docs/server/developer-guide/grpc/managing-metadata This Go example shows how to programmatically construct a `PutUserTaskDefRequest` to define a `UserTaskDef` with specified fields and a description, then register it with the LittleHorse client. ```Go config := littlehorse.NewConfigFromEnv() client, err := config.GetGrpcClient() description := "this is a cool usertaskdef!" result, err := (*client).PutUserTaskDef(context.Background(), &lhproto.PutUserTaskDefRequest{ Name: "my-user-task", Fields: []*lhproto.UserTaskField{ &lhproto.UserTaskField{ Name: "my-first-int-field", Type: lhproto.VariableType_INT, }, &lhproto.UserTaskField{ Name: "my-second-str-field", Type: lhproto.VariableType_STR, }, }, Description: &description, }, ) ``` -------------------------------- ### Execute a Registered Task Node Source: https://littlehorse.io/docs/server/developer-guide/wfspec-development/basics Shows how to execute a pre-registered `TaskDef` using the `WorkflowThread::execute()` method. It emphasizes that the task must be registered and a Task Worker must be polling for it. ```Java public void myWf(WorkflowThread thread) { NodeOutput output = thread.execute("foo"); } ``` ```Go func myThreadFunc(thread *littlehorse.WorkflowThread) { taskOutput := thread.Execute("foo") } ``` ```Python def thread_function(thread: WorkflowThread) -> None: thread.execute("foo") ``` ```C# static void MyWf(WorkflowThread thread) { NodeOutput output = thread.Execute("foo"); } ``` -------------------------------- ### Access LittleHorse gRPC Client and Put External Event Definition Source: https://littlehorse.io/docs/server/developer-guide/grpc/basics This snippet demonstrates how to initialize the LittleHorse SDK configuration, obtain a gRPC client, construct a `PutExternalEventDefRequest` protobuf with a specified name, and execute the request to define an external event. The result, an `ExternalEventDef` object, is then printed. This example uses environment variables for configuration and relies on pre-compiled protobufs shipped with the SDKs. ```Java package io.littlehorse.quickstart; import java.io.IOException; import io.littlehorse.sdk.common.LHLibUtil; import io.littlehorse.sdk.common.config.LHConfig; import io.littlehorse.sdk.common.proto.LittleHorseGrpc.LittleHorseBlockingStub; // All protobuf objects can be found in this package. import io.littlehorse.sdk.common.proto.ExternalEventDef; import io.littlehorse.sdk.common.proto.PutExternalEventDefRequest; public class Main { public static void main(String[] args) throws IOException { // First, create an LHConfig. Using the default constructor loads the // configurations from your environment variables. LHConfig config = new LHConfig(); // Get a gRPC client. Java gRPC has two types: "Blocking" and regular. // "Blocking" stubs are easier to work with as they are synchronous. LittleHorseBlockingStub client = config.getBlockingStub(); // Build the request PutExternalEventDefRequest req = PutExternalEventDefRequest.newBuilder() .setName("my-external-event") .build(); // Make the request ExternalEventDef result = client.putExternalEventDef(req); // Print the result in JSON format System.out.println(LHLibUtil.protoToJson(result)); } } ``` ```Go package main import ( "context" "log" // Littlehorse functions are found in this package "github.com/littlehorse-enterprises/littlehorse/sdk-go/littlehorse" // All protobuf data structs and gRPC clients are found in this package "github.com/littlehorse-enterprises/littlehorse/sdk-go/lhproto" ) func main() { // Create a config using the environment variables. config := littlehorse.NewConfigFromEnv() // Load the client client, err := config.GetGrpcClient() if err != nil { log.Fatal(err) } // Create the request protobuf structure req := &lhproto.PutExternalEventDefRequest{ Name: "my-external-event-def", } // Make the request var result *lhproto.ExternalEventDef result, err = (*client).PutExternalEventDef(context.Background(), req) littlehorse.PrintProto(result) } ``` ```Python from littlehorse.config import LHConfig # All protobuf models are in this package from littlehorse.model import LittleHorseStub, PutExternalEventDefRequest, ExternalEventDef # You can use this utility to print protobuf prettily (: from google.protobuf.json_format import MessageToJson if __name__ == '__main__': # Create a config object using the environment variables. config: LHConfig = LHConfig() # Create the gRPC Client (in gRPC, a client is called a "stub") client: LittleHorseStub = config.stub() # Formulate the request, which is a protobuf object. request = PutExternalEventDefRequest(name="my-external-event-def") # Make the request! result: ExternalEventDef = client.PutExternalEventDef(request) # Print it out print(MessageToJson(result)) ``` ```C# using LittleHorse.Sdk; // All protobuf objects can be found in this namespace. using LittleHorse.Sdk.Common.Proto; public class Program { static void Main(string[] args) { // First, create an LHConfig. Using the default constructor loads the // configurations from your environment variables. var config = new LHConfig(); // Get a gRPC Client var lhClient = config.GetGrpcClientInstance(); // Create the request var externalEventRequest = new PutExternalEventDefRequest {Name = "my-external-event"}; // Make the request var result = lhClient.PutExternalEventDef(externalEventRequest); // Print the result in JSON format Console.WriteLine($"External event: {result}"); } } ``` -------------------------------- ### Install `lhctl` CLI from GoLang source Source: https://littlehorse.io/docs/cloud/accessing-littlehorse-cloud-orchestrator This command compiles and installs the `lhctl` CLI directly from its GoLang source code. Users must ensure their Go binary path (`~/go/bin/`) is included in their system's PATH environment variable for the command to be accessible. ```bash go install github.com/littlehorse-enterprises/littlehorse/lhctl@0.10.0 ``` -------------------------------- ### Initialize and Start LittleHorse Task Worker in Java Source: https://littlehorse.io/docs/getting-started/your-first-task-worker This Java code snippet demonstrates how to create and start a LittleHorse Task Worker. It initializes an LHTaskWorker with a Greeter task, registers the task definition, and then starts the worker to listen for TaskRuns. ```Java package io.littlehorse.quickstart; import io.littlehorse.sdk.common.config.LHConfig; import io.littlehorse.sdk.worker.LHTaskWorker; public class Main { static LHConfig config = new LHConfig(); public static void main(String[] args) { LHTaskWorker worker = new LHTaskWorker(new Greeter(), "greet", config); worker.registerTaskDef(); worker.start(); } } ``` -------------------------------- ### C# LittleHorse Task Worker Setup and Registration Source: https://littlehorse.io/docs/server/concepts/variables This C# `Main` method demonstrates how to set up and register LittleHorse task workers. It initializes `LHConfig`, creates instances of `LHTaskWorker` for 'send-email' and 'fetch-user' tasks, registers their definitions with the LittleHorse cluster, and then starts the workers to begin processing tasks. ```C# public abstract class Program { static void Main(string[] args) { var config = new LHConfig(); MyTasks myFuncs = new MyTasks(); LHTaskWorker emailer = new LHTaskWorker(myFuncs, "send-email", config); LHTaskWorker userService = new LHTaskWorker(myFuncs, "fetch-user", config); emailer.RegisterTaskDef(); userService.RegisterTaskDef(); emailer.Start(); userService.Start(); } } ``` -------------------------------- ### Initialize and Start LittleHorse Task Worker in Python Source: https://littlehorse.io/docs/getting-started/your-first-task-worker This Python code defines an asynchronous method `normal_python_method` that acts as the task. It then initializes a LHTaskWorker with this method and starts it using `asyncio.run`, allowing the worker to process 'greet' tasks. ```Python import asyncio import littlehorse from littlehorse.worker import WorkerContext, LHTaskWorker from littlehorse.config import LHConfig async def normal_python_method(name: str, ctx: WorkerContext) -> str: return f"Hello, {name}!" config = LHConfig() async def main() -> None: await littlehorse.start(LHTaskWorker(normal_python_method, "greet", config)) if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Register and Run LittleHorse TaskDef and Worker Source: https://littlehorse.io/docs/server/concepts/external-events This set of code snippets demonstrates how to define a `TaskDef` (named 'greet') and simultaneously deploy a corresponding `TaskWorker` using the LittleHorse SDK across various programming languages. The worker is designed to execute `TaskRun`s for the 'greet' `TaskDef` once a `WfRun` is initiated. The examples show how to define the task method, configure the LittleHorse client, register the `TaskDef` with the server, and start the worker process, including graceful shutdown mechanisms where applicable. ```Java package io.littlehorse.quickstart; import io.littlehorse.sdk.common.config.LHConfig; import io.littlehorse.sdk.worker.LHTaskMethod; import io.littlehorse.sdk.worker.LHTaskWorker; class Greeter { @LHTaskMethod("greet") public String greet(String name) { String result = "Hello, " + name + "!"; System.out.println(result); return result; } } public class Main { public static void main(String[] args) { LHConfig config = new LHConfig(); // Create a Task Worker LHTaskWorker worker = new LHTaskWorker(new Greeter(), "greet", config); Runtime.getRuntime().addShutdownHook(new Thread(worker::close)); // Register the TaskDef worker.registerTaskDef(); // Start the Worker worker.start(); } } ``` ```Python import littlehorse from littlehorse import create_task_def from littlehorse.worker import LHTaskWorker from littlehorse.config import LHConfig import asyncio config = LHConfig() #define the task method async def greet(name: str) -> str: result = "Hello there " + name + "!" print(result) return result async def main(): #create a task worker greeter = LHTaskWorker(greet, "greet", config) #start the worker await littlehorse.start(greeter) if __name__ == "__main__": #register the task def with the littlehorse server create_task_def(greet, "greet", config) asyncio.run(main()) ``` ```Go import ( "fmt" "github.com/littlehorse-enterprises/littlehorse/sdk-go/littlehorse" ) func Greet(name string) string { result := "Hello, " + name + "!" fmt.Println(result) return result } func main() { config := littlehorse.NewConfigFromEnv() //Create Task Worker worker, _ := littlehorse.NewTaskWorker(config, Greet, "greet") //Register TaskDef worker.RegisterTaskDef() //Start the worker worker.Start() } ``` ```C# using LittleHorse.Sdk; using LittleHorse.Sdk.Worker; namespace Quickstart; class Greeter { [LHTaskMethod("greet")] public string Greet(string name) { string result = $"Hello, {name}!"; Console.WriteLine(result); return result; } } public class Program { static void Main(string[] args) { var config = new LHConfig(); // Create a Task Worker var worker = new LHTaskWorker(new Greeter(), "greet", config); // Register the TaskDef worker.RegisterTaskDef(); AppDomain.CurrentDomain.ProcessExit += (sender, e) => { // Close processes gracefully, for worker does a call to the server, and it could be some disconnections. worker.Close(); }; // Start the Worker worker.Start(); } } ``` -------------------------------- ### Install LittleHorse CLI with Homebrew Source: https://littlehorse.io/docs/server/developer-guide/install Use this command to install the `lhctl` command-line utility on macOS and Linux systems via Homebrew. This utility is essential for interacting with the LittleHorse Kernel. ```Shell brew install littlehorse-enterprises/lh/lhctl ``` -------------------------------- ### Register and Start LittleHorse Task Workers Source: https://littlehorse.io/docs/server/concepts/variables This snippet demonstrates the main application logic for LittleHorse task workers. It initializes the SDK configuration, creates worker instances for 'fetch-user' and 'send-email' tasks, registers their definitions with the LittleHorse server, and starts the workers to begin processing incoming tasks. It also includes graceful shutdown handling. ```Java public class Main { public static void main(String[] args) throws Exception { LHConfig config = new LHConfig(); MyTasks taskFuncs = new MyTasks(); LHTaskWorker emailer = new LHTaskWorker(taskFuncs, "send-email", config); LHTaskWorker userService = new LHTaskWorker(taskFuncs, "fetch-user", config); emailer.registerTaskDef(); userService.registerTaskDef(); Runtime.getRuntime().addShutdownHook(new Thread(emailer::close)); Runtime.getRuntime().addShutdownHook(new Thread(userService::close)); emailer.start(); userService.start(); } } ``` ```Python async def main(): workers = [ LHTaskWorker(fetch_user, "fetch-user", config), LHTaskWorker(send_email, "send-email", config) ] await littlehorse.start(*workers) if __name__ == "__main__": create_task_def(fetch_user, "fetch-user", config) create_task_def(send_email, "send-email", config) asyncio.run(main()) ``` ```Go func main() { config := littlehorse.NewConfigFromEnv(); emailer, _ := littlehorse.NewTaskWorker(config, SendEmail, "send-email"); userService, _ := littlehorse.NewTaskWorker(config, FetchUser, "fetch-user"); //Register TaskDef emailer.RegisterTaskDef(); userService.RegisterTaskDef(); //Start Task Worker go func() { emailer.Start(); }(); userService.Start(); } ``` -------------------------------- ### Register 'greet' TaskDef and Start Worker Source: https://littlehorse.io/docs/server/concepts/workflows This snippet demonstrates how to define and register a 'greet' TaskDef in LittleHorse. The 'greet' task accepts a string 'name' as input and returns a customized greeting string, printing it to the console. It sets up a Task Worker, registers the TaskDef with the LittleHorse server, and starts the worker to listen for tasks. ```Java package io.littlehorse.quickstart; import io.littlehorse.sdk.common.config.LHConfig; import io.littlehorse.sdk.worker.LHTaskMethod; import io.littlehorse.sdk.worker.LHTaskWorker; class Greeter { @LHTaskMethod("greet") public String greeting(String name) { String result = "Hello " + name + "!"; System.out.println(result); return result; } } public class Main { public static void main(String[] args) { LHConfig config = new LHConfig(); Greeter greeter = new Greeter(); // Create a Task Worker LHTaskWorker worker = new LHTaskWorker(greeter, "greet", config); Runtime.getRuntime().addShutdownHook(new Thread(worker::close)); // Register the TaskDef worker.registerTaskDef(); // Start the Worker worker.start(); } } ``` ```Python import littlehorse from littlehorse import create_task_def from littlehorse.worker import LHTaskWorker from littlehorse.config import LHConfig import asyncio config = LHConfig() #define the task method async def greet(name: str) -> str: result = "Hello there " + name + "!" print(result) return result async def main(): #create a task worker if **name** == "**main**": #register the task def with the littlehorse server create_task_def(greet, "greet", config) asyncio.run(main()) ``` ```Go import ( "fmt" "github.com/littlehorse-enterprises/littlehorse/sdk-go/littlehorse" ) func Greet(name string) string { result := "Hello there, " + name + "!" fmt.Println(result); return result } func main() { config := littlehorse.NewConfigFromEnv() worker, _ := littlehorse.NewTaskWorker(config, Greet, "greet") //Register TaskDef worker.RegisterTaskDef() //Start Task Worker worker.Start() } ``` ```C# using LittleHorse.Sdk; using LittleHorse.Sdk.Worker; class Greeter { [LHTaskMethod("greet")] public string Greeting(string name) { string result = $"Hello {name}!"; Console.WriteLine(result); return result; } } public abstract class Program { static void Main(string[] args) { var config = new LHConfig(); // Create a Task Worker var greeter = new Greeter(); LHTaskWorker worker = new LHTaskWorker(greeter, "greet", config); // Register the TaskDef worker.RegisterTaskDef(); // Start the Worker worker.Start(); } } ``` -------------------------------- ### Example Keycloak OIDC Properties Configuration Source: https://littlehorse.io/docs/user-tasks-bridge/backend/configuration/keycloak An example `oidc-properties.yml` file demonstrating the configuration for integrating Keycloak with the LittleHorse User Tasks Bridge Backend. This snippet shows how to define Keycloak realm details, user claims, authorities, and authorized clients for OIDC. ```yaml com: c4-soft: springaddons: oidc: ops: - iss: https:///realms/ label-name: Default Keycloak username-claim: preferred_username user-id-claim: EMAIL authorities: - path: $.realm_access.roles - path: $.resource_access.*.roles vendor: keycloak tenant-id: client-id-claim: azp clients: - ``` -------------------------------- ### Initialize and Start LittleHorse Task Worker in C# Source: https://littlehorse.io/docs/getting-started/your-first-task-worker This C# code snippet shows how to instantiate and run a LittleHorse Task Worker. It creates an LHTaskWorker instance, registers the associated task definition, and then starts the worker to begin processing tasks. ```C# using Quickstart; using LittleHorse.Sdk; using LittleHorse.Sdk.Common.Proto; using LittleHorse.Sdk.Worker; public class Program { static LHConfig config = new LHConfig(); static void Main(string[] args) { var greetingWorker = new LHTaskWorker(new Greeter(), "greet", config); greetingWorker.RegisterTaskDef(); greetingWorker.Start(); } } ``` -------------------------------- ### Run Commands for LittleHorse WfSpec Registration Source: https://littlehorse.io/docs/getting-started/your-first-wfspec These commands illustrate how to execute the workflow registration logic for different language projects (Java, Python, Go, C#) using their respective build and run tools, effectively registering the `quickstart` WfSpec with LittleHorse. ```Java ./gradlew run ``` ```Python python -m quickstart.register ``` ```Go go run ./src ``` ```C# dotnet run -f net9.0 ``` -------------------------------- ### Start Workflow Run with lhctl Source: https://littlehorse.io/docs/server/concepts/external-events This command starts a new workflow run for the 'greet-event' workflow specification using the `lhctl` command-line tool. It will output a `WfRunId` which is needed to post external events to this specific workflow run. ```Shell lhctl run greet-event ``` -------------------------------- ### Define a LittleHorse Workflow Specification (WfSpec) in Java Source: https://littlehorse.io/docs/server/faq This Java code defines a `WfSpec` named 'quickstart' using the LittleHorse SDK. It illustrates how to create an input variable, execute a task, and register the workflow with the LittleHorse Kernel. A `WfSpec` outlines the tasks, their order, exception handling, and variable passing for a workflow. ```Java 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 LittleHorse Kernel. */ public Workflow getWorkflow() { return Workflow.newWorkflow(WF_NAME, this::quickstartWf); } } ``` -------------------------------- ### Define and Register LittleHorse Workflow Specification in Python Source: https://littlehorse.io/docs/getting-started/your-first-wfspec This Python code defines a `WfSpec` named "quickstart" with an input variable "input-name" and specifies a "greet" task execution. The `main` function then registers this `WfSpec` with the LittleHorse platform using the SDK, loading configuration from environment variables. ```Python def get_workflow() -> Workflow: def quickstart_workflow(wf: WorkflowThread) -> None: # Define an input variable the_name = wf.add_variable("input-name", VariableType.STR).searchable() # Execute the 'greet' task and pass in the variable as an argument. wf.execute("greet", the_name) # Provide the name of the WfSpec and a function which has the logic. return Workflow("quickstart", quickstart_workflow) def main() -> None: print("Registering WfSpec and TaskDef") # Configuration loaded from environment variables config = LHConfig() wf = get_workflow() littlehorse.create_workflow_spec(wf, config) if __name__ == "__main__": main() ``` -------------------------------- ### Start a LittleHorse Workflow Run using lhctl Source: https://littlehorse.io/docs/server/concepts/user-tasks This `lhctl` command initiates a new run of the 'favorite-player-demo' workflow. It passes 'obiwan' as the value for the 'user-id' input variable, demonstrating how to programmatically start a workflow instance from the command line. ```Shell lhctl run favorite-player-demo user-id obiwan ``` -------------------------------- ### Example LHConfig Environment Variables Configuration Source: https://littlehorse.io/docs/cloud/accessing-littlehorse-cloud-orchestrator This snippet provides an example of the environment variables required to configure programmatic access for LittleHorse. These variables define the API endpoint, protocol, OAuth client ID and secret, access token URL, and tenant ID, which are essential for initializing the LHConfig object. ```Configuration LHC_API_PORT=2023 LHC_API_PROTOCOL=TLS LHC_API_HOST= replace me! LHC_OAUTH_CLIENT_ID= # replace me! LHC_OAUTH_CLIENT_SECRET= # replace me! LHC_OAUTH_ACCESS_TOKEN_URL= # replace me! LHC_TENANT_ID= # replace me! ``` -------------------------------- ### Define and Start LittleHorse Tasks in Python Source: https://littlehorse.io/docs/server/concepts/exception-handling This Python snippet demonstrates how to define various tasks (e.g., charge-credit-card, fetch-amount, ship-item) using `create_task_def` and then start the LittleHorse workers to process these tasks asynchronously. It sets up the task definitions and initiates the worker processes. ```Python await littlehorse.start(*workers) if __name__ == "__main__": create_task_def(charge_credit_card, "charge-credit-card", config) create_task_def(fetch_amount, "fetch-amount", config) create_task_def(ship_item, "ship-item", config) create_task_def(cancel_order_insufficient_funds, "cancel-order-insufficient-funds", config) create_task_def(notify_order_failed, "notify-order-failed", config) asyncio.run(main()) ``` -------------------------------- ### Registering a 'hello-world' WfSpec with LittleHorse Kernel Source: https://littlehorse.io/docs/server/concepts/workflows This snippet demonstrates how to define and register a simple 'hello-world' `WfSpec` that takes a 'name' string and executes a 'greet' task. It shows the implementation across Java, Python, Go, and C# using the LittleHorse SDK to interact with the Kernel. ```Java package io.littlehorse.quickstart; import io.littlehorse.sdk.common.config.LHConfig; import io.littlehorse.sdk.wfsdk.WfRunVariable; import io.littlehorse.sdk.wfsdk.Workflow; public class Main { public static final String WF_NAME = "quickstart"; public static void main(String[] args) { LHConfig config = new LHConfig(); Workflow workflowGenerator = Workflow.newWorkflow(WF_NAME, wf -> { WfRunVariable name = wf.declareStr("name").searchable().required(); wf.execute("greet", name); }); workflowGenerator.registerWfSpec(config.getBlockingStub()); } } ``` ```Python import asyncio from littlehorse.workflow import Workflow, WorkflowThread from littlehorse import create_workflow_spec from littlehorse.config import LHConfig config = LHConfig() def get_workflow() -> Workflow: def quickstart_workflow(wf: WorkflowThread) -> None: name = wf.declare_str("name").searchable() wf.execute("greet", name) return Workflow("quickstart", quickstart_workflow) async def main(): print("Registering WfSpec") create_workflow_spec(get_workflow(), config) if __name__ == "__main__": asyncio.run(main()) ``` ```Go import ( "context" "github.com/littlehorse-enterprises/littlehorse/sdk-go/littlehorse" ) func QuickStart(wf *littlehorse.WorkflowThread){ name := wf.DeclareStr("name").Searchable() wf.Execute("greet", name ) } func main() { // Get a client config := littlehorse.NewConfigFromEnv() client, _ := config.GetGrpcClient() workflowGenerator := littlehorse.NewWorkflow(QuickStart, "quickstart") request, err := workflowGenerator.Compile() if err != nil { log.Fatal(err) } (*client).PutWfSpec(context.Background(), request) } ``` ```C# using LittleHorse.Sdk; using LittleHorse.Sdk.Workflow.Spec; namespace Quickstart; public abstract class Program { public static string WfName = "quickstart"; static void Main(string[] args) { var config = new LHConfig(); Workflow workflowGenerator = new Workflow(WfName, (WorkflowThread wf) => { WfRunVariable name = wf.DeclareStr("name").Searchable().Required(); wf.Execute("greet", name); }); workflowGenerator.RegisterWfSpec(config.GetGrpcClientInstance()); } } ``` -------------------------------- ### Get and Delete WfSpec by ID Source: https://littlehorse.io/docs/server/developer-guide/grpc/managing-metadata Shows how to retrieve a `WfSpec` using its ID (name, major version, revision) and how to delete an existing `WfSpec` from the LittleHorse system. Also includes an example of getting the latest `WfSpec` in Go. ```Java package io.littlehorse.quickstart; import java.io.IOException; import io.littlehorse.sdk.common.LHLibUtil; import io.littlehorse.sdk.common.config.LHConfig; import io.littlehorse.sdk.common.proto.LittleHorseGrpc.LittleHorseBlockingStub; import io.littlehorse.sdk.common.proto.DeleteWfSpecRequest; import io.littlehorse.sdk.common.proto.WfSpec; import io.littlehorse.sdk.common.proto.WfSpecId; public class Main { public static void main(String[] args) throws IOException { LHConfig config = new LHConfig(); LittleHorseBlockingStub client = config.getBlockingStub(); WfSpecId wfSpecId = WfSpecId.newBuilder() .setName("my-wfspec") .setMajorVersion(0) // Set to whichever major version you want .setRevision(0) // Set to whichever revision you want .build(); WfSpec wfSpec = client.getWfSpec(wfSpecId); System.out.println(LHLibUtil.protoToJson(wfSpec)); // Delete the WfSpec DeleteWfSpecRequest req = DeleteWfSpecRequest.newBuilder().setId(wfSpecId).build(); client.deleteWfSpec(req); } } ``` ```Go wfSpecId := &lhproto.WfSpecId{ Name: "my-wf", MajorVersion: 2, Revision: 1, } wfSpec, err := (*client).GetWfSpec(context.Background(), wfSpecId) // Get the latest wfSpec. Setting majorVersion is optional for this request majorVersion := int32(2) someWf, err := (*client).GetLatestWfSpec( context.Background(), &lhproto.GetLatestWfSpecRequest{ Name: "some-wf", MajorVersion: &majorVersion, }, ) // delete the WfSpec _, err = (*client).DeleteWfSpec(context.Background(), &lhproto.DeleteWfSpecRequest{ Id: wfSpecId, }) ```