@temporalio/lambda-worker 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2021-2025 Temporal Technologies Inc. All rights reserved.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,158 @@
1
+ # lambda-worker
2
+
3
+ A wrapper for running [Temporal](https://temporal.io) workers inside AWS Lambda. A single
4
+ `runWorker` call handles the full per-invocation lifecycle: connecting to the Temporal server,
5
+ creating a worker with Lambda-tuned defaults, polling for tasks, and gracefully shutting down before
6
+ the invocation deadline.
7
+
8
+ ## Quick start
9
+
10
+ ```typescript
11
+ // handler.ts
12
+ import { runWorker } from '@temporalio/lambda-worker';
13
+ import * as activities from './activities';
14
+
15
+ export const handler = runWorker({ deploymentName: 'my-service', buildId: 'v1.0' }, (config) => {
16
+ config.workerOptions.taskQueue = 'my-task-queue';
17
+ config.workerOptions.workflowBundle = { code: require('./workflow-bundle.js') };
18
+ config.workerOptions.activities = activities;
19
+ });
20
+ ```
21
+
22
+ Prefer `workflowBundle` (pre-bundled with `bundleWorkflowCode`) over `workflowsPath` to avoid
23
+ webpack bundling overhead on Lambda cold starts.
24
+
25
+ ## Configuration
26
+
27
+ Client connection settings (address, namespace, TLS, API key) are loaded automatically from a TOML
28
+ config file and/or environment variables via `@temporalio/envconfig`. The config file is resolved in
29
+ order:
30
+
31
+ 1. `TEMPORAL_CONFIG_FILE` env var, if set.
32
+ 2. `temporal.toml` in `$LAMBDA_TASK_ROOT` (typically `/var/task`).
33
+ 3. `temporal.toml` in the current working directory.
34
+
35
+ The file is optional -- if absent, only environment variables are used.
36
+
37
+ The configure callback receives a `LambdaWorkerConfig` object with fields pre-populated with
38
+ Lambda-appropriate defaults. Override any field directly in the callback. The `taskQueue` in
39
+ `workerOptions` is pre-populated from the `TEMPORAL_TASK_QUEUE` environment variable if set.
40
+
41
+ ## Lambda-tuned worker defaults
42
+
43
+ The package applies conservative concurrency limits suited to Lambda's resource constraints:
44
+
45
+ | Setting | Default |
46
+ | -------------------------------------- | ------------------ |
47
+ | `maxConcurrentActivityTaskExecutions` | 2 |
48
+ | `maxConcurrentWorkflowTaskExecutions` | 10 |
49
+ | `maxConcurrentLocalActivityExecutions` | 2 |
50
+ | `maxConcurrentNexusTaskExecutions` | 5 |
51
+ | `workflowTaskPollerBehavior` | `SimpleMaximum(2)` |
52
+ | `activityTaskPollerBehavior` | `SimpleMaximum(1)` |
53
+ | `nexusTaskPollerBehavior` | `SimpleMaximum(1)` |
54
+ | `shutdownGraceTime` | 5 seconds |
55
+ | `maxCachedWorkflows` | 30 |
56
+
57
+ Worker Deployment Versioning is always enabled. The default versioning behavior is `PINNED`; to
58
+ change it, override `workerDeploymentOptions.defaultVersioningBehavior` in the configure callback:
59
+
60
+ ```typescript
61
+ config.workerOptions.workerDeploymentOptions = {
62
+ defaultVersioningBehavior: 'AUTO_UPGRADE',
63
+ };
64
+ ```
65
+
66
+ ## Logging
67
+
68
+ The Temporal `Runtime` is installed automatically by `runWorker`. If
69
+ [`@aws-lambda-powertools/logger`](https://docs.aws.amazon.com/powertools/typescript/latest/features/logger/)
70
+ is installed, the runtime is configured with a `PowertoolsLoggerAdapter` that produces structured
71
+ JSON output automatically parsed by CloudWatch Logs. If Powertools is not installed, the SDK's
72
+ default human-readable logger is used.
73
+
74
+ To customize the logger or other runtime options, modify `config.runtimeOptions` in the configure
75
+ callback:
76
+
77
+ ```typescript
78
+ export const handler = runWorker({ deploymentName: 'my-service', buildId: 'v1.0' }, (config) => {
79
+ config.workerOptions.taskQueue = 'my-task-queue';
80
+ // Use a custom logger
81
+ config.runtimeOptions.logger = myCustomLogger;
82
+ // Or configure telemetry
83
+ config.runtimeOptions.telemetryOptions = { ... };
84
+ });
85
+ ```
86
+
87
+ Shutdown signals are disabled by default (`shutdownSignals: []`) since Lambda manages its own
88
+ lifecycle.
89
+
90
+ ## Observability
91
+
92
+ Metrics and tracing are opt-in. The `otel` module provides convenience helpers for
93
+ [AWS Distro for OpenTelemetry (ADOT)](https://aws-otel.github.io/docs/getting-started/lambda).
94
+
95
+ Call `applyDefaults(config)` in your configure callback to:
96
+
97
+ - Register Temporal SDK interceptors (`@temporalio/interceptors-opentelemetry`) for tracing
98
+ Workflow, Activity, and Nexus calls.
99
+ - Configure the Temporal Core SDK (Rust) to export its own metrics (task latencies, poll counts,
100
+ etc.) via OTLP to the collector.
101
+
102
+ ```typescript
103
+ import { runWorker } from '@temporalio/lambda-worker';
104
+ import { applyDefaults } from '@temporalio/lambda-worker/otel';
105
+ import * as activities from './activities';
106
+
107
+ export const handler = runWorker({ deploymentName: 'my-service', buildId: 'v1.0' }, (config) => {
108
+ applyDefaults(config);
109
+ config.workerOptions.taskQueue = 'my-task-queue';
110
+ config.workerOptions.workflowBundle = { code: require('./workflow-bundle.js') };
111
+ config.workerOptions.activities = activities;
112
+ });
113
+ ```
114
+
115
+ **Important**: When pre-bundling Workflow code with `bundleWorkflowCode()`, pass `makeOtelPlugin()`
116
+ so that Workflow interceptor modules are included in the bundle:
117
+
118
+ ```typescript
119
+ import { bundleWorkflowCode } from '@temporalio/worker';
120
+ import { makeOtelPlugin } from '@temporalio/lambda-worker/otel';
121
+
122
+ const { plugin } = makeOtelPlugin();
123
+ const { code } = await bundleWorkflowCode({
124
+ workflowsPath: require.resolve('./workflows'),
125
+ plugins: [plugin],
126
+ });
127
+ ```
128
+
129
+ ### AWS setup
130
+
131
+ Attach two Lambda layers:
132
+
133
+ 1. **[ADOT JavaScript layer](https://aws-otel.github.io/docs/getting-started/lambda/lambda-js)** —
134
+ auto-instruments the handler and exports Node.js-side traces (Lambda invocation spans, HTTP
135
+ calls, etc.) to X-Ray.
136
+ 2. **[ADOT Collector layer](https://aws-otel.github.io/docs/getting-started/lambda)**
137
+ (`aws-otel-collector-amd64`) — runs the OTel Collector as a Lambda extension, receiving
138
+ Temporal Core SDK metrics and SDK trace spans via OTLP gRPC on `localhost:4317`, then
139
+ forwarding them to CloudWatch/X-Ray via a custom collector config.
140
+
141
+ Set these environment variables:
142
+
143
+ ```
144
+ AWS_LAMBDA_EXEC_WRAPPER=/opt/otel-instrument
145
+ OPENTELEMETRY_COLLECTOR_CONFIG_URI=/var/task/otel-collector-config.yaml
146
+ ```
147
+
148
+ `AWS_LAMBDA_EXEC_WRAPPER` enables the JS layer's auto-instrumentation.
149
+ `OPENTELEMETRY_COLLECTOR_CONFIG_URI` points the collector at a custom config file bundled in
150
+ your deployment package — use this to route metrics to CloudWatch EMF, traces to X-Ray, or any
151
+ other supported exporter.
152
+
153
+ Enable X-Ray active tracing on the Lambda function (required for traces to appear):
154
+
155
+ ```bash
156
+ aws lambda update-function-configuration --function-name <function-name> \
157
+ --tracing-config Mode=Active
158
+ ```
@@ -0,0 +1,12 @@
1
+ import { type ClientConnectConfig, type LoadClientProfileOptions } from '@temporalio/envconfig';
2
+ /**
3
+ * Load client connection config with Lambda-aware config file resolution.
4
+ *
5
+ * Resolution order:
6
+ * 1. User-provided `configSource` in options (passthrough)
7
+ * 2. `TEMPORAL_CONFIG_FILE` env var (handled by envconfig)
8
+ * 3. `$LAMBDA_TASK_ROOT/temporal.toml`
9
+ * 4. `process.cwd()/temporal.toml`
10
+ * 5. Envconfig default (XDG paths / env-only)
11
+ */
12
+ export declare function loadLambdaClientConnectConfig(options?: Partial<LoadClientProfileOptions>): ClientConnectConfig;
package/lib/config.js ADDED
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.loadLambdaClientConnectConfig = loadLambdaClientConnectConfig;
27
+ const fs = __importStar(require("node:fs"));
28
+ const path = __importStar(require("node:path"));
29
+ const envconfig_1 = require("@temporalio/envconfig");
30
+ /**
31
+ * Load client connection config with Lambda-aware config file resolution.
32
+ *
33
+ * Resolution order:
34
+ * 1. User-provided `configSource` in options (passthrough)
35
+ * 2. `TEMPORAL_CONFIG_FILE` env var (handled by envconfig)
36
+ * 3. `$LAMBDA_TASK_ROOT/temporal.toml`
37
+ * 4. `process.cwd()/temporal.toml`
38
+ * 5. Envconfig default (XDG paths / env-only)
39
+ */
40
+ function loadLambdaClientConnectConfig(options) {
41
+ const resolvedOptions = { ...options };
42
+ // If the user provided a configSource or TEMPORAL_CONFIG_FILE is set, let envconfig handle it
43
+ if (!resolvedOptions.configSource && !process.env['TEMPORAL_CONFIG_FILE']) {
44
+ const lambdaConfigPath = findLambdaConfigFile();
45
+ if (lambdaConfigPath) {
46
+ resolvedOptions.configSource = { path: lambdaConfigPath };
47
+ }
48
+ }
49
+ return (0, envconfig_1.loadClientConnectConfig)(resolvedOptions);
50
+ }
51
+ function findLambdaConfigFile() {
52
+ const candidates = [];
53
+ const lambdaTaskRoot = process.env['LAMBDA_TASK_ROOT'];
54
+ if (lambdaTaskRoot) {
55
+ candidates.push(path.join(lambdaTaskRoot, 'temporal.toml'));
56
+ }
57
+ candidates.push(path.join(process.cwd(), 'temporal.toml'));
58
+ for (const candidate of candidates) {
59
+ try {
60
+ fs.accessSync(candidate, fs.constants.R_OK);
61
+ return candidate;
62
+ }
63
+ catch {
64
+ // File doesn't exist or isn't readable, try next
65
+ }
66
+ }
67
+ return undefined;
68
+ }
69
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAkBA,sEAYC;AA9BD,4CAA8B;AAC9B,gDAAkC;AAClC,qDAI+B;AAE/B;;;;;;;;;GASG;AACH,SAAgB,6BAA6B,CAAC,OAA2C;IACvF,MAAM,eAAe,GAA6B,EAAE,GAAG,OAAO,EAAE,CAAC;IAEjE,8FAA8F;IAC9F,IAAI,CAAC,eAAe,CAAC,YAAY,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,EAAE,CAAC;QAC1E,MAAM,gBAAgB,GAAG,oBAAoB,EAAE,CAAC;QAChD,IAAI,gBAAgB,EAAE,CAAC;YACrB,eAAe,CAAC,YAAY,GAAG,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC;QAC5D,CAAC;IACH,CAAC;IAED,OAAO,IAAA,mCAAuB,EAAC,eAAe,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,oBAAoB;IAC3B,MAAM,UAAU,GAAa,EAAE,CAAC;IAEhC,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IACvD,IAAI,cAAc,EAAE,CAAC;QACnB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC,CAAC;IAC9D,CAAC;IAED,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;IAE3D,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,CAAC;YACH,EAAE,CAAC,UAAU,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAC5C,OAAO,SAAS,CAAC;QACnB,CAAC;QAAC,MAAM,CAAC;YACP,iDAAiD;QACnD,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { WorkerOptions } from '@temporalio/worker';
2
+ /** Minimum work time in ms — error if less. */
3
+ export declare const MINIMUM_WORK_TIME_MS = 1000;
4
+ /** Low work time threshold in ms — warn if less. */
5
+ export declare const WARN_WORK_TIME_MS = 5000;
6
+ /**
7
+ * Default buffer in ms before the Lambda deadline to begin shutdown.
8
+ * Equals the default shutdownGraceTime (5s) + 2s margin.
9
+ */
10
+ export declare const DEFAULT_SHUTDOWN_DEADLINE_BUFFER_MS = 7000;
11
+ /**
12
+ * Lambda-tuned worker defaults. These are conservative values appropriate for
13
+ * Lambda's memory and CPU constraints. Users can override any of these via the
14
+ * configure callback.
15
+ */
16
+ export declare const LAMBDA_WORKER_DEFAULTS: Partial<WorkerOptions>;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LAMBDA_WORKER_DEFAULTS = exports.DEFAULT_SHUTDOWN_DEADLINE_BUFFER_MS = exports.WARN_WORK_TIME_MS = exports.MINIMUM_WORK_TIME_MS = void 0;
4
+ /** Minimum work time in ms — error if less. */
5
+ exports.MINIMUM_WORK_TIME_MS = 1000;
6
+ /** Low work time threshold in ms — warn if less. */
7
+ exports.WARN_WORK_TIME_MS = 5000;
8
+ /**
9
+ * Default buffer in ms before the Lambda deadline to begin shutdown.
10
+ * Equals the default shutdownGraceTime (5s) + 2s margin.
11
+ */
12
+ exports.DEFAULT_SHUTDOWN_DEADLINE_BUFFER_MS = 7000;
13
+ /**
14
+ * Lambda-tuned worker defaults. These are conservative values appropriate for
15
+ * Lambda's memory and CPU constraints. Users can override any of these via the
16
+ * configure callback.
17
+ */
18
+ exports.LAMBDA_WORKER_DEFAULTS = {
19
+ maxConcurrentActivityTaskExecutions: 2,
20
+ maxConcurrentWorkflowTaskExecutions: 10,
21
+ maxConcurrentLocalActivityExecutions: 2,
22
+ maxConcurrentNexusTaskExecutions: 5,
23
+ shutdownGraceTime: '5s',
24
+ maxCachedWorkflows: 30,
25
+ workflowTaskPollerBehavior: { type: 'simple-maximum', maximum: 2 },
26
+ activityTaskPollerBehavior: { type: 'simple-maximum', maximum: 1 },
27
+ nexusTaskPollerBehavior: { type: 'simple-maximum', maximum: 1 },
28
+ };
29
+ //# sourceMappingURL=defaults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":";;;AAEA,+CAA+C;AAClC,QAAA,oBAAoB,GAAG,IAAI,CAAC;AAEzC,oDAAoD;AACvC,QAAA,iBAAiB,GAAG,IAAI,CAAC;AAEtC;;;GAGG;AACU,QAAA,mCAAmC,GAAG,IAAI,CAAC;AAExD;;;;GAIG;AACU,QAAA,sBAAsB,GAA2B;IAC5D,mCAAmC,EAAE,CAAC;IACtC,mCAAmC,EAAE,EAAE;IACvC,oCAAoC,EAAE,CAAC;IACvC,gCAAgC,EAAE,CAAC;IACnC,iBAAiB,EAAE,IAAI;IACvB,kBAAkB,EAAE,EAAE;IACtB,0BAA0B,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,CAAC,EAAE;IAClE,0BAA0B,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,CAAC,EAAE;IAClE,uBAAuB,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,CAAC,EAAE;CAChE,CAAC"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export { runWorker } from './lambda-worker';
2
+ export { PowertoolsLoggerAdapter } from './json-logger';
3
+ export type { LambdaWorkerConfig, LambdaHandler, ShutdownHook } from './types';
package/lib/index.js ADDED
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PowertoolsLoggerAdapter = exports.runWorker = void 0;
4
+ var lambda_worker_1 = require("./lambda-worker");
5
+ Object.defineProperty(exports, "runWorker", { enumerable: true, get: function () { return lambda_worker_1.runWorker; } });
6
+ var json_logger_1 = require("./json-logger");
7
+ Object.defineProperty(exports, "PowertoolsLoggerAdapter", { enumerable: true, get: function () { return json_logger_1.PowertoolsLoggerAdapter; } });
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,iDAA4C;AAAnC,0GAAA,SAAS,OAAA;AAClB,6CAAwD;AAA/C,sHAAA,uBAAuB,OAAA"}
@@ -0,0 +1,29 @@
1
+ import type { Logger as PowertoolsLogger } from '@aws-lambda-powertools/logger';
2
+ import type { Context } from 'aws-lambda';
3
+ import type { LogLevel, LogMetadata } from '@temporalio/common';
4
+ import type { Logger } from '@temporalio/worker';
5
+ /**
6
+ * Adapter that wraps an AWS Lambda Powertools Logger to implement the Temporal SDK Logger interface.
7
+ *
8
+ * This is used as the default logger for the Lambda worker, producing structured JSON output
9
+ * that CloudWatch Logs automatically parses.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * import { Logger } from '@aws-lambda-powertools/logger';
14
+ * import { PowertoolsLoggerAdapter } from '@temporalio/lambda-worker';
15
+ *
16
+ * const adapter = new PowertoolsLoggerAdapter(new Logger({ serviceName: 'my-worker' }));
17
+ * ```
18
+ */
19
+ export declare class PowertoolsLoggerAdapter implements Logger {
20
+ private readonly ptLogger;
21
+ constructor(ptLogger: PowertoolsLogger);
22
+ addContext(context: Context): void;
23
+ log(level: LogLevel, message: string, meta?: LogMetadata): void;
24
+ trace(message: string, meta?: LogMetadata): void;
25
+ debug(message: string, meta?: LogMetadata): void;
26
+ info(message: string, meta?: LogMetadata): void;
27
+ warn(message: string, meta?: LogMetadata): void;
28
+ error(message: string, meta?: LogMetadata): void;
29
+ }
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PowertoolsLoggerAdapter = void 0;
4
+ /**
5
+ * Adapter that wraps an AWS Lambda Powertools Logger to implement the Temporal SDK Logger interface.
6
+ *
7
+ * This is used as the default logger for the Lambda worker, producing structured JSON output
8
+ * that CloudWatch Logs automatically parses.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { Logger } from '@aws-lambda-powertools/logger';
13
+ * import { PowertoolsLoggerAdapter } from '@temporalio/lambda-worker';
14
+ *
15
+ * const adapter = new PowertoolsLoggerAdapter(new Logger({ serviceName: 'my-worker' }));
16
+ * ```
17
+ */
18
+ class PowertoolsLoggerAdapter {
19
+ ptLogger;
20
+ constructor(ptLogger) {
21
+ this.ptLogger = ptLogger;
22
+ }
23
+ addContext(context) {
24
+ this.ptLogger.addContext(context);
25
+ }
26
+ log(level, message, meta) {
27
+ switch (level) {
28
+ case 'TRACE':
29
+ this.ptLogger.debug(message, { ...meta, traceLevel: true });
30
+ break;
31
+ case 'DEBUG':
32
+ this.ptLogger.debug(message, meta);
33
+ break;
34
+ case 'INFO':
35
+ this.ptLogger.info(message, meta);
36
+ break;
37
+ case 'WARN':
38
+ this.ptLogger.warn(message, meta);
39
+ break;
40
+ case 'ERROR':
41
+ this.ptLogger.error(message, meta);
42
+ break;
43
+ default:
44
+ level;
45
+ break;
46
+ }
47
+ }
48
+ trace(message, meta) {
49
+ this.log('TRACE', message, meta);
50
+ }
51
+ debug(message, meta) {
52
+ this.log('DEBUG', message, meta);
53
+ }
54
+ info(message, meta) {
55
+ this.log('INFO', message, meta);
56
+ }
57
+ warn(message, meta) {
58
+ this.log('WARN', message, meta);
59
+ }
60
+ error(message, meta) {
61
+ this.log('ERROR', message, meta);
62
+ }
63
+ }
64
+ exports.PowertoolsLoggerAdapter = PowertoolsLoggerAdapter;
65
+ //# sourceMappingURL=json-logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-logger.js","sourceRoot":"","sources":["../src/json-logger.ts"],"names":[],"mappings":";;;AAKA;;;;;;;;;;;;;GAaG;AACH,MAAa,uBAAuB;IACL;IAA7B,YAA6B,QAA0B;QAA1B,aAAQ,GAAR,QAAQ,CAAkB;IAAG,CAAC;IAE3D,UAAU,CAAC,OAAgB;QACzB,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;IAED,GAAG,CAAC,KAAe,EAAE,OAAe,EAAE,IAAkB;QACtD,QAAQ,KAAK,EAAE,CAAC;YACd,KAAK,OAAO;gBACV,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC5D,MAAM;YACR,KAAK,OAAO;gBACV,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,IAA+B,CAAC,CAAC;gBAC9D,MAAM;YACR,KAAK,MAAM;gBACT,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,IAA+B,CAAC,CAAC;gBAC7D,MAAM;YACR,KAAK,MAAM;gBACT,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,IAA+B,CAAC,CAAC;gBAC7D,MAAM;YACR,KAAK,OAAO;gBACV,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,IAA+B,CAAC,CAAC;gBAC9D,MAAM;YACR;gBACE,KAAqB,CAAC;gBACtB,MAAM;QACV,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,IAAkB;QACvC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,IAAkB;QACvC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,IAAkB;QACtC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,IAAkB;QACtC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,IAAkB;QACvC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;CACF;AAjDD,0DAiDC"}
@@ -0,0 +1,51 @@
1
+ import type { WorkerDeploymentVersion, Logger } from '@temporalio/common';
2
+ import { type WorkerOptions, type NativeConnectionOptions, type RuntimeOptions } from '@temporalio/worker';
3
+ import type { ClientConnectConfig } from '@temporalio/envconfig';
4
+ import type { LambdaWorkerConfig, LambdaHandler } from './types';
5
+ /**
6
+ * @internal Dependency injection interface for testing.
7
+ */
8
+ export interface WorkerDeps {
9
+ connect: (options: NativeConnectionOptions) => Promise<{
10
+ close(): Promise<void>;
11
+ }>;
12
+ createWorker: (options: WorkerOptions) => Promise<{
13
+ runUntil(p: Promise<void>): Promise<void>;
14
+ }>;
15
+ loadConnectConfig: () => ClientConnectConfig;
16
+ installRuntime: (options: RuntimeOptions) => void;
17
+ getLogger: () => Logger;
18
+ }
19
+ /**
20
+ * Create an AWS Lambda handler that runs a Temporal Worker for the duration of each invocation.
21
+ *
22
+ * The handler connects to Temporal, creates a Worker, polls for tasks until the Lambda deadline
23
+ * approaches, then gracefully shuts down and runs any registered shutdown hooks.
24
+ *
25
+ * Calling this more than once will result in an error.
26
+ *
27
+ * @param version - The worker deployment version. Worker versioning is always enabled.
28
+ * @param configure - Callback to customize the pre-populated {@link LambdaWorkerConfig}.
29
+ * Mutate the config object directly (e.g., set `config.workerOptions.taskQueue`).
30
+ * @returns A Lambda handler function.
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * import { runWorker } from '@temporalio/lambda-worker';
35
+ * import * as activities from './activities';
36
+ *
37
+ * export const handler = runWorker(
38
+ * { buildId: 'v1.0.0', deploymentName: 'my-service' },
39
+ * (config) => {
40
+ * config.workerOptions.taskQueue = 'my-task-queue';
41
+ * config.workerOptions.workflowBundle = { code: require('./workflow-bundle.js') };
42
+ * config.workerOptions.activities = activities;
43
+ * },
44
+ * );
45
+ * ```
46
+ */
47
+ export declare function runWorker(version: WorkerDeploymentVersion, configure: (config: LambdaWorkerConfig) => void): LambdaHandler;
48
+ /**
49
+ * @internal Testable implementation of runWorker with injected dependencies.
50
+ */
51
+ export declare function _runWorkerInternal(version: WorkerDeploymentVersion, configure: (config: LambdaWorkerConfig) => void, deps: WorkerDeps): LambdaHandler;
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runWorker = runWorker;
4
+ exports._runWorkerInternal = _runWorkerInternal;
5
+ const promises_1 = require("timers/promises");
6
+ const worker_1 = require("@temporalio/worker");
7
+ const defaults_1 = require("./defaults");
8
+ const config_1 = require("./config");
9
+ const json_logger_1 = require("./json-logger");
10
+ const logger_factory_1 = require("./logger-factory");
11
+ const defaultDeps = {
12
+ connect: (opts) => worker_1.NativeConnection.connect(opts),
13
+ createWorker: (opts) => worker_1.Worker.create(opts),
14
+ loadConnectConfig: config_1.loadLambdaClientConnectConfig,
15
+ installRuntime: (opts) => worker_1.Runtime.install(opts),
16
+ getLogger: () => worker_1.Runtime.instance().logger,
17
+ };
18
+ /**
19
+ * Create an AWS Lambda handler that runs a Temporal Worker for the duration of each invocation.
20
+ *
21
+ * The handler connects to Temporal, creates a Worker, polls for tasks until the Lambda deadline
22
+ * approaches, then gracefully shuts down and runs any registered shutdown hooks.
23
+ *
24
+ * Calling this more than once will result in an error.
25
+ *
26
+ * @param version - The worker deployment version. Worker versioning is always enabled.
27
+ * @param configure - Callback to customize the pre-populated {@link LambdaWorkerConfig}.
28
+ * Mutate the config object directly (e.g., set `config.workerOptions.taskQueue`).
29
+ * @returns A Lambda handler function.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * import { runWorker } from '@temporalio/lambda-worker';
34
+ * import * as activities from './activities';
35
+ *
36
+ * export const handler = runWorker(
37
+ * { buildId: 'v1.0.0', deploymentName: 'my-service' },
38
+ * (config) => {
39
+ * config.workerOptions.taskQueue = 'my-task-queue';
40
+ * config.workerOptions.workflowBundle = { code: require('./workflow-bundle.js') };
41
+ * config.workerOptions.activities = activities;
42
+ * },
43
+ * );
44
+ * ```
45
+ */
46
+ function runWorker(version, configure) {
47
+ return _runWorkerInternal(version, configure, defaultDeps);
48
+ }
49
+ /**
50
+ * @internal Testable implementation of runWorker with injected dependencies.
51
+ */
52
+ function _runWorkerInternal(version, configure, deps) {
53
+ const config = {
54
+ workerOptions: {
55
+ ...defaults_1.LAMBDA_WORKER_DEFAULTS,
56
+ workerDeploymentOptions: {
57
+ defaultVersioningBehavior: 'PINNED',
58
+ },
59
+ },
60
+ runtimeOptions: {
61
+ logger: (0, logger_factory_1.makePowertoolsLogger)(),
62
+ shutdownSignals: [],
63
+ },
64
+ shutdownHooks: [],
65
+ };
66
+ const envTaskQueue = process.env['TEMPORAL_TASK_QUEUE'];
67
+ if (envTaskQueue) {
68
+ config.workerOptions.taskQueue = envTaskQueue;
69
+ }
70
+ const connectConfig = deps.loadConnectConfig();
71
+ config.connectionOptions = { ...connectConfig.connectionOptions };
72
+ config.namespace = connectConfig.namespace || 'default';
73
+ configure(config);
74
+ const taskQueue = config.workerOptions.taskQueue;
75
+ if (!taskQueue) {
76
+ throw new Error('taskQueue is required: set config.workerOptions.taskQueue in the configure callback ' +
77
+ 'or set the TEMPORAL_TASK_QUEUE environment variable');
78
+ }
79
+ // Install the Runtime with the (possibly user-modified) options
80
+ deps.installRuntime(config.runtimeOptions);
81
+ const shutdownDeadlineBufferMs = config.shutdownDeadlineBufferMs ?? defaults_1.DEFAULT_SHUTDOWN_DEADLINE_BUFFER_MS;
82
+ const runtimeLogger = config.runtimeOptions.logger;
83
+ return async (_event, context) => {
84
+ if (runtimeLogger instanceof json_logger_1.PowertoolsLoggerAdapter) {
85
+ runtimeLogger.addContext(context);
86
+ }
87
+ const logger = deps.getLogger();
88
+ const remainingMs = context.getRemainingTimeInMillis();
89
+ const workTimeMs = remainingMs - shutdownDeadlineBufferMs;
90
+ if (workTimeMs <= defaults_1.MINIMUM_WORK_TIME_MS) {
91
+ throw new Error(`Insufficient time for Lambda worker: ${remainingMs}ms remaining, ` +
92
+ `${shutdownDeadlineBufferMs}ms shutdown buffer, only ${workTimeMs}ms work time ` +
93
+ `(minimum: ${defaults_1.MINIMUM_WORK_TIME_MS}ms)`);
94
+ }
95
+ if (workTimeMs < defaults_1.WARN_WORK_TIME_MS) {
96
+ logger.warn('Low work time available for Lambda worker', {
97
+ remainingMs,
98
+ shutdownDeadlineBufferMs,
99
+ workTimeMs,
100
+ });
101
+ }
102
+ const identity = `${context.awsRequestId}@${context.invokedFunctionArn}`;
103
+ let connection;
104
+ try {
105
+ connection = await deps.connect(config.connectionOptions ?? {});
106
+ const workerOptions = {
107
+ ...config.workerOptions,
108
+ taskQueue,
109
+ connection: connection,
110
+ namespace: config.namespace,
111
+ identity,
112
+ workerDeploymentOptions: {
113
+ version,
114
+ useWorkerVersioning: true,
115
+ defaultVersioningBehavior: config.workerOptions.workerDeploymentOptions?.defaultVersioningBehavior ?? 'PINNED',
116
+ },
117
+ };
118
+ const worker = await deps.createWorker(workerOptions);
119
+ await worker.runUntil((0, promises_1.setTimeout)(workTimeMs));
120
+ }
121
+ finally {
122
+ for (const hook of config.shutdownHooks) {
123
+ try {
124
+ await hook();
125
+ }
126
+ catch (err) {
127
+ logger.error('Lambda worker shutdown hook failed', { error: err });
128
+ }
129
+ }
130
+ try {
131
+ if (connection) {
132
+ await connection.close();
133
+ }
134
+ }
135
+ catch (err) {
136
+ logger.error('Failed to close Temporal connection', { error: err });
137
+ }
138
+ }
139
+ };
140
+ }
141
+ //# sourceMappingURL=lambda-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lambda-worker.js","sourceRoot":"","sources":["../src/lambda-worker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { Logger } from '@temporalio/worker';
2
+ /**
3
+ * Create a Powertools-based logger for the Lambda worker.
4
+ *
5
+ * If `@aws-lambda-powertools/logger` is installed, returns a
6
+ * {@link PowertoolsLoggerAdapter} wrapping a Powertools Logger.
7
+ * Otherwise, returns `undefined`, causing the Runtime to fall back
8
+ * to its default logger.
9
+ */
10
+ export declare function makePowertoolsLogger(): Logger | undefined;