Job workers
The Go SDK is a technical preview. Its API surface may still evolve and changes may not follow semantic versioning. Pin an exact version if you need stability.
Register a REST activate-jobs worker with NewJobWorker. The handler's return
value decides the job outcome:
// One JobHandler contract for both workers: returning variables completes the
// job; returning a *camunda.BpmnError throws a BPMN error; returning any other
// error fails the job (decrementing its retries).
worker := client.NewJobWorker("greet",
func(ctx context.Context, job *camunda.Job) (map[string]any, error) {
var in struct {
Name string `json:"name"`
}
if err := job.Variables(&in); err != nil {
return nil, err
}
return map[string]any{"greeting": "Hello, " + in.Name + "!"}, nil
},
camunda.WithMaxConcurrentJobs(10),
camunda.WithPollInterval(500*time.Millisecond),
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// Run blocks until ctx is canceled, draining in-flight jobs on shutdown.
if err := worker.Run(ctx); err != nil {
fmt.Println("worker stopped:", err)
}
For high-throughput, low-latency work, use the gRPC streaming worker
(NewStreamJobWorker) — a capability unique to this SDK among the Camunda
Orchestration Cluster SDKs:
// The gRPC streaming worker activates jobs over a StreamActivatedJobs stream
// and acknowledges them over gRPC. A low-frequency REST sidecar poll backs it
// up (a safety net for jobs re-queued after a timeout or brief reconnect).
worker := client.NewStreamJobWorker("greet",
func(ctx context.Context, job *camunda.Job) (map[string]any, error) {
return map[string]any{"greeting": "Hello!"}, nil
},
camunda.WithStreamPollInterval(30*time.Second), // -1 disables the sidecar poll
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
if err := worker.Run(ctx); err != nil {
fmt.Println("stream worker stopped:", err)
}
Pass camunda.WithStreamJobLease(true) to activate jobs with a lease. Each job
then carries a lease token that the worker sends back when it completes, fails,
or throws — so if the job timed out and another worker picked it up, the stale
acknowledgement is rejected instead of racing the newer activation. It covers
both the gRPC stream and the REST sidecar poll. The REST worker takes the same
option as camunda.WithJobLease(true). Leases are off by default (matching the
engine) and need an engine that supports them; older gateways ignore the flag and
keep handing out unleased jobs.