UNPKG

@temporalio/worker

Version:
304 lines 14.9 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.isCodeBundleOption = isCodeBundleOption; exports.isPathBundleOption = isPathBundleOption; exports.defaultSinks = defaultSinks; exports.appendDefaultInterceptors = appendDefaultInterceptors; exports.compileWorkerOptions = compileWorkerOptions; exports.toNativeWorkerOptions = toNativeWorkerOptions; exports.toNativeTaskPollerBehavior = toNativeTaskPollerBehavior; const os = __importStar(require("node:os")); const v8 = __importStar(require("node:v8")); const time_1 = require("@temporalio/common/lib/time"); const internal_non_workflow_1 = require("@temporalio/common/lib/internal-non-workflow"); const activity_log_interceptor_1 = require("./activity-log-interceptor"); const logger_1 = require("./workflow/logger"); const metrics_1 = require("./workflow/metrics"); const runtime_1 = require("./runtime"); const utils_1 = require("./utils"); const worker_tuner_1 = require("./worker-tuner"); function isCodeBundleOption(bundleOpt) { const opt = bundleOpt; // Cast to access properties without TS complaining return typeof opt.code === 'string'; } function isPathBundleOption(bundleOpt) { const opt = bundleOpt; // Cast to access properties without TS complaining return typeof opt.codePath === 'string'; } // Sinks and Interceptors ////////////////////////////////////////////////////////////////////////// /** * Build the sink used internally by the SDK to forwards log messages from the Workflow sandbox to an actual logger. * * @param logger a {@link Logger} - defaults to the {@link Runtime} singleton logger. * @deprecated Calling `defaultSink()` is no longer required. To configure a custom logger, set the * {@link Runtime.logger} property instead. */ // eslint-disable-next-line deprecation/deprecation function defaultSinks(logger) { // initLoggerSink() returns a sink that complies to the new LoggerSinksInternal API (ie. named __temporal_logger), but // code that is still calling defaultSinks() expects return type to match the deprecated LoggerSinks API. Silently // cast just to mask type checking issues, even though we know this is wrong. Users shouldn't call functions directly // on the returned object anyway. // If no logger was provided, the legacy behavior was to _lazily_ set the sink's logger to the Runtime's logger. // This was required because we may call defaultSinks() before the Runtime is initialized. We preserve that behavior // here by silently not initializing the sink if no logger is provided. // eslint-disable-next-line deprecation/deprecation if (!logger) return {}; // eslint-disable-next-line deprecation/deprecation return (0, logger_1.initLoggerSink)(logger); } /** * Appends the default Worker logging interceptors to given interceptor arrays. * * @param logger a {@link Logger} - defaults to the {@link Runtime} singleton logger. * * @deprecated Calling `appendDefaultInterceptors()` is no longer required. To configure a custom logger, set the * {@link Runtime.logger} property instead. */ function appendDefaultInterceptors(interceptors, logger) { if (!logger || logger === runtime_1.Runtime.instance().logger) return interceptors; return { activityInbound: [ // eslint-disable-next-line deprecation/deprecation (ctx) => new activity_log_interceptor_1.ActivityInboundLogInterceptor(ctx, logger), // eslint-disable-next-line deprecation/deprecation ...(interceptors.activityInbound ?? []), ], activity: interceptors.activity, workflowModules: interceptors.workflowModules, }; } function compileWorkerInterceptors({ activity, activityInbound, // eslint-disable-line deprecation/deprecation workflowModules, }) { return { activity: [...activityInbound.map((factory) => (ctx) => ({ inbound: factory(ctx) })), ...activity], workflowModules, }; } function addDefaultWorkerOptions(options, logger, metricMeter) { const { buildId, // eslint-disable-line deprecation/deprecation useVersioning, // eslint-disable-line deprecation/deprecation maxCachedWorkflows, showStackTraceSources, namespace, sinks, nonStickyToStickyPollRatio, interceptors, maxConcurrentActivityTaskExecutions, maxConcurrentLocalActivityExecutions, maxConcurrentWorkflowTaskExecutions, workflowTaskPollerBehavior, activityTaskPollerBehavior, ...rest } = options; const debugMode = options.debugMode || isSet(process.env.TEMPORAL_DEBUG); const reuseV8Context = options.reuseV8Context ?? true; const heapSizeMiB = v8.getHeapStatistics().heap_size_limit / utils_1.MiB; const defaultMaxCachedWorkflows = reuseV8Context ? Math.max(Math.floor((Math.max(heapSizeMiB - 200, 0) * 600) / 1024), 10) : Math.max(Math.floor((Math.max(heapSizeMiB - 400, 0) * 250) / 1024), 10); if (useVersioning && !buildId) { throw new TypeError('Must provide a buildId if useVersioning is true'); } // Difficult to predict appropriate poll numbers for resource based slots let maxWFTPolls = 10; let maxATPolls = 10; let setTuner; if (rest.tuner !== undefined) { if (maxConcurrentActivityTaskExecutions !== undefined) { throw new TypeError('Cannot set both tuner and maxConcurrentActivityTaskExecutions'); } if (maxConcurrentLocalActivityExecutions !== undefined) { throw new TypeError('Cannot set both tuner and maxConcurrentLocalActivityExecutions'); } if (maxConcurrentWorkflowTaskExecutions !== undefined) { throw new TypeError('Cannot set both tuner and maxConcurrentWorkflowTaskExecutions'); } setTuner = rest.tuner; } else { const maxWft = maxConcurrentWorkflowTaskExecutions ?? 40; maxWFTPolls = Math.min(10, maxWft); const maxAT = maxConcurrentActivityTaskExecutions ?? 100; maxATPolls = Math.min(10, maxAT); const maxLAT = maxConcurrentLocalActivityExecutions ?? 100; setTuner = { workflowTaskSlotSupplier: { type: 'fixed-size', numSlots: maxWft, }, activityTaskSlotSupplier: { type: 'fixed-size', numSlots: maxAT, }, localActivityTaskSlotSupplier: { type: 'fixed-size', numSlots: maxLAT, }, }; } const createPollerBehavior = (defaultMax, behavior) => !behavior ? { type: 'simple-maximum', maximum: defaultMax } : behavior.type === 'simple-maximum' ? { type: 'simple-maximum', maximum: behavior.maximum ?? defaultMax } : { type: 'autoscaling', minimum: behavior.minimum ?? 1, initial: behavior.initial ?? 5, maximum: behavior.maximum ?? 100, }; const wftPollerBehavior = createPollerBehavior(maxWFTPolls, workflowTaskPollerBehavior); const atPollerBehavior = createPollerBehavior(maxATPolls, activityTaskPollerBehavior); return { namespace: namespace ?? 'default', identity: `${process.pid}@${os.hostname()}`, useVersioning: useVersioning ?? false, buildId, shutdownGraceTime: 0, enableNonLocalActivities: true, workflowTaskPollerBehavior: wftPollerBehavior, activityTaskPollerBehavior: atPollerBehavior, stickyQueueScheduleToStartTimeout: '10s', maxHeartbeatThrottleInterval: '60s', defaultHeartbeatThrottleInterval: '30s', // 4294967295ms is the maximum allowed time isolateExecutionTimeout: debugMode ? '4294967295ms' : '5s', workflowThreadPoolSize: reuseV8Context ? 1 : 2, maxCachedWorkflows: maxCachedWorkflows ?? defaultMaxCachedWorkflows, showStackTraceSources: showStackTraceSources ?? false, debugMode: debugMode ?? false, interceptors: { activity: interceptors?.activity ?? [], // eslint-disable-next-line deprecation/deprecation activityInbound: interceptors?.activityInbound ?? [], workflowModules: interceptors?.workflowModules ?? [], }, nonStickyToStickyPollRatio: nonStickyToStickyPollRatio ?? 0.2, sinks: { ...(0, logger_1.initLoggerSink)(logger), ...(0, metrics_1.initMetricSink)(metricMeter), // Fix deprecated registration of the 'defaultWorkerLogger' sink ...(sinks?.defaultWorkerLogger ? { __temporal_logger: sinks.defaultWorkerLogger } : {}), ...sinks, }, ...rest, tuner: setTuner, reuseV8Context, }; } function compileWorkerOptions(rawOpts, logger, metricMeter) { const opts = addDefaultWorkerOptions(rawOpts, logger, metricMeter); if (opts.maxCachedWorkflows !== 0 && opts.maxCachedWorkflows < 2) { logger.warn('maxCachedWorkflows must be either 0 (ie. cache is disabled) or greater than 1. Defaulting to 2.'); opts.maxCachedWorkflows = 2; } if (opts.maxConcurrentWorkflowTaskExecutions !== undefined) { if (opts.maxCachedWorkflows > 0 && opts.maxConcurrentWorkflowTaskExecutions > opts.maxCachedWorkflows) { logger.warn("maxConcurrentWorkflowTaskExecutions can't exceed maxCachedWorkflows (unless cache is disabled). Defaulting to maxCachedWorkflows."); opts.maxConcurrentWorkflowTaskExecutions = opts.maxCachedWorkflows; } if (opts.maxCachedWorkflows > 0 && opts.maxConcurrentWorkflowTaskExecutions < 2) { logger.warn("maxConcurrentWorkflowTaskExecutions can't be lower than 2 if maxCachedWorkflows is non-zero. Defaulting to 2."); opts.maxConcurrentWorkflowTaskExecutions = 2; } } const activities = new Map(Object.entries(opts.activities ?? {}).filter(([_, v]) => typeof v === 'function')); const tuner = (0, worker_tuner_1.asNativeTuner)(opts.tuner, logger); return { ...opts, interceptors: compileWorkerInterceptors(opts.interceptors), shutdownGraceTimeMs: (0, time_1.msToNumber)(opts.shutdownGraceTime), shutdownForceTimeMs: (0, time_1.msOptionalToNumber)(opts.shutdownForceTime), stickyQueueScheduleToStartTimeoutMs: (0, time_1.msToNumber)(opts.stickyQueueScheduleToStartTimeout), isolateExecutionTimeoutMs: (0, time_1.msToNumber)(opts.isolateExecutionTimeout), maxHeartbeatThrottleIntervalMs: (0, time_1.msToNumber)(opts.maxHeartbeatThrottleInterval), defaultHeartbeatThrottleIntervalMs: (0, time_1.msToNumber)(opts.defaultHeartbeatThrottleInterval), loadedDataConverter: (0, internal_non_workflow_1.loadDataConverter)(opts.dataConverter), activities, enableNonLocalActivities: opts.enableNonLocalActivities && activities.size > 0, tuner, }; } function toNativeWorkerOptions(opts) { return { identity: opts.identity, buildId: opts.buildId, // eslint-disable-line deprecation/deprecation useVersioning: opts.useVersioning, // eslint-disable-line deprecation/deprecation workerDeploymentOptions: toNativeDeploymentOptions(opts.workerDeploymentOptions), taskQueue: opts.taskQueue, namespace: opts.namespace, tuner: opts.tuner, nonStickyToStickyPollRatio: opts.nonStickyToStickyPollRatio, workflowTaskPollerBehavior: toNativeTaskPollerBehavior(opts.workflowTaskPollerBehavior), activityTaskPollerBehavior: toNativeTaskPollerBehavior(opts.activityTaskPollerBehavior), enableNonLocalActivities: opts.enableNonLocalActivities, stickyQueueScheduleToStartTimeout: (0, time_1.msToNumber)(opts.stickyQueueScheduleToStartTimeout), maxCachedWorkflows: opts.maxCachedWorkflows, maxHeartbeatThrottleInterval: (0, time_1.msToNumber)(opts.maxHeartbeatThrottleInterval), defaultHeartbeatThrottleInterval: (0, time_1.msToNumber)(opts.defaultHeartbeatThrottleInterval), maxTaskQueueActivitiesPerSecond: opts.maxTaskQueueActivitiesPerSecond ?? null, maxActivitiesPerSecond: opts.maxActivitiesPerSecond ?? null, shutdownGraceTime: (0, time_1.msToNumber)(opts.shutdownGraceTime), }; } function toNativeTaskPollerBehavior(behavior) { switch (behavior.type) { case 'simple-maximum': return { type: 'simple-maximum', maximum: behavior.maximum, }; case 'autoscaling': return { type: 'autoscaling', minimum: behavior.minimum, initial: behavior.initial, maximum: behavior.maximum, }; default: throw new Error(`Unknown poller behavior type: ${behavior.type}`); } } function toNativeDeploymentOptions(options) { if (options === undefined) { return null; } let vb; switch (options.defaultVersioningBehavior) { case 'PINNED': vb = { type: 'pinned' }; break; case 'AUTO_UPGRADE': vb = { type: 'auto-upgrade' }; break; default: options.defaultVersioningBehavior; throw new Error(`Unknown versioning behavior: ${options.defaultVersioningBehavior}`); } return { version: options.version, useWorkerVersioning: options.useWorkerVersioning, defaultVersioningBehavior: vb, }; } // Utils /////////////////////////////////////////////////////////////////////////////////////////// function isSet(env) { if (env === undefined) return false; env = env.toLocaleLowerCase(); return env === '1' || env === 't' || env === 'true'; } //# sourceMappingURL=worker-options.js.map