Skip to main content

Quickstart

View Markdown

Standalone Activities are Activity Executions that run independently, without being orchestrated by a Workflow. Instead of starting an Activity from within a Workflow Definition using workflow.ExecuteActivity(), you start a Standalone Activity directly from a Temporal Client using client.ExecuteActivity().

The Activity definition and Worker registration are identical to regular Activities, and only the execution path differs.

info

This documentation uses source code from the standalone-activity/helloworld.

Get started with Standalone Activities

Prerequisites:

Start the Temporal development server with temporal server start-dev.

This command automatically starts the Temporal development server with the Web UI, and creates the default Namespace. It uses an in-memory database, so do not use it for real use cases.

The Temporal Server should now be available for client connections on localhost:7233, and the Temporal Web UI should now be accessible at http://localhost:8233.

brew install temporal
temporal --version
temporal server start-dev

Clone the sample

Clone the samples-go repository to follow along:

git clone https://github.com/temporalio/samples-go.git
cd samples-go

The sample project is structured as follows:

standalone-activity/helloworld/
├── activity.go
├── worker/
│ └── main.go
└── starter/
└── main.go

Define your Activity

Define your Activity in a shared file so that both the Worker and starter can reference it.

standalone-activity/helloworld/activity.go

activity.go
package helloworld

import (
"context"
"go.temporal.io/sdk/activity"
)

func Activity(ctx context.Context, name string) (string, error) {
logger := activity.GetLogger(ctx)
logger.Info("Activity", "name", name)
return "Hello " + name + "!", nil
}

Run a Worker with the Activity registered

Running a Worker for Standalone Activities is the same as running a Worker for Workflow-driven Activities — you create a Worker, register the Activity, and call Run(). The Worker doesn't need to know whether the Activity will be invoked from a Workflow or as a Standalone Activity.

See How to develop a Worker in Go for more details on Worker setup and configuration options.

standalone-activity/helloworld/worker/main.go

Open a new terminal, navigate to the samples-go directory, and run the Worker. Leave this terminal running - the Worker needs to stay up to process activities.

worker/main.go
package main

import (
"github.com/temporalio/samples-go/standalone-activity/helloworld"
"go.temporal.io/sdk/client"
"go.temporal.io/sdk/contrib/envconfig"
"go.temporal.io/sdk/worker"
"log"
)

func main() {
c, err := client.Dial(envconfig.MustLoadDefaultClientOptions())
if err != nil {
log.Fatalln("Unable to create client", err)
}
defer c.Close()

w := worker.New(c, "standalone-activity-helloworld", worker.Options{})

w.RegisterActivity(helloworld.Activity)

err = w.Run(worker.InterruptCh())
if err != nil {
log.Fatalln("Unable to start worker", err)
}
}
go run standalone-activity/helloworld/worker/main.go

Execute a Standalone Activity

Use client.ExecuteActivity() to start a Standalone Activity Execution. This is called from application code (for example, a starter program), not from inside a Workflow Definition.

ExecuteActivity returns an ActivityHandle that you can use to get the result, describe, cancel, or terminate the Activity.

The following starter program demonstrates how to execute a Standalone Activity, get its result, list activities, and count activities:

Create standalone-activity/helloworld/starter/main.go.

You can pass the Activity as either a function reference or a string Activity type name:

handle, err := c.ExecuteActivity(ctx, options, helloworld.Activity, "arg1")

// Using a string type name
handle, err := c.ExecuteActivity(ctx, options, "Activity", "arg1")

client.StartActivityOptions requires ID, TaskQueue, and at least one of ScheduleToCloseTimeout or StartToCloseTimeout. See StartActivityOptions in the API reference for the full set of options.

To run the starter:

  1. Make sure the Temporal Server is running (from the Get Started step above).
  2. Make sure the Worker is running (from the Run a Worker step above).
  3. Open a new terminal, navigate to the samples-go directory, and run go run standalone-activity/helloworld/starter/main.go.

Or use the Temporal CLI to execute a Standalone Activity.

starter/main.go
package main

import (
"context"
"github.com/temporalio/samples-go/standalone-activity/helloworld"
"go.temporal.io/sdk/client"
"go.temporal.io/sdk/contrib/envconfig"
"log"
"time"
)

func main() {
c, err := client.Dial(envconfig.MustLoadDefaultClientOptions())
if err != nil {
log.Fatalln("Unable to create client", err)
}
defer c.Close()

activityOptions := client.StartActivityOptions{
ID: "standalone_activity_helloworld_ActivityID",
TaskQueue: "standalone-activity-helloworld",
ScheduleToCloseTimeout: 10 * time.Second,
}

handle, err := c.ExecuteActivity(context.Background(), activityOptions, helloworld.Activity, "Temporal")
if err != nil {
log.Fatalln("Unable to execute activity", err)
}

log.Println("Started standalone activity", "ActivityID", handle.GetID(), "RunID", handle.GetRunID())

var result string
err = handle.Get(context.Background(), &result)
if err != nil {
log.Fatalln("Unable get standalone activity result", err)
}
log.Println("Activity result:", result)

resp, err := c.ListActivities(context.Background(), client.ListActivitiesOptions{
Query: "TaskQueue = 'standalone-activity-helloworld'",
})
if err != nil {
log.Fatalln("Unable to list activities", err)
}

log.Println("ListActivity results")
for info, err := range resp.Results {
if err != nil {
log.Fatalln("Error iterating activities", err)
}
log.Printf(" ActivityID: %s, Type: %s, Status: %v
",
info.ActivityID, info.ActivityType, info.Status)
}

resp1, err := c.CountActivities(context.Background(), client.CountActivitiesOptions{
Query: "TaskQueue = 'standalone-activity-helloworld'",
})
if err != nil {
log.Fatalln("Unable to count activities", err)
}

log.Println("Total activities:", resp1.Count)
}
go run standalone-activity/helloworld/starter/main.go
temporal activity execute \
--type Activity \
--activity-id standalone_activity_helloworld_ActivityID \
--task-queue standalone-activity-helloworld \
--schedule-to-close-timeout 10s \
--input '"Temporal"'

Run with Temporal Cloud

All code samples on this page use envconfig.MustLoadDefaultClientOptions() to configure the Temporal Client connection. It responds to environment variables and TOML configuration files, so the same code works against a local dev server and Temporal Cloud without changes. See Run Standalone Activities with Temporal Cloud in the Feature Guide for mTLS and API key setup.

Next steps