From bfb4b592f41e685b13078ff40595e326756a5051 Mon Sep 17 00:00:00 2001 From: Lenny Chen Date: Mon, 27 Jul 2026 17:31:54 -0700 Subject: [PATCH] Restructure the Go, Python, and TypeScript Worker pages Gives all three pages the same six sections, ordered by the reader's journey: create and run, register types, connect to Cloud, configure options, run a versioned Worker, shut down. - Adds a versioned Worker section. None of the eight SDK Worker pages documented Worker Versioning. - Replaces hand-written inline code with snipsync snippets. - Un-nests the TypeScript register-types section, which was an H3 inside the Temporal Cloud section. - Replaces the TypeScript mTLS-only Cloud walkthrough with a pointer to the Client page, which also covers API keys. - Fills out the Python page, previously a single section. Existing anchor IDs are preserved because eight other pages link to them. The TypeScript Docker section is unchanged, moved after the core sections. --- .../develop/go/workers/run-worker-process.mdx | 92 ++-- docs/develop/python/workers/run-process.mdx | 151 ++++--- .../typescript/workers/run-process.mdx | 393 +++++++++++------- 3 files changed, 389 insertions(+), 247 deletions(-) diff --git a/docs/develop/go/workers/run-worker-process.mdx b/docs/develop/go/workers/run-worker-process.mdx index 310f7b68f6..4f1ff5317d 100644 --- a/docs/develop/go/workers/run-worker-process.mdx +++ b/docs/develop/go/workers/run-worker-process.mdx @@ -22,36 +22,44 @@ Create a [`Worker`](https://pkg.go.dev/go.temporal.io/sdk/worker#Worker) by call 2. The name of the Task Queue to poll. 3. A [`worker.Options`](https://pkg.go.dev/go.temporal.io/sdk/internal#WorkerOptions) struct (can be empty for defaults). -Register your Workflow and Activity types, then call `Run()` to start polling. The Worker process is a long-running process that blocks while polling for tasks. -Run it in a separate terminal from your starter code or other application logic. +Register your Workflow and Activity types, then call `Run()` to start polling. +The Worker blocks while it polls, so run it in a separate terminal from your starter code. + +[helloworld/worker/main.go](https://github.com/temporalio/samples-go/blob/main/helloworld/worker/main.go) ```go package main import ( - "log" + "log" - "go.temporal.io/sdk/client" - "go.temporal.io/sdk/worker" + "go.temporal.io/sdk/client" + "go.temporal.io/sdk/contrib/envconfig" + "go.temporal.io/sdk/worker" + + "github.com/temporalio/samples-go/helloworld" ) func main() { - c, err := client.Dial(client.Options{}) - if err != nil { - log.Fatalln("Unable to create client", err) - } - defer c.Close() - - w := worker.New(c, "my-task-queue", worker.Options{}) - w.RegisterWorkflow(MyWorkflow) - w.RegisterActivity(MyActivity) - - err = w.Run(worker.InterruptCh()) - if err != nil { - log.Fatalln("Unable to start Worker", err) - } + // The client and worker are heavyweight objects that should be created once per process. + c, err := client.Dial(envconfig.MustLoadDefaultClientOptions()) + if err != nil { + log.Fatalln("Unable to create client", err) + } + defer c.Close() + + w := worker.New(c, "hello-world", worker.Options{}) + + w.RegisterWorkflow(helloworld.Workflow) + w.RegisterActivity(helloworld.Activity) + + err = w.Run(worker.InterruptCh()) + if err != nil { + log.Fatalln("Unable to start worker", err) + } } ``` + `Run()` accepts an interrupt channel so the Worker shuts down on `SIGINT` or `SIGTERM`. You can also call `Start()` and `Stop()` separately for more control over the lifecycle. @@ -67,11 +75,6 @@ gow run worker/main.go ::: -## Connect to Temporal Cloud {/* #connect-to-temporal-cloud */} - -To run a Worker against Temporal Cloud, configure the client connection with your Namespace address and authentication credentials. -See [Connect to Temporal Cloud](/develop/go/client/temporal-client#connect-to-temporal-cloud) for setup instructions. - ## Register Workflows and Activities {/* #register-types */} All Workers listening to the same Task Queue must be registered to handle the same Workflow Types and Activity Types. @@ -89,9 +92,46 @@ w.RegisterActivity(&MyActivities{}) To customize the registered name or other options, use `RegisterWorkflowWithOptions()` or `RegisterActivityWithOptions()`. See [`workflow.RegisterOptions`](https://pkg.go.dev/go.temporal.io/sdk/workflow#RegisterOptions) and [`activity.RegisterOptions`](https://pkg.go.dev/go.temporal.io/sdk/activity#RegisterOptions). -## Worker options {/* #worker-options */} +## Connect to Temporal Cloud {/* #connect-to-temporal-cloud */} + +To run a Worker against Temporal Cloud, configure the Client connection with your Namespace address and authentication credentials. +See [Connect to Temporal Cloud](/develop/go/client/temporal-client#connect-to-temporal-cloud) for setup instructions. + +## Configure Worker options {/* #worker-options */} Pass a [`worker.Options`](https://pkg.go.dev/go.temporal.io/sdk/internal#WorkerOptions) struct to `worker.New()` to configure concurrency limits, pollers, timeouts, and other Worker behavior. An empty struct uses defaults that work for most cases. -For the full list of options and their defaults, see the [Go SDK reference](https://pkg.go.dev/go.temporal.io/sdk@v1.42.0/internal#WorkerOptions). +To tune these values against real load, see [Worker performance](/develop/worker-performance) and the [Worker tuning reference](/develop/worker-tuning-reference). + +## Run a versioned Worker {/* #versioned-worker */} + +Set a Worker Deployment Version and enable versioning in `worker.Options`, then set a versioning behavior on each Workflow. + + +[features/snippets/worker/worker.go](https://github.com/temporalio/features/blob/main/features/snippets/worker/worker.go) +```go +w := worker.New(c, "my-task-queue", worker.Options{ + DeploymentOptions: worker.DeploymentOptions{ + UseVersioning: true, + Version: worker.WorkerDeploymentVersion{ + DeploymentName: "my-app", + BuildID: "1.0", + }, + }, +}) + +w.RegisterWorkflowWithOptions(HelloWorkflow, workflow.RegisterOptions{ + VersioningBehavior: workflow.VersioningBehaviorPinned, +}) +``` + + +See [Worker Versioning](/worker-versioning) for the available versioning behaviors and how new versions roll out. + +## Shut down a Worker {/* #shut-down-a-worker */} + +A Worker started with `Run(worker.InterruptCh())` shuts down when the process receives `SIGINT` or `SIGTERM`. +It stops polling for new Tasks and waits for in-flight Tasks to finish, up to the `WorkerStopTimeout` set in `worker.Options`. + +See [Worker shutdown](/encyclopedia/workers/worker-shutdown) for what happens to in-flight Workflow Tasks and Activities. diff --git a/docs/develop/python/workers/run-process.mdx b/docs/develop/python/workers/run-process.mdx index c34e4eb895..091addeeb4 100644 --- a/docs/develop/python/workers/run-process.mdx +++ b/docs/develop/python/workers/run-process.mdx @@ -1,8 +1,8 @@ --- id: run-worker-process -title: Worker processes - Python SDK -description: Shows how to run Worker processes with the Python SDK -sidebar_label: Worker processes +title: Run a Worker - Python SDK +description: Create and run a Temporal Worker using the Python SDK. +sidebar_label: Run a Worker slug: /develop/python/workers/run-worker-process toc_max_heading_level: 3 tags: @@ -11,81 +11,110 @@ tags: - Worker --- -import { ViewSourceCodeNotice } from '@site/src/components'; +This page covers long-lived Workers that you host and run as persistent processes. +For Workers that run on serverless compute like AWS Lambda, see [Serverless Workers](/develop/python/workers/serverless-workers). -## Run a Worker Process {/* #run-a-dev-worker */} +## Create and run a Worker {/* #run-a-dev-worker */} -**How to run a Worker Process using the Temporal Python SDK.** +Create a `Worker` with a Temporal Client, the Task Queue to poll, and the Workflows and Activities it can execute. +Call `run()` to start polling. The Worker runs until the process is interrupted. -The [Worker Process](/workers#worker-process) is where Workflow Functions and Activity Functions are executed. + +[features/snippets/worker/worker.py](https://github.com/temporalio/features/blob/main/features/snippets/worker/worker.py) +```py +client = await Client.connect("localhost:7233") -- Each [Worker Entity](/workers#worker-entity) in the Worker Process must register the exact Workflow Types and Activity - Types it may execute. -- Each Worker Entity must also associate itself with exactly one [Task Queue](/task-queue). -- Each Worker Entity polling the same Task Queue must be registered with the same Workflow Types and Activity Types. +worker = Worker( + client, + task_queue="my-task-queue", + workflows=[HelloWorkflow], + activities=[some_activity], +) +await worker.run() +``` + -A [Worker Entity](/workers#worker-entity) is the component within a Worker Process that listens to a specific Task -Queue. +A Worker is also an async context manager, so `async with worker:` runs it for the duration of a block. +See [Shut down a Worker](#shut-down-a-worker) for the pattern most Worker processes use. -Although multiple Worker Entities can be in a single Worker Process, a single Worker Entity Worker Process may be -perfectly sufficient. For more information, see the [Worker tuning guide](/develop/worker-performance). +## Register Workflows and Activities {/* #register-types */} -A Worker Entity contains a Workflow Worker and/or an Activity Worker, which makes progress on Workflow Executions and -Activity Executions, respectively. +All Workers listening to the same Task Queue must be registered to handle the same Workflow Types and Activity Types. +If a Worker polls a Task for a type it does not know about, the Task fails. The Workflow Execution itself does not fail. -To develop a Worker, use the `Worker()` constructor and add your Client, Task Queue, Workflows, and Activities as -arguments. The following code example creates a Worker that polls for tasks from the Task Queue and executes the -Workflow. When a Worker is created, it accepts a list of Workflows in the workflows parameter, a list of Activities in -the activities parameter, or both. +Pass a list of Workflows in `workflows`, a list of Activities in `activities`, or both. - +Activities defined with `async def` run on the Worker's event loop. Activities defined with a plain `def` are synchronous and require an executor, so pass one in `activity_executor`: ```python -from temporalio.client import Client -from temporalio.worker import Worker -# ... -# ... -async def main(): - client = await Client.connect("localhost:7233") - worker = Worker( - client, - task_queue="your-task-queue", - workflows=[YourWorkflow], - activities=[your_activity], - ) - await worker.run() - -if __name__ == "__main__": - asyncio.run(main()) +worker = Worker( + client, + task_queue="my-task-queue", + workflows=[MyWorkflow], + activities=[my_sync_activity], + activity_executor=ThreadPoolExecutor(5), +) ``` -### Register types {/* #register-types */} +The same executor can be shared across multiple Workers. -**How to register types using the Temporal Python SDK.** +## Connect to Temporal Cloud {/* #connect-to-temporal-cloud */} -All Workers listening to the same Task Queue name must be registered to handle the exact same Workflows Types and -Activity Types. +To run a Worker against Temporal Cloud, configure the Client connection with your Namespace address and authentication credentials. +See [Connect to Temporal Cloud](/develop/python/client/temporal-client#connect-to-temporal-cloud) for setup instructions. -If a Worker polls a Task for a Workflow Type or Activity Type it does not know about, it fails that Task. However, the -failure of the Task does not cause the associated Workflow Execution to fail. +## Configure Worker options {/* #worker-options */} -When a `Worker` is created, it accepts a list of Workflows in the `workflows` parameter, a list of Activities in the -`activities` parameter, or both. +The `Worker` constructor takes keyword arguments that control concurrency limits, pollers, timeouts, and caching, including `max_concurrent_activities`, `max_concurrent_workflow_tasks`, and `max_cached_workflows`. +The defaults work for most cases. - +To tune these values against real load, see [Worker performance](/develop/worker-performance) and the [Worker tuning reference](/develop/worker-tuning-reference). -```python -# ... -async def main(): - client = await Client.connect("localhost:7233") - worker = Worker( - client, - task_queue="your-task-queue", - workflows=[YourWorkflow], - activities=[your_activity], - ) - await worker.run() - -if __name__ == "__main__": - asyncio.run(main()) +## Run a versioned Worker {/* #versioned-worker */} + +Set a Worker Deployment Version and enable versioning in `deployment_config`, then set a default versioning behavior for the Workflows on the Worker. + + +[features/snippets/worker/worker.py](https://github.com/temporalio/features/blob/main/features/snippets/worker/worker.py) +```py +worker = Worker( + client, + task_queue="my-task-queue", + workflows=[HelloWorkflow], + activities=[some_activity], + deployment_config=WorkerDeploymentConfig( + version=WorkerDeploymentVersion( + deployment_name="my-app", + build_id="1.0", + ), + use_worker_versioning=True, + default_versioning_behavior=VersioningBehavior.PINNED, + ), +) +``` + + +To set the behavior per Workflow instead of on the Worker, pass `versioning_behavior` to `@workflow.defn`. +See [Worker Versioning](/worker-versioning) for the available versioning behaviors and how new versions roll out. + +## Shut down a Worker {/* #shut-down-a-worker */} + +Use the Worker as an async context manager and wait on an event that your signal handler sets. +When the block exits, the Worker stops polling for new Tasks and waits for in-flight Tasks to finish, up to `graceful_shutdown_timeout`. + + +[features/snippets/worker/worker.py](https://github.com/temporalio/features/blob/main/features/snippets/worker/worker.py) +```py +worker = Worker( + client, + task_queue="my-task-queue", + workflows=[HelloWorkflow], + activities=[some_activity], + graceful_shutdown_timeout=timedelta(seconds=30), +) +async with worker: + await interrupt_event.wait() ``` + + +See [Worker shutdown](/encyclopedia/workers/worker-shutdown) for what happens to in-flight Workflow Tasks and Activities. diff --git a/docs/develop/typescript/workers/run-process.mdx b/docs/develop/typescript/workers/run-process.mdx index f1272c7201..b3e15210e6 100644 --- a/docs/develop/typescript/workers/run-process.mdx +++ b/docs/develop/typescript/workers/run-process.mdx @@ -1,8 +1,8 @@ --- id: run-worker-process -title: Worker processes - TypeScript SDK -description: Shows how to run Worker processes with the TypeScript SDK -sidebar_label: Worker processes +title: Run a Worker - TypeScript SDK +description: Create and run a Temporal Worker using the TypeScript SDK. +sidebar_label: Run a Worker slug: /develop/typescript/workers/run-worker-process toc_max_heading_level: 3 tags: @@ -11,39 +11,251 @@ tags: - Worker --- -## How to run Worker Processes {/* #run-a-dev-worker */} +This page covers long-lived Workers that you host and run as persistent processes. +For Workers that run on serverless compute like AWS Lambda, see [Serverless Workers](/develop/typescript/workers/serverless-workers). -The [Worker Process](/workers#worker-process) is where Workflow Functions and Activity Functions are executed. +## Create and run a Worker {/* #run-a-dev-worker */} -- Each [Worker Entity](/workers#worker-entity) in the Worker Process must register the exact Workflow Types and Activity - Types it may execute. -- Each Worker Entity must also associate itself with exactly one [Task Queue](/task-queue). -- Each Worker Entity polling the same Task Queue must be registered with the same Workflow Types and Activity Types. +A [Worker Process](/workers#worker-process) is where Workflow Functions and Activity Functions execute. +Each Worker polls exactly one [Task Queue](/task-queue), and every Worker polling a given Task Queue must register the same Workflow Types and Activity Types. -A [Worker Entity](/workers#worker-entity) is the component within a Worker Process that listens to a specific Task -Queue. +Create a Worker with `Worker.create()`, passing a connection, the Task Queue to poll, and the Workflows and Activities it can execute. +Call `run()` to start polling. -Although multiple Worker Entities can be in a single Worker Process, a single Worker Entity Worker Process may be -perfectly sufficient. For more information, see the [Worker tuning guide](/develop/worker-performance). + +[hello-world/src/worker.ts](https://github.com/temporalio/samples-typescript/blob/main/hello-world/src/worker.ts) +```ts +import { NativeConnection, Worker } from '@temporalio/worker'; +import * as activities from './activities'; + +async function run() { + // Step 1: Establish a connection with Temporal server. + // + // Worker code uses `@temporalio/worker.NativeConnection`. + // (But in your application code it's `@temporalio/client.Connection`.) + const connection = await NativeConnection.connect({ + address: 'localhost:7233', + // TLS and gRPC metadata configuration goes here. + }); + try { + // Step 2: Register Workflows and Activities with the Worker. + const worker = await Worker.create({ + connection, + namespace: 'default', + taskQueue: 'hello-world', + // Workflows are registered using a path as they run in a separate JS context. + workflowsPath: require.resolve('./workflows'), + activities, + }); + + // Step 3: Start accepting tasks on the `hello-world` queue + // + // The worker runs until it encounters an unexpected error or the process receives a shutdown signal registered on + // the SDK Runtime object. + // + // By default, worker logs are written via the Runtime logger to STDERR at INFO level. + // + // See https://typescript.temporal.io/api/classes/worker.Runtime#install to customize these defaults. + await worker.run(); + } finally { + // Close the connection once the worker has stopped + await connection.close(); + } +} + +run().catch((err) => { + console.error(err); + process.exit(1); +}); +``` + + +Workflows are registered by path rather than by value, because they run in a separate JavaScript context. + +## Register Workflows and Activities {/* #register-types */} + +All Workers listening to the same Task Queue must be registered to handle the same Workflow Types and Activity Types. +If a Worker polls a Task for a type it does not know about, the Task fails. The Workflow Execution itself does not fail. + +In development, use [`workflowsPath`](https://typescript.temporal.io/api/interfaces/worker.WorkerOptions/#workflowspath): + + +[snippets/src/worker.ts](https://github.com/temporalio/samples-typescript/blob/main/snippets/src/worker.ts) +```ts +import { Worker } from '@temporalio/worker'; +import * as activities from './activities'; + +async function run() { + const worker = await Worker.create({ + workflowsPath: require.resolve('./workflows'), + taskQueue: 'snippets', + activities, + }); + + await worker.run(); +} +``` + + +In this snippet, the Worker bundles the Workflow code at runtime. + +In production, you can improve your Worker's startup time by bundling in advance. As part of your production build, call `bundleWorkflowCode`: + + +[production/src/scripts/build-workflow-bundle.ts](https://github.com/temporalio/samples-typescript/blob/main/production/src/scripts/build-workflow-bundle.ts) +```ts +import { bundleWorkflowCode } from '@temporalio/worker'; +import { writeFile } from 'fs/promises'; +import path from 'path'; + +async function bundle() { + const { code } = await bundleWorkflowCode({ + workflowsPath: require.resolve('../workflows'), + }); + const codePath = path.join(__dirname, '../../workflow-bundle.js'); + + await writeFile(codePath, code); + console.log(`Bundle written to ${codePath}`); +} +``` + + +Then pass the bundle to the Worker: + + +[production/src/worker.ts](https://github.com/temporalio/samples-typescript/blob/main/production/src/worker.ts) +```ts +const workflowOption = () => + process.env.NODE_ENV === 'production' + ? { + workflowBundle: { + codePath: require.resolve('../workflow-bundle.js'), + }, + } + : { workflowsPath: require.resolve('./workflows') }; + +async function run() { + const worker = await Worker.create({ + ...workflowOption(), + activities, + taskQueue: 'production-sample', + }); + + await worker.run(); +} +``` + + +## Connect to Temporal Cloud {/* #run-a-temporal-cloud-worker */} + +To run a Worker against Temporal Cloud, configure the connection with your Namespace address and authentication credentials. +See [Connect to Temporal Cloud](/develop/typescript/client/temporal-client#connect-to-temporal-cloud) for setup instructions. + +## Configure Worker options {/* #worker-options */} + +[`Worker.create()`](https://typescript.temporal.io/api/classes/worker.Worker#create) accepts options that control concurrency limits, pollers, timeouts, and caching. +The defaults work for most cases. + +To tune these values against real load, see [Worker performance](/develop/worker-performance) and the [Worker tuning reference](/develop/worker-tuning-reference). + +## Run a versioned Worker {/* #versioned-worker */} + +Set a Worker Deployment Version and enable versioning in `workerDeploymentOptions`. +When `useWorkerVersioning` is `true`, `defaultVersioningBehavior` is required. + + +[features/snippets/worker/worker.ts](https://github.com/temporalio/features/blob/main/features/snippets/worker/worker.ts) +```ts +const worker = await Worker.create({ + connection, + taskQueue: 'my-task-queue', + workflowsPath: require.resolve('./workflows'), + workerDeploymentOptions: { + version: { deploymentName: 'my-app', buildId: '1.0' }, + useWorkerVersioning: true, + defaultVersioningBehavior: 'PINNED', + }, +}); +``` + + +See [Worker Versioning](/worker-versioning) for the available versioning behaviors and how new versions roll out. + +## Shut down a Worker {/* #shut-down-a-worker */} + +Workers shut down if they receive any of the Signals enumerated in +[shutdownSignals](https://typescript.temporal.io/api/interfaces/worker.RuntimeOptions#shutdownsignals): `'SIGINT'`, +`'SIGTERM'`, `'SIGQUIT'`, and `'SIGUSR2'`. + +In development, shut down Workers with `Ctrl+C` (`SIGINT`) or +[nodemon](https://github.com/temporalio/samples-typescript/blob/c37bae3ea235d1b6956fcbe805478aa46af973ce/hello-world/package.json#L10) +(`SIGUSR2`). In production, give Workers time to finish in-progress Activities by setting +[shutdownGraceTime](https://typescript.temporal.io/api/interfaces/worker.WorkerOptions#shutdowngracetime): + + +[features/snippets/worker/worker.ts](https://github.com/temporalio/features/blob/main/features/snippets/worker/worker.ts) +```ts +const worker = await Worker.create({ + connection, + taskQueue: 'my-task-queue', + workflowsPath: require.resolve('./workflows'), + shutdownGraceTime: '30s', +}); + +await worker.run(); +``` + + +As soon as a Worker receives a shutdown Signal or request, the Worker stops polling for new Tasks and allows in-flight +Tasks to complete until `shutdownGraceTime` is reached. Any Activities still running at that time stop running and are +rescheduled by the Temporal Service when an Activity timeout occurs. + +If you must guarantee that the Worker eventually shuts down, set +[shutdownForceTime](https://typescript.temporal.io/api/interfaces/worker.WorkerOptions#shutdownforcetime). + +You might want to programmatically shut down Workers (with +[Worker.shutdown()](https://typescript.temporal.io/api/classes/worker.Worker#shutdown)) in integration tests or when +automating a fleet of Workers. + +See [Worker shutdown](/encyclopedia/workers/worker-shutdown) for what happens to in-flight Workflow Tasks and Activities. + +### Worker states + +At any time, you can Query Worker state with +[Worker.getState()](https://typescript.temporal.io/api/classes/worker.Worker#getstate). A Worker is always in one of +seven states: + +- `INITIALIZED`: The initial state of the Worker after calling + [Worker.create()](https://typescript.temporal.io/api/classes/worker.Worker#create) and successfully connecting to the + server. +- `RUNNING`: [Worker.run()](https://typescript.temporal.io/api/classes/worker.Worker#run) was called and the Worker is + polling Task Queues. +- `FAILED`: The Worker encountered an unrecoverable error; `Worker.run()` should reject with the error. +- The last four states are related to the Worker shutdown process: + - `STOPPING`: The Worker received a shutdown Signal or `Worker.shutdown()` was called. The Worker will forcefully shut + down after `shutdownGraceTime` expires. + - `DRAINING`: All Workflow Tasks have been drained; waiting for Activities and cached Workflows eviction. + - `DRAINED`: All Activities and Workflows have completed; ready to shut down. + - `STOPPED`: Shutdown complete; `worker.run()` resolves. -A Worker Entity contains a Workflow Worker and/or an Activity Worker, which makes progress on Workflow Executions and -Activity Executions, respectively. +If you need more visibility into internal Worker state, see the +[Worker class](https://typescript.temporal.io/api/classes/worker.Worker) in the API reference. -## How to run a Worker on Docker in TypeScript {/* #run-a-worker-on-docker */} +## Run a Worker on Docker {/* #run-a-worker-on-docker */} :::note -To improve worker startup time, we recommend preparing workflow bundles ahead-of-time. See our -[productionsample](https://github.com/temporalio/samples-typescript/tree/main/production) for details. +To improve Worker startup time, prepare Workflow bundles ahead of time. See the +[production sample](https://github.com/temporalio/samples-typescript/tree/main/production) for details. ::: Workers based on the TypeScript SDK can be deployed and run as Docker containers. -We recommend an LTS Node.js release such as 18, 20, 22, or 24. Both `amd64` and `arm64` architectures are supported. A +Use an LTS Node.js release such as 18, 20, 22, or 24. Both `amd64` and `arm64` architectures are supported. A glibc-based image is required; musl-based images are _not_ supported (see below). -The easiest way to deploy a TypeScript SDK Worker on Docker is to start with the `node:20-bullseye` image. For example: +The most direct way to deploy a TypeScript SDK Worker on Docker is to start with the `node:20-bullseye` image. For example: ```dockerfile FROM node:20-bullseye @@ -70,7 +282,7 @@ following caveats. smaller images. However, TypeScript SDK requires the presence of root TLS certificates (the `ca-certificates` package), which are not -included in `slim` images. The `ca-certificates` package is required even when connecting to a local Temporal Server or +included in `slim` images. The `ca-certificates` package is required even when connecting to a local Temporal Service or when using a server connection config that doesn't explicitly use TLS. For this reason, the `ca-certificates` package must be installed during the construction of the Docker image. For @@ -153,142 +365,3 @@ Or like this: ```sh Error: Error relocating /opt/app/node_modules/@temporalio/core-bridge/index.node: __register_atfork: symbol not found ``` - -## How to run a Temporal Cloud Worker {/* #run-a-temporal-cloud-worker */} - -To run a Worker that uses [Temporal Cloud](/cloud), you need to provide additional connection and client options that -include the following: - -- An address that includes your [Cloud Namespace Name](/namespaces) and a port number: - `..tmprl.cloud:`. -- mTLS CA certificate. -- mTLS private key. - -For more information about managing and generating client certificates for Temporal Cloud, see -[How to manage certificates in Temporal Cloud](/cloud/certificates). - -For more information about configuring TLS to secure inter- and intra-network communication for a Temporal Service, see -[Temporal Customization Samples](https://github.com/temporalio/samples-server). - -### How to register types {/* #register-types */} - -All Workers listening to the same Task Queue name must be registered to handle the exact same Workflows Types and -Activity Types. - -If a Worker polls a Task for a Workflow Type or Activity Type it does not know about, it fails that Task. However, the -failure of the Task does not cause the associated Workflow Execution to fail. - -In development, use -[`workflowsPath`](https://typescript.temporal.io/api/interfaces/worker.WorkerOptions/#workflowspath): - - -[snippets/src/worker.ts](https://github.com/temporalio/samples-typescript/blob/main/snippets/src/worker.ts) -```ts -import { Worker } from '@temporalio/worker'; -import * as activities from './activities'; - -async function run() { - const worker = await Worker.create({ - workflowsPath: require.resolve('./workflows'), - taskQueue: 'snippets', - activities, - }); - - await worker.run(); -} -``` - - -In this snippet, the Worker bundles the Workflow code at runtime. - -In production, you can improve your Worker's startup time by bundling in advance: as part of your production build, call -`bundleWorkflowCode`: - - -[production/src/scripts/build-workflow-bundle.ts](https://github.com/temporalio/samples-typescript/blob/main/production/src/scripts/build-workflow-bundle.ts) -```ts -import { bundleWorkflowCode } from '@temporalio/worker'; -import { writeFile } from 'fs/promises'; -import path from 'path'; - -async function bundle() { - const { code } = await bundleWorkflowCode({ - workflowsPath: require.resolve('../workflows'), - }); - const codePath = path.join(__dirname, '../../workflow-bundle.js'); - - await writeFile(codePath, code); - console.log(`Bundle written to ${codePath}`); -} -``` - - -Then the bundle can be passed to the Worker: - - -[production/src/worker.ts](https://github.com/temporalio/samples-typescript/blob/main/production/src/worker.ts) -```ts -const workflowOption = () => - process.env.NODE_ENV === 'production' - ? { - workflowBundle: { - codePath: require.resolve('../workflow-bundle.js'), - }, - } - : { workflowsPath: require.resolve('./workflows') }; - -async function run() { - const worker = await Worker.create({ - ...workflowOption(), - activities, - taskQueue: 'production-sample', - }); - - await worker.run(); -} -``` - - -## How to shut down a Worker and track its state {/* #shut-down-a-worker */} - -Workers shut down if they receive any of the Signals enumerated in -[shutdownSignals](https://typescript.temporal.io/api/interfaces/worker.RuntimeOptions#shutdownsignals): `'SIGINT'`, -`'SIGTERM'`, `'SIGQUIT'`, and `'SIGUSR2'`. - -In development, we shut down Workers with `Ctrl+C` (`SIGINT`) or -[nodemon](https://github.com/temporalio/samples-typescript/blob/c37bae3ea235d1b6956fcbe805478aa46af973ce/hello-world/package.json#L10) -(`SIGUSR2`). In production, you usually want to give Workers time to finish any in-progress Activities by setting -[shutdownGraceTime](https://typescript.temporal.io/api/interfaces/worker.WorkerOptions#shutdowngracetime). - -As soon as a Worker receives a shutdown Signal or request, the Worker stops polling for new Tasks and allows in-flight -Tasks to complete until `shutdownGraceTime` is reached. Any Activities that are still running at that time will stop -running and will be rescheduled by Temporal Server when an Activity timeout occurs. - -If you must guarantee that the Worker eventually shuts down, you can set -[shutdownForceTime](https://typescript.temporal.io/api/interfaces/worker.WorkerOptions#shutdownforcetime). - -You might want to programmatically shut down Workers (with -[Worker.shutdown()](https://typescript.temporal.io/api/classes/worker.Worker#shutdown)) in integration tests or when -automating a fleet of Workers. - -### Worker states - -At any time, you can Query Worker state with -[Worker.getState()](https://typescript.temporal.io/api/classes/worker.Worker#getstate). A Worker is always in one of -seven states: - -- `INITIALIZED`: The initial state of the Worker after calling - [Worker.create()](https://typescript.temporal.io/api/classes/worker.Worker#create) and successfully connecting to the - server. -- `RUNNING`: [Worker.run()](https://typescript.temporal.io/api/classes/worker.Worker#run) was called and the Worker is - polling Task Queues. -- `FAILED`: The Worker encountered an unrecoverable error; `Worker.run()` should reject with the error. -- The last four states are related to the Worker shutdown process: - - `STOPPING`: The Worker received a shutdown Signal or `Worker.shutdown()` was called. The Worker will forcefully shut - down after `shutdownGraceTime` expires. - - `DRAINING`: All Workflow Tasks have been drained; waiting for Activities and cached Workflows eviction. - - `DRAINED`: All Activities and Workflows have completed; ready to shut down. - - `STOPPED`: Shutdown complete; `worker.run()` resolves. - -If you need more visibility into internal Worker state, see the -[Worker class](https://typescript.temporal.io/api/classes/worker.Worker) in the API reference.