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 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 executes a Standalone Activity, gets its result, lists activities, and counts 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​