Skip to main content

Clients

The protoc-gen-go-temporal plugin generates comprehensive client libraries that provide type-safe interfaces for interacting with Temporal workflows. These clients wrap the standard Temporal Go SDK to provide structured access to workflow execution, signals, queries, and updates.

Client Interface

Each protobuf service generates a client interface (e.g., ExampleClient) that provides methods for all workflow operations defined in your schema.

Generated Client Interface
type ExampleClient interface {
// Workflow execution methods
CreateFoo(ctx context.Context, req *CreateFooRequest, opts ...*CreateFooOptions) (*CreateFooResponse, error)
CreateFooAsync(ctx context.Context, req *CreateFooRequest, opts ...*CreateFooOptions) (CreateFooRun, error)
GetCreateFoo(ctx context.Context, workflowID, runID string) CreateFooRun

// Signal methods
SetFooProgress(ctx context.Context, workflowID, runID string, req *SetFooProgressRequest) error

// Query methods
GetFooProgress(ctx context.Context, workflowID, runID string) (*GetFooProgressResponse, error)

// Update methods
UpdateFooProgress(ctx context.Context, workflowID, runID string, req *SetFooProgressRequest, opts ...*UpdateFooProgressOptions) (*GetFooProgressResponse, error)
UpdateFooProgressAsync(ctx context.Context, workflowID, runID string, req *SetFooProgressRequest, opts ...*UpdateFooProgressOptions) (UpdateFooProgressHandle, error)

// Workflow management
CancelWorkflow(ctx context.Context, workflowID, runID string) error
TerminateWorkflow(ctx context.Context, workflowID, runID string, reason string, details ...any) error
}

Client Initialization

Initialize a client by providing a Temporal client instance and optional configuration.

main.go
package main

import (
"log"

examplev1 "path/to/gen/example/v1"
"go.temporal.io/sdk/client"
)

func main() {
// Initialize Temporal client
c, err := client.Dial(client.Options{})
if err != nil {
log.Fatalf("error initializing temporal client: %v", err)
}
defer c.Close()

// Initialize generated client
client := examplev1.NewExampleClient(c)

// Use client...
}

Workflow Execution

Clients provide both synchronous and asynchronous methods for workflow execution.

Synchronous Execution

Synchronous methods execute the workflow and block until completion.

main.go
package main

import (
"context"
"log"

examplev1 "path/to/gen/example/v1"
"go.temporal.io/sdk/client"
)

func main() {
c, _ := client.Dial(client.Options{})
client := examplev1.NewExampleClient(c)

// Execute workflow synchronously - blocks until completion
result, err := client.CreateFoo(context.Background(), &examplev1.CreateFooRequest{
Name: "my-foo",
})
if err != nil {
log.Fatalf("workflow execution failed: %v", err)
}

log.Printf("workflow completed: %s", result.String())
}

Asynchronous Execution

Asynchronous methods start the workflow and return immediately with a workflow run handle.

main.go
package main

import (
"context"
"log"

examplev1 "path/to/gen/example/v1"
"go.temporal.io/sdk/client"
)

func main() {
c, _ := client.Dial(client.Options{})
client := examplev1.NewExampleClient(c)

// Start workflow asynchronously
run, err := client.CreateFooAsync(context.Background(), &examplev1.CreateFooRequest{
Name: "my-foo",
})
if err != nil {
log.Fatalf("workflow start failed: %v", err)
}

log.Printf("workflow started: id=%s, run_id=%s", run.ID(), run.RunID())

// Get result when ready
result, err := run.Get(context.Background())
if err != nil {
log.Fatalf("workflow execution failed: %v", err)
}

log.Printf("workflow completed: %s", result.String())
}

Workflow Run

Workflow run handles provide access to workflow metadata and operations for running workflows.

Generated Run Interface
type CreateFooRun interface {
// Workflow metadata
ID() string
RunID() string
Run() client.WorkflowRun

// Result retrieval
Get(ctx context.Context) (*CreateFooResponse, error)

// Lifecycle management
Cancel(ctx context.Context) error
Terminate(ctx context.Context, reason string, details ...any) error

// Signal methods (if workflow defines signals)
SetFooProgress(ctx context.Context, req *SetFooProgressRequest) error

// Query methods (if workflow defines queries)
GetFooProgress(ctx context.Context) (*GetFooProgressResponse, error)

// Update methods (if workflow defines updates)
UpdateFooProgress(ctx context.Context, req *SetFooProgressRequest, opts ...*UpdateFooProgressOptions) (*GetFooProgressResponse, error)
UpdateFooProgressAsync(ctx context.Context, req *SetFooProgressRequest, opts ...*UpdateFooProgressOptions) (UpdateFooProgressHandle, error)
}

Signals

Send signals to running workflows using client methods or workflow run handles.

main.go
func sendSignals(client examplev1.ExampleClient) {
ctx := context.Background()

// Send signal using client method
err := client.SetFooProgress(ctx, "workflow-id", "run-id", &examplev1.SetFooProgressRequest{
Progress: 50.0,
})
if err != nil {
log.Printf("signal failed: %v", err)
}
}

Queries

Execute queries against running workflows to retrieve current state.

main.go
func executeQueries(client examplev1.ExampleClient) {
ctx := context.Background()

// Execute query using client method
progress, err := client.GetFooProgress(ctx, "workflow-id", "run-id")
if err != nil {
log.Printf("query failed: %v", err)
return
}

log.Printf("current progress: %.1f%%", progress.Progress)
}

Updates

Execute updates to modify workflow state and receive return values.

main.go
func executeUpdates(client examplev1.ExampleClient) {
ctx := context.Background()

// Execute update synchronously - blocks until completion
result, err := client.UpdateFooProgress(ctx, "workflow-id", "run-id",
&examplev1.SetFooProgressRequest{Progress: 100.0})
if err != nil {
log.Printf("update failed: %v", err)
return
}

log.Printf("update completed: %.1f%%", result.Progress)
}

Signal-with-Start

Execute workflows with an initial signal, allowing workflows to be started in a specific state.

main.go
package main

import (
"context"
"log"

examplev1 "path/to/gen/example/v1"
"go.temporal.io/sdk/client"
)

func main() {
c, _ := client.Dial(client.Options{})
client := examplev1.NewExampleClient(c)
ctx := context.Background()

// Start workflow with initial signal
result, err := client.CreateFooWithSetFooProgress(ctx,
&examplev1.CreateFooRequest{Name: "test"},
&examplev1.SetFooProgressRequest{Progress: 25.0},
)
if err != nil {
log.Fatalf("signal-with-start failed: %v", err)
}

log.Printf("workflow completed with initial progress: %s", result.String())
}

Update-with-Start

Execute workflows with an initial update, allowing workflows to be started and immediately updated atomically.

warning

Update-with-start is considered experimental.

main.go
package main

import (
"context"
"log"

examplev1 "path/to/gen/example/v1"
"go.temporal.io/sdk/client"
)

func main() {
c, _ := client.Dial(client.Options{})
client := examplev1.NewExampleClient(c)
ctx := context.Background()

// Start workflow with initial update
updateResult, workflowRun, err := client.CreateFooWithUpdateFooProgress(ctx,
&examplev1.CreateFooRequest{Name: "test"},
&examplev1.SetFooProgressRequest{Progress: 50.0},
)
if err != nil {
log.Fatalf("update-with-start failed: %v", err)
}

log.Printf("workflow started with initial update: %s", updateResult.String())
log.Printf("workflow ID: %s", workflowRun.ID())

// Continue with workflow execution
finalResult, err := workflowRun.Get(ctx)
if err != nil {
log.Fatalf("workflow execution failed: %v", err)
}

log.Printf("workflow completed: %s", finalResult.String())
}

Options

Configure workflow execution, updates, and other operations using the generated options builders.

Workflow Options

main.go
package main

import (
"context"
"time"

examplev1 "path/to/gen/example/v1"
"go.temporal.io/api/enums/v1"
"go.temporal.io/sdk/temporal"
)

func executeWithOptions(client examplev1.ExampleClient) {
ctx := context.Background()

// Execute workflow with custom options
run, err := client.CreateFooAsync(ctx, &examplev1.CreateFooRequest{Name: "test"},
examplev1.NewCreateFooOptions().
WithID("custom-workflow-id").
WithExecutionTimeout(time.Hour * 2).
WithTaskQueue("custom-task-queue").
WithRetryPolicy(&temporal.RetryPolicy{
MaximumAttempts: 3,
}).
WithSearchAttributes(map[string]any{
"environment": "staging",
"team": "backend",
}).
WithIDReusePolicy(enums.WORKFLOW_ID_REUSE_POLICY_ALLOW_DUPLICATE),
)
if err != nil {
log.Printf("workflow start failed: %v", err)
return
}

// Use run...
}

Update Options

main.go
func executeUpdateWithOptions(run examplev1.CreateFooRun) {
ctx := context.Background()

// Execute update with custom options
result, err := run.UpdateFooProgress(ctx,
&examplev1.SetFooProgressRequest{Progress: 100.0},
examplev1.NewUpdateFooProgressOptions().
WithUpdateID("custom-update-id").
WithWaitPolicy(enums.UPDATE_WORKFLOW_EXECUTION_LIFECYCLE_STAGE_COMPLETED),
)
if err != nil {
log.Printf("update failed: %v", err)
return
}

log.Printf("update completed: %s", result.String())
}