@proompteng/temporal-bun-sdk 0.4.0 → 0.5.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/README.md +8 -1
- package/dist/src/bin/temporal-bun.js +1 -1
- package/dist/src/common/payloads/converter.js +1 -1
- package/dist/src/common/payloads/converter.js.map +1 -1
- package/dist/src/common/payloads/json-codec.d.ts.map +1 -1
- package/dist/src/common/payloads/json-codec.js +4 -6
- package/dist/src/common/payloads/json-codec.js.map +1 -1
- package/dist/src/config.d.ts +16 -0
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +49 -0
- package/dist/src/config.js.map +1 -1
- package/dist/src/interceptors/client.d.ts.map +1 -1
- package/dist/src/interceptors/client.js +24 -3
- package/dist/src/interceptors/client.js.map +1 -1
- package/dist/src/interceptors/worker.d.ts.map +1 -1
- package/dist/src/interceptors/worker.js +24 -3
- package/dist/src/interceptors/worker.js.map +1 -1
- package/dist/src/observability/index.d.ts +4 -0
- package/dist/src/observability/index.d.ts.map +1 -1
- package/dist/src/observability/index.js +4 -0
- package/dist/src/observability/index.js.map +1 -1
- package/dist/src/observability/metrics.d.ts.map +1 -1
- package/dist/src/observability/metrics.js +70 -10
- package/dist/src/observability/metrics.js.map +1 -1
- package/dist/src/observability/opentelemetry.d.ts +20 -0
- package/dist/src/observability/opentelemetry.d.ts.map +1 -0
- package/dist/src/observability/opentelemetry.js +334 -0
- package/dist/src/observability/opentelemetry.js.map +1 -0
- package/dist/src/proto/temporal/api/activity/v1/message_pb.js +1 -1
- package/dist/src/proto/temporal/api/batch/v1/message_pb.js +1 -1
- package/dist/src/proto/temporal/api/command/v1/message_pb.js +1 -1
- package/dist/src/proto/temporal/api/common/v1/message_pb.js +1 -1
- package/dist/src/proto/temporal/api/deployment/v1/message_pb.js +1 -1
- package/dist/src/proto/temporal/api/enums/v1/batch_operation_pb.js +1 -1
- package/dist/src/proto/temporal/api/enums/v1/command_type_pb.js +1 -1
- package/dist/src/proto/temporal/api/enums/v1/common_pb.js +1 -1
- package/dist/src/proto/temporal/api/enums/v1/deployment_pb.js +1 -1
- package/dist/src/proto/temporal/api/enums/v1/event_type_pb.js +1 -1
- package/dist/src/proto/temporal/api/enums/v1/failed_cause_pb.js +1 -1
- package/dist/src/proto/temporal/api/enums/v1/namespace_pb.js +1 -1
- package/dist/src/proto/temporal/api/enums/v1/nexus_pb.js +1 -1
- package/dist/src/proto/temporal/api/enums/v1/query_pb.js +1 -1
- package/dist/src/proto/temporal/api/enums/v1/reset_pb.js +1 -1
- package/dist/src/proto/temporal/api/enums/v1/schedule_pb.js +1 -1
- package/dist/src/proto/temporal/api/enums/v1/task_queue_pb.js +1 -1
- package/dist/src/proto/temporal/api/enums/v1/update_pb.js +1 -1
- package/dist/src/proto/temporal/api/enums/v1/workflow_pb.js +1 -1
- package/dist/src/proto/temporal/api/errordetails/v1/message_pb.js +1 -1
- package/dist/src/proto/temporal/api/export/v1/message_pb.js +1 -1
- package/dist/src/proto/temporal/api/failure/v1/message_pb.js +1 -1
- package/dist/src/proto/temporal/api/filter/v1/message_pb.js +1 -1
- package/dist/src/proto/temporal/api/history/v1/message_pb.js +1 -1
- package/dist/src/proto/temporal/api/namespace/v1/message_pb.js +1 -1
- package/dist/src/proto/temporal/api/nexus/v1/message_pb.js +1 -1
- package/dist/src/proto/temporal/api/operatorservice/v1/request_response_pb.js +1 -1
- package/dist/src/proto/temporal/api/operatorservice/v1/service_pb.js +1 -1
- package/dist/src/proto/temporal/api/protocol/v1/message_pb.js +1 -1
- package/dist/src/proto/temporal/api/query/v1/message_pb.js +1 -1
- package/dist/src/proto/temporal/api/replication/v1/message_pb.js +1 -1
- package/dist/src/proto/temporal/api/rules/v1/message_pb.js +1 -1
- package/dist/src/proto/temporal/api/sdk/v1/enhanced_stack_trace_pb.js +1 -1
- package/dist/src/proto/temporal/api/sdk/v1/task_complete_metadata_pb.js +1 -1
- package/dist/src/proto/temporal/api/sdk/v1/user_metadata_pb.js +1 -1
- package/dist/src/proto/temporal/api/sdk/v1/worker_config_pb.js +1 -1
- package/dist/src/proto/temporal/api/sdk/v1/workflow_metadata_pb.js +1 -1
- package/dist/src/proto/temporal/api/taskqueue/v1/message_pb.js +1 -1
- package/dist/src/proto/temporal/api/update/v1/message_pb.js +1 -1
- package/dist/src/proto/temporal/api/version/v1/message_pb.js +1 -1
- package/dist/src/proto/temporal/api/worker/v1/message_pb.js +1 -1
- package/dist/src/proto/temporal/api/workflow/v1/message_pb.js +1 -1
- package/dist/src/proto/temporal/api/workflowservice/v1/request_response_pb.js +1 -1
- package/dist/src/proto/temporal/api/workflowservice/v1/service_pb.js +1 -1
- package/dist/src/worker/runtime.d.ts +1 -0
- package/dist/src/worker/runtime.d.ts.map +1 -1
- package/dist/src/worker/runtime.js +649 -61
- package/dist/src/worker/runtime.js.map +1 -1
- package/dist/src/worker/sticky-cache.d.ts +10 -0
- package/dist/src/worker/sticky-cache.d.ts.map +1 -1
- package/dist/src/worker/sticky-cache.js.map +1 -1
- package/dist/src/workflow/commands.d.ts +2 -1
- package/dist/src/workflow/commands.d.ts.map +1 -1
- package/dist/src/workflow/commands.js +9 -7
- package/dist/src/workflow/commands.js.map +1 -1
- package/dist/src/workflow/context.d.ts.map +1 -1
- package/dist/src/workflow/context.js +28 -9
- package/dist/src/workflow/context.js.map +1 -1
- package/dist/src/workflow/definition.js.map +1 -1
- package/dist/src/workflow/determinism.d.ts +4 -0
- package/dist/src/workflow/determinism.d.ts.map +1 -1
- package/dist/src/workflow/determinism.js +104 -17
- package/dist/src/workflow/determinism.js.map +1 -1
- package/dist/src/workflow/executor.d.ts +3 -0
- package/dist/src/workflow/executor.d.ts.map +1 -1
- package/dist/src/workflow/executor.js +80 -11
- package/dist/src/workflow/executor.js.map +1 -1
- package/dist/src/workflow/inbound.d.ts +1 -0
- package/dist/src/workflow/inbound.d.ts.map +1 -1
- package/dist/src/workflow/inbound.js +1 -0
- package/dist/src/workflow/inbound.js.map +1 -1
- package/dist/src/workflow/index.d.ts +5 -0
- package/dist/src/workflow/index.d.ts.map +1 -1
- package/dist/src/workflow/index.js +3 -0
- package/dist/src/workflow/index.js.map +1 -1
- package/dist/src/workflow/log.d.ts +18 -0
- package/dist/src/workflow/log.d.ts.map +1 -0
- package/dist/src/workflow/log.js +36 -0
- package/dist/src/workflow/log.js.map +1 -0
- package/dist/src/workflow/replay.d.ts +31 -3
- package/dist/src/workflow/replay.d.ts.map +1 -1
- package/dist/src/workflow/replay.js +543 -66
- package/dist/src/workflow/replay.js.map +1 -1
- package/package.json +4 -3
|
@@ -2,7 +2,7 @@ import { pathToFileURL } from 'node:url';
|
|
|
2
2
|
import { create } from '@bufbuild/protobuf';
|
|
3
3
|
import { Code, ConnectError, createClient } from '@connectrpc/connect';
|
|
4
4
|
import { createGrpcTransport } from '@connectrpc/connect-node';
|
|
5
|
-
import { Cause, Effect, Exit, Fiber } from 'effect';
|
|
5
|
+
import { Cause, Duration, Effect, Exit, Fiber, Schedule } from 'effect';
|
|
6
6
|
import { makeActivityLifecycle, } from '../activities/lifecycle';
|
|
7
7
|
import { buildTransportOptions, normalizeTemporalAddress } from '../client';
|
|
8
8
|
import { durationFromMillis, durationToMillis } from '../common/duration';
|
|
@@ -24,10 +24,12 @@ import { HistoryEventFilterType, TimeoutType, VersioningBehavior } from '../prot
|
|
|
24
24
|
import { StickyExecutionAttributesSchema, TaskQueueSchema, } from '../proto/temporal/api/taskqueue/v1/message_pb';
|
|
25
25
|
import { GetWorkflowExecutionHistoryRequestSchema, PollActivityTaskQueueRequestSchema, PollWorkflowTaskQueueRequestSchema, RespondActivityTaskCanceledRequestSchema, RespondActivityTaskCompletedRequestSchema, RespondActivityTaskFailedRequestSchema, RespondQueryTaskCompletedRequestSchema, RespondWorkflowTaskCompletedRequestSchema, RespondWorkflowTaskFailedRequestSchema, } from '../proto/temporal/api/workflowservice/v1/request_response_pb';
|
|
26
26
|
import { WorkflowService } from '../proto/temporal/api/workflowservice/v1/service_pb';
|
|
27
|
+
import { intentsEqual, stableStringify } from '../workflow/determinism';
|
|
27
28
|
import { WorkflowNondeterminismError } from '../workflow/errors';
|
|
28
29
|
import { WorkflowExecutor } from '../workflow/executor';
|
|
30
|
+
import { CHILD_WORKFLOW_COMPLETED_SIGNAL, } from '../workflow/inbound';
|
|
29
31
|
import { WorkflowRegistry } from '../workflow/registry';
|
|
30
|
-
import { DETERMINISM_MARKER_NAME, diffDeterminismState,
|
|
32
|
+
import { DETERMINISM_MARKER_NAME, diffDeterminismState, encodeDeterminismMarkerDetailsWithSize, ingestWorkflowHistory, resolveHistoryLastEventId, } from '../workflow/replay';
|
|
31
33
|
import { runWithActivityContext } from './activity-context';
|
|
32
34
|
import { checkWorkerVersioningCapability, registerWorkerBuildIdCompatibility } from './build-id';
|
|
33
35
|
import { makeWorkerScheduler, } from './concurrency';
|
|
@@ -53,11 +55,19 @@ const mergeUpdateInvocations = (historyInvocations, messageInvocations) => {
|
|
|
53
55
|
const POLL_TIMEOUT_MS = 60_000;
|
|
54
56
|
const RESPOND_TIMEOUT_MS = 15_000;
|
|
55
57
|
const HISTORY_FETCH_TIMEOUT_MS = 60_000;
|
|
58
|
+
const DEFAULT_METRICS_FLUSH_INTERVAL_MS = 10_000;
|
|
56
59
|
const HEARTBEAT_RETRY_INITIAL_DELAY_MS = 250;
|
|
57
60
|
const HEARTBEAT_RETRY_MAX_DELAY_MS = 5_000;
|
|
58
61
|
const HEARTBEAT_RETRY_MAX_ATTEMPTS = 5;
|
|
59
62
|
const HEARTBEAT_RETRY_BACKOFF = 2;
|
|
60
63
|
const HEARTBEAT_RETRY_JITTER = 0.2;
|
|
64
|
+
const parseMetricsFlushInterval = (value) => {
|
|
65
|
+
if (!value) {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
const parsed = Number.parseInt(value, 10);
|
|
69
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
70
|
+
};
|
|
61
71
|
const STICKY_QUEUE_PREFIX = 'sticky';
|
|
62
72
|
const COMPLETION_COMMAND_TYPES = new Set([
|
|
63
73
|
CommandType.COMPLETE_WORKFLOW_EXECUTION,
|
|
@@ -90,7 +100,10 @@ export class WorkerRuntime {
|
|
|
90
100
|
metricsRegistry: options.metrics,
|
|
91
101
|
metricsExporter: options.metricsExporter,
|
|
92
102
|
}));
|
|
93
|
-
const { logger, metricsRegistry, metricsExporter } = observability;
|
|
103
|
+
const { logger, metricsRegistry, metricsExporter, openTelemetry } = observability;
|
|
104
|
+
const metricsFlushIntervalMs = options.metricsFlushIntervalMs ??
|
|
105
|
+
parseMetricsFlushInterval(process.env.TEMPORAL_METRICS_FLUSH_INTERVAL_MS) ??
|
|
106
|
+
DEFAULT_METRICS_FLUSH_INTERVAL_MS;
|
|
94
107
|
const dataConverter = options.dataConverter ??
|
|
95
108
|
createDefaultDataConverter({
|
|
96
109
|
payloadCodecs: buildCodecsFromConfig(config.payloadCodecs),
|
|
@@ -102,6 +115,7 @@ export class WorkerRuntime {
|
|
|
102
115
|
const executor = new WorkflowExecutor({
|
|
103
116
|
registry,
|
|
104
117
|
dataConverter,
|
|
118
|
+
logger,
|
|
105
119
|
});
|
|
106
120
|
const runtimeMetrics = await WorkerRuntime.#initMetrics(metricsRegistry);
|
|
107
121
|
let workflowService;
|
|
@@ -162,6 +176,11 @@ export class WorkerRuntime {
|
|
|
162
176
|
const stickySchedulingEnabled = options.stickyScheduling ??
|
|
163
177
|
(config.stickySchedulingEnabled &&
|
|
164
178
|
(hasStickyCacheInstance ? config.workerStickyCacheSize > 0 : stickyCacheSize > 0));
|
|
179
|
+
const determinismMarkerMode = config.determinismMarkerMode;
|
|
180
|
+
const determinismMarkerIntervalTasks = config.determinismMarkerIntervalTasks;
|
|
181
|
+
const determinismMarkerFullSnapshotIntervalTasks = config.determinismMarkerFullSnapshotIntervalTasks;
|
|
182
|
+
const determinismMarkerSkipUnchanged = config.determinismMarkerSkipUnchanged;
|
|
183
|
+
const determinismMarkerMaxDetailBytes = config.determinismMarkerMaxDetailBytes;
|
|
165
184
|
const deploymentName = options.deployment?.name ?? config.workerDeploymentName ?? WorkerRuntime.#defaultDeploymentName(taskQueue);
|
|
166
185
|
const buildId = options.deployment?.buildId ?? config.workerBuildId ?? identity;
|
|
167
186
|
const workerVersioningMode = options.deployment?.versioningMode ?? WorkerVersioningMode.UNVERSIONED;
|
|
@@ -173,6 +192,7 @@ export class WorkerRuntime {
|
|
|
173
192
|
buildId,
|
|
174
193
|
workerVersioningMode,
|
|
175
194
|
});
|
|
195
|
+
const rpcDeploymentOptions = workerVersioningMode === WorkerVersioningMode.VERSIONED ? deploymentOptions : undefined;
|
|
176
196
|
if (workerVersioningMode === WorkerVersioningMode.VERSIONED) {
|
|
177
197
|
const capability = await checkWorkerVersioningCapability(workflowService, namespace, taskQueue);
|
|
178
198
|
if (capability.supported) {
|
|
@@ -226,11 +246,17 @@ export class WorkerRuntime {
|
|
|
226
246
|
workflowConcurrency,
|
|
227
247
|
activityConcurrency,
|
|
228
248
|
stickySchedulingEnabled,
|
|
249
|
+
determinismMarkerMode,
|
|
250
|
+
determinismMarkerIntervalTasks,
|
|
251
|
+
determinismMarkerFullSnapshotIntervalTasks,
|
|
252
|
+
determinismMarkerSkipUnchanged,
|
|
253
|
+
determinismMarkerMaxDetailBytes,
|
|
229
254
|
deploymentName,
|
|
230
255
|
buildId,
|
|
231
256
|
logLevel: config.logLevel,
|
|
232
257
|
logFormat: config.logFormat,
|
|
233
258
|
metricsExporter: config.metricsExporter.type,
|
|
259
|
+
metricsFlushIntervalMs,
|
|
234
260
|
}));
|
|
235
261
|
return new WorkerRuntime({
|
|
236
262
|
config,
|
|
@@ -242,7 +268,9 @@ export class WorkerRuntime {
|
|
|
242
268
|
logger,
|
|
243
269
|
metricsRegistry,
|
|
244
270
|
metricsExporter,
|
|
271
|
+
metricsFlushIntervalMs,
|
|
245
272
|
metrics: runtimeMetrics,
|
|
273
|
+
openTelemetry,
|
|
246
274
|
namespace,
|
|
247
275
|
taskQueue,
|
|
248
276
|
identity,
|
|
@@ -252,8 +280,14 @@ export class WorkerRuntime {
|
|
|
252
280
|
stickyQueue,
|
|
253
281
|
stickyScheduleToStartTimeoutMs,
|
|
254
282
|
deploymentOptions,
|
|
283
|
+
rpcDeploymentOptions,
|
|
255
284
|
versioningBehavior,
|
|
256
285
|
stickySchedulingEnabled,
|
|
286
|
+
determinismMarkerMode,
|
|
287
|
+
determinismMarkerIntervalTasks,
|
|
288
|
+
determinismMarkerFullSnapshotIntervalTasks,
|
|
289
|
+
determinismMarkerSkipUnchanged,
|
|
290
|
+
determinismMarkerMaxDetailBytes,
|
|
257
291
|
workflowPollerCount,
|
|
258
292
|
interceptors: workerInterceptors,
|
|
259
293
|
});
|
|
@@ -268,6 +302,9 @@ export class WorkerRuntime {
|
|
|
268
302
|
#metricsRegistry;
|
|
269
303
|
#metrics;
|
|
270
304
|
#metricsExporter;
|
|
305
|
+
#metricsFlushIntervalMs;
|
|
306
|
+
#metricsFlushInFlight = false;
|
|
307
|
+
#openTelemetry;
|
|
271
308
|
#namespace;
|
|
272
309
|
#taskQueue;
|
|
273
310
|
#identity;
|
|
@@ -277,8 +314,14 @@ export class WorkerRuntime {
|
|
|
277
314
|
#stickyCache;
|
|
278
315
|
#stickyQueue;
|
|
279
316
|
#stickySchedulingEnabled;
|
|
317
|
+
#determinismMarkerMode;
|
|
318
|
+
#determinismMarkerIntervalTasks;
|
|
319
|
+
#determinismMarkerFullSnapshotIntervalTasks;
|
|
320
|
+
#determinismMarkerSkipUnchanged;
|
|
321
|
+
#determinismMarkerMaxDetailBytes;
|
|
280
322
|
#stickyAttributes;
|
|
281
323
|
#deploymentOptions;
|
|
324
|
+
#rpcDeploymentOptions;
|
|
282
325
|
#versioningBehavior;
|
|
283
326
|
#workflowPollerCount;
|
|
284
327
|
#running = false;
|
|
@@ -296,6 +339,8 @@ export class WorkerRuntime {
|
|
|
296
339
|
this.#metricsRegistry = params.metricsRegistry;
|
|
297
340
|
this.#metrics = params.metrics;
|
|
298
341
|
this.#metricsExporter = params.metricsExporter;
|
|
342
|
+
this.#metricsFlushIntervalMs = Math.max(0, params.metricsFlushIntervalMs);
|
|
343
|
+
this.#openTelemetry = params.openTelemetry;
|
|
299
344
|
this.#namespace = params.namespace;
|
|
300
345
|
this.#taskQueue = params.taskQueue;
|
|
301
346
|
this.#identity = params.identity;
|
|
@@ -305,7 +350,13 @@ export class WorkerRuntime {
|
|
|
305
350
|
this.#stickyCache = params.stickyCache;
|
|
306
351
|
this.#stickyQueue = params.stickyQueue;
|
|
307
352
|
this.#stickySchedulingEnabled = params.stickySchedulingEnabled;
|
|
353
|
+
this.#determinismMarkerMode = params.determinismMarkerMode;
|
|
354
|
+
this.#determinismMarkerIntervalTasks = Math.max(1, params.determinismMarkerIntervalTasks);
|
|
355
|
+
this.#determinismMarkerFullSnapshotIntervalTasks = Math.max(1, params.determinismMarkerFullSnapshotIntervalTasks);
|
|
356
|
+
this.#determinismMarkerSkipUnchanged = params.determinismMarkerSkipUnchanged;
|
|
357
|
+
this.#determinismMarkerMaxDetailBytes = Math.max(0, params.determinismMarkerMaxDetailBytes);
|
|
308
358
|
this.#deploymentOptions = params.deploymentOptions;
|
|
359
|
+
this.#rpcDeploymentOptions = params.rpcDeploymentOptions;
|
|
309
360
|
this.#versioningBehavior = params.versioningBehavior;
|
|
310
361
|
this.#workflowPollerCount = params.workflowPollerCount;
|
|
311
362
|
this.#stickyAttributes = create(StickyExecutionAttributesSchema, {
|
|
@@ -406,6 +457,7 @@ export class WorkerRuntime {
|
|
|
406
457
|
if (!runtimeFiber) {
|
|
407
458
|
await this.#stopScheduler();
|
|
408
459
|
await this.#flushMetrics();
|
|
460
|
+
await this.#shutdownOpenTelemetry();
|
|
409
461
|
this.#running = false;
|
|
410
462
|
this.#log('info', 'temporal worker shutdown complete', this.#runtimeLogFields({ drained: false }));
|
|
411
463
|
return;
|
|
@@ -421,6 +473,7 @@ export class WorkerRuntime {
|
|
|
421
473
|
this.#runFiber = null;
|
|
422
474
|
this.#running = false;
|
|
423
475
|
}
|
|
476
|
+
await this.#shutdownOpenTelemetry();
|
|
424
477
|
this.#log('info', 'temporal worker shutdown complete', this.#runtimeLogFields({ drained: true }));
|
|
425
478
|
}
|
|
426
479
|
#buildRuntimeEffect() {
|
|
@@ -437,6 +490,10 @@ export class WorkerRuntime {
|
|
|
437
490
|
workflowPollers: runtime.#workflowPollerCount,
|
|
438
491
|
stickySchedulingEnabled: runtime.#stickySchedulingEnabled,
|
|
439
492
|
}));
|
|
493
|
+
if (runtime.#metricsFlushIntervalMs > 0) {
|
|
494
|
+
const flushLoop = Effect.repeat(Effect.promise(() => runtime.#flushMetrics()), Schedule.spaced(Duration.millis(runtime.#metricsFlushIntervalMs)));
|
|
495
|
+
yield* Effect.forkScoped(flushLoop);
|
|
496
|
+
}
|
|
440
497
|
if (pollerLoops.length > 0) {
|
|
441
498
|
yield* Effect.forEach(pollerLoops, (loop) => Effect.forkScoped(loop), { concurrency: 'unbounded' });
|
|
442
499
|
}
|
|
@@ -444,9 +501,16 @@ export class WorkerRuntime {
|
|
|
444
501
|
})).pipe(Effect.ensuring(Effect.promise(async () => {
|
|
445
502
|
await runtime.#stopScheduler();
|
|
446
503
|
await runtime.#flushMetrics();
|
|
504
|
+
await runtime.#shutdownOpenTelemetry();
|
|
447
505
|
runtime.#log('info', 'temporal worker runtime stopped', runtime.#runtimeLogFields());
|
|
448
506
|
})));
|
|
449
507
|
}
|
|
508
|
+
async #shutdownOpenTelemetry() {
|
|
509
|
+
if (!this.#openTelemetry) {
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
await this.#openTelemetry.shutdown();
|
|
513
|
+
}
|
|
450
514
|
async #awaitRuntimeFiber(fiber) {
|
|
451
515
|
const exit = await Effect.runPromiseExit(Fiber.join(fiber));
|
|
452
516
|
if (Exit.isFailure(exit)) {
|
|
@@ -482,7 +546,7 @@ export class WorkerRuntime {
|
|
|
482
546
|
namespace: this.#namespace,
|
|
483
547
|
taskQueue: create(TaskQueueSchema, { name: queueName }),
|
|
484
548
|
identity: this.#identity,
|
|
485
|
-
deploymentOptions: this.#
|
|
549
|
+
deploymentOptions: this.#rpcDeploymentOptions,
|
|
486
550
|
});
|
|
487
551
|
const pollOnce = this.#withRpcAbort(async (signal) => {
|
|
488
552
|
const start = Date.now();
|
|
@@ -516,7 +580,7 @@ export class WorkerRuntime {
|
|
|
516
580
|
namespace: this.#namespace,
|
|
517
581
|
taskQueue: create(TaskQueueSchema, { name: this.#taskQueue }),
|
|
518
582
|
identity: this.#identity,
|
|
519
|
-
deploymentOptions: this.#
|
|
583
|
+
deploymentOptions: this.#rpcDeploymentOptions,
|
|
520
584
|
});
|
|
521
585
|
const pollOnce = this.#withRpcAbort(async (signal) => {
|
|
522
586
|
const start = Date.now();
|
|
@@ -638,9 +702,20 @@ export class WorkerRuntime {
|
|
|
638
702
|
if (isLegacyQueryTask) {
|
|
639
703
|
this.#incrementCounter(this.#metrics.queryTaskStarted);
|
|
640
704
|
}
|
|
641
|
-
const
|
|
705
|
+
const queryCount = response.queries && typeof response.queries === 'object' && !Array.isArray(response.queries)
|
|
706
|
+
? Object.keys(response.queries).length
|
|
707
|
+
: Array.isArray(response.queries)
|
|
708
|
+
? response.queries.length
|
|
709
|
+
: 0;
|
|
710
|
+
const hasHistoryEvents = (response.history?.events?.length ?? 0) > 0;
|
|
711
|
+
const hasMoreHistory = (response.nextPageToken?.length ?? 0) > 0;
|
|
712
|
+
const isLegacyQueryOnly = isLegacyQueryTask && !hasHistoryEvents && !hasMoreHistory;
|
|
713
|
+
const hasQueryPayloads = Boolean(response.query) || queryCount > 0;
|
|
714
|
+
const historyEvents = await this.#collectWorkflowHistory(execution, response, {
|
|
715
|
+
forceFullHistory: (hasQueryPayloads && !isLegacyQueryOnly) || nondeterminismRetry > 0,
|
|
716
|
+
skipFetchOnMissingStart: isLegacyQueryOnly,
|
|
717
|
+
});
|
|
642
718
|
const workflowType = this.#resolveWorkflowType(response, historyEvents);
|
|
643
|
-
const args = await this.#decodeWorkflowArgs(historyEvents);
|
|
644
719
|
const workflowInfo = this.#buildWorkflowInfo(workflowType, execution);
|
|
645
720
|
const collectedUpdates = await collectWorkflowUpdates({
|
|
646
721
|
messages: response.messages ?? [],
|
|
@@ -677,6 +752,26 @@ export class WorkerRuntime {
|
|
|
677
752
|
});
|
|
678
753
|
const stickyKey = this.#buildStickyKey(execution.workflowId, execution.runId);
|
|
679
754
|
const stickyEntry = stickyKey ? await this.#getStickyEntry(stickyKey) : undefined;
|
|
755
|
+
const decodedArgs = await this.#decodeWorkflowArgs(historyEvents);
|
|
756
|
+
let args = decodedArgs.args;
|
|
757
|
+
let argsSource = decodedArgs.hasStartEvent ? 'history' : 'unknown';
|
|
758
|
+
if (argsSource === 'unknown' && stickyEntry?.workflowArguments !== undefined) {
|
|
759
|
+
args = stickyEntry.workflowArguments;
|
|
760
|
+
argsSource = 'sticky';
|
|
761
|
+
}
|
|
762
|
+
if (argsSource === 'unknown' && !isLegacyQueryOnly) {
|
|
763
|
+
const fetchedArgs = await this.#fetchWorkflowStartArguments(execution);
|
|
764
|
+
if (fetchedArgs !== undefined) {
|
|
765
|
+
args = fetchedArgs;
|
|
766
|
+
argsSource = 'fetch';
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
if (argsSource !== 'history') {
|
|
770
|
+
this.#log('debug', 'workflow arguments resolved from fallback source', {
|
|
771
|
+
...baseLogFields,
|
|
772
|
+
argsSource,
|
|
773
|
+
});
|
|
774
|
+
}
|
|
680
775
|
const historyReplay = await this.#ingestDeterminismState(workflowInfo, historyEvents, {
|
|
681
776
|
queryRequests,
|
|
682
777
|
});
|
|
@@ -729,6 +824,19 @@ export class WorkerRuntime {
|
|
|
729
824
|
try {
|
|
730
825
|
const { results: activityResults, scheduledEventIds: activityScheduleEventIds } = await this.#extractActivityResolutions(historyEvents);
|
|
731
826
|
const timerResults = await this.#extractTimerResolutions(historyEvents);
|
|
827
|
+
const mergedActivityResults = new Map(stickyEntry?.activityResults ?? []);
|
|
828
|
+
for (const [activityId, resolution] of activityResults.entries()) {
|
|
829
|
+
mergedActivityResults.set(activityId, resolution);
|
|
830
|
+
}
|
|
831
|
+
const mergedScheduleEventIds = new Map(stickyEntry?.activityScheduleEventIds ?? []);
|
|
832
|
+
for (const [activityId, scheduleId] of activityScheduleEventIds.entries()) {
|
|
833
|
+
mergedScheduleEventIds.set(activityId, scheduleId);
|
|
834
|
+
}
|
|
835
|
+
const mergedTimerResults = new Set(stickyEntry?.timerResults ?? []);
|
|
836
|
+
for (const timerId of timerResults) {
|
|
837
|
+
mergedTimerResults.add(timerId);
|
|
838
|
+
}
|
|
839
|
+
const pendingChildWorkflows = await this.#extractPendingChildWorkflows(historyEvents);
|
|
732
840
|
const replayUpdates = historyReplay?.updates ?? [];
|
|
733
841
|
const mergedUpdates = mergeUpdateInvocations(replayUpdates, collectedUpdates.invocations);
|
|
734
842
|
const output = await this.#executor.execute({
|
|
@@ -739,10 +847,11 @@ export class WorkerRuntime {
|
|
|
739
847
|
taskQueue: this.#taskQueue,
|
|
740
848
|
arguments: args,
|
|
741
849
|
determinismState: previousState,
|
|
742
|
-
activityResults,
|
|
743
|
-
activityScheduleEventIds,
|
|
850
|
+
activityResults: mergedActivityResults,
|
|
851
|
+
activityScheduleEventIds: mergedScheduleEventIds,
|
|
852
|
+
pendingChildWorkflows,
|
|
744
853
|
signalDeliveries,
|
|
745
|
-
timerResults,
|
|
854
|
+
timerResults: mergedTimerResults,
|
|
746
855
|
queryRequests,
|
|
747
856
|
updates: mergedUpdates,
|
|
748
857
|
mode: isLegacyQueryTask ? 'query' : 'workflow',
|
|
@@ -788,8 +897,18 @@ export class WorkerRuntime {
|
|
|
788
897
|
return;
|
|
789
898
|
}
|
|
790
899
|
const cacheBaselineEventId = this.#resolveCurrentStartedEventId(response) ?? historyReplay?.lastEventId ?? null;
|
|
791
|
-
const shouldRecordMarker = output.completion === 'pending';
|
|
792
900
|
let commandsForResponse = output.commands;
|
|
901
|
+
const workflowTaskCount = output.completion === 'pending'
|
|
902
|
+
? (stickyEntry?.workflowTaskCount ?? 0) + 1
|
|
903
|
+
: (stickyEntry?.workflowTaskCount ?? 0);
|
|
904
|
+
let markerHash = stickyEntry?.lastDeterminismMarkerHash;
|
|
905
|
+
let lastMarkerTask = stickyEntry?.lastDeterminismMarkerTask;
|
|
906
|
+
let lastFullSnapshotTask = stickyEntry?.lastDeterminismFullSnapshotTask;
|
|
907
|
+
let lastMarkerState = stickyEntry?.lastDeterminismMarkerState;
|
|
908
|
+
let markerType = output.completion === 'pending' ? this.#resolveDeterminismMarkerType(workflowTaskCount, stickyEntry) : null;
|
|
909
|
+
let determinismDelta;
|
|
910
|
+
let markerLastEventId = null;
|
|
911
|
+
const markerBaseState = historyReplay?.markerState ?? lastMarkerState;
|
|
793
912
|
const dispatchesForNewMessages = (output.updateDispatches ?? []).filter((dispatch) => {
|
|
794
913
|
if (dispatch.type === 'acceptance' || dispatch.type === 'rejection') {
|
|
795
914
|
return collectedUpdates.requestsByUpdateId.has(dispatch.updateId);
|
|
@@ -804,41 +923,153 @@ export class WorkerRuntime {
|
|
|
804
923
|
defaultIdentity: this.#identity,
|
|
805
924
|
log: (level, message, fields) => this.#log(level, message, fields),
|
|
806
925
|
});
|
|
807
|
-
if (
|
|
808
|
-
if (
|
|
809
|
-
|
|
810
|
-
this.#log('debug', 'sticky cache snapshot persisted', {
|
|
926
|
+
if (markerType === 'delta') {
|
|
927
|
+
if (!markerBaseState) {
|
|
928
|
+
this.#log('warn', 'determinism delta base unavailable; falling back to full snapshot', {
|
|
811
929
|
...baseLogFields,
|
|
812
|
-
cacheBaselineEventId,
|
|
813
930
|
});
|
|
931
|
+
markerType = 'full';
|
|
814
932
|
}
|
|
815
933
|
else {
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
934
|
+
determinismDelta = this.#buildDeterminismDelta(markerBaseState, output.determinismState);
|
|
935
|
+
}
|
|
936
|
+
if (!determinismDelta) {
|
|
937
|
+
markerType = 'full';
|
|
938
|
+
}
|
|
939
|
+
else if (this.#determinismMarkerSkipUnchanged && this.#isDeterminismDeltaEmpty(determinismDelta)) {
|
|
940
|
+
markerType = null;
|
|
819
941
|
}
|
|
820
942
|
}
|
|
821
|
-
if (
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
const
|
|
832
|
-
|
|
943
|
+
if (markerType) {
|
|
944
|
+
markerLastEventId =
|
|
945
|
+
historyReplay?.lastEventId ??
|
|
946
|
+
this.#resolveWorkflowHistoryLastEventId(response) ??
|
|
947
|
+
stickyEntry?.lastEventId ??
|
|
948
|
+
null;
|
|
949
|
+
let resolvedMarkerType = markerType;
|
|
950
|
+
let markerDetails = null;
|
|
951
|
+
let markerSizeBytes = 0;
|
|
952
|
+
const limitBytes = this.#determinismMarkerMaxDetailBytes;
|
|
953
|
+
const markerHashCandidate = this.#hashDeterminismMarker(this.#buildDeterminismMarkerSignature(output.determinismState));
|
|
954
|
+
if (this.#determinismMarkerSkipUnchanged && markerHashCandidate === stickyEntry?.lastDeterminismMarkerHash) {
|
|
955
|
+
resolvedMarkerType = null;
|
|
956
|
+
}
|
|
957
|
+
if (resolvedMarkerType) {
|
|
958
|
+
const buildMarkerDetails = async (targetType) => Effect.runPromise(encodeDeterminismMarkerDetailsWithSize(this.#dataConverter, {
|
|
959
|
+
info: workflowInfo,
|
|
960
|
+
determinismState: output.determinismState,
|
|
961
|
+
determinismDelta: targetType === 'delta' ? determinismDelta : undefined,
|
|
962
|
+
markerType: targetType,
|
|
963
|
+
lastEventId: markerLastEventId,
|
|
964
|
+
}));
|
|
965
|
+
if (resolvedMarkerType === 'full') {
|
|
966
|
+
const fullResult = await buildMarkerDetails('full');
|
|
967
|
+
if (fullResult.sizeBytes > limitBytes && determinismDelta) {
|
|
968
|
+
this.#log('debug', 'determinism full marker payload exceeds size limit; falling back to delta', {
|
|
969
|
+
...baseLogFields,
|
|
970
|
+
sizeBytes: fullResult.sizeBytes,
|
|
971
|
+
limitBytes,
|
|
972
|
+
});
|
|
973
|
+
const deltaResult = await buildMarkerDetails('delta');
|
|
974
|
+
if (deltaResult.sizeBytes <= limitBytes) {
|
|
975
|
+
resolvedMarkerType = 'delta';
|
|
976
|
+
markerDetails = deltaResult.details;
|
|
977
|
+
markerSizeBytes = deltaResult.sizeBytes;
|
|
978
|
+
}
|
|
979
|
+
else {
|
|
980
|
+
this.#log('warn', 'determinism marker payload exceeds size limit', {
|
|
981
|
+
...baseLogFields,
|
|
982
|
+
markerType: 'delta',
|
|
983
|
+
sizeBytes: deltaResult.sizeBytes,
|
|
984
|
+
limitBytes,
|
|
985
|
+
});
|
|
986
|
+
resolvedMarkerType = null;
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
else if (fullResult.sizeBytes <= limitBytes) {
|
|
990
|
+
markerDetails = fullResult.details;
|
|
991
|
+
markerSizeBytes = fullResult.sizeBytes;
|
|
992
|
+
}
|
|
993
|
+
else {
|
|
994
|
+
this.#log('warn', 'determinism marker payload exceeds size limit', {
|
|
995
|
+
...baseLogFields,
|
|
996
|
+
markerType: 'full',
|
|
997
|
+
sizeBytes: fullResult.sizeBytes,
|
|
998
|
+
limitBytes,
|
|
999
|
+
});
|
|
1000
|
+
resolvedMarkerType = null;
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
else if (resolvedMarkerType === 'delta') {
|
|
1004
|
+
const deltaResult = await buildMarkerDetails('delta');
|
|
1005
|
+
if (deltaResult.sizeBytes <= limitBytes) {
|
|
1006
|
+
markerDetails = deltaResult.details;
|
|
1007
|
+
markerSizeBytes = deltaResult.sizeBytes;
|
|
1008
|
+
}
|
|
1009
|
+
else {
|
|
1010
|
+
this.#log('warn', 'determinism marker payload exceeds size limit', {
|
|
1011
|
+
...baseLogFields,
|
|
1012
|
+
markerType: 'delta',
|
|
1013
|
+
sizeBytes: deltaResult.sizeBytes,
|
|
1014
|
+
limitBytes,
|
|
1015
|
+
});
|
|
1016
|
+
resolvedMarkerType = null;
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
if (resolvedMarkerType) {
|
|
1021
|
+
markerHash = markerHashCandidate;
|
|
1022
|
+
lastMarkerTask = workflowTaskCount;
|
|
1023
|
+
if (resolvedMarkerType === 'full') {
|
|
1024
|
+
lastFullSnapshotTask = workflowTaskCount;
|
|
1025
|
+
}
|
|
1026
|
+
lastMarkerState = output.determinismState;
|
|
1027
|
+
if (markerDetails) {
|
|
1028
|
+
this.#log('debug', 'determinism marker recorded', {
|
|
1029
|
+
...baseLogFields,
|
|
1030
|
+
markerType: resolvedMarkerType,
|
|
1031
|
+
sizeBytes: markerSizeBytes,
|
|
1032
|
+
});
|
|
1033
|
+
const markerCommand = this.#buildDeterminismMarkerCommand(markerDetails);
|
|
1034
|
+
commandsForResponse = this.#injectDeterminismMarker(commandsForResponse, markerCommand);
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
let pendingStickyUpdate = null;
|
|
1039
|
+
let shouldClearSticky = false;
|
|
1040
|
+
if (stickyKey) {
|
|
1041
|
+
if (output.completion === 'pending') {
|
|
1042
|
+
const resolvedWorkflowArgs = argsSource === 'unknown' ? stickyEntry?.workflowArguments : args;
|
|
1043
|
+
pendingStickyUpdate = {
|
|
1044
|
+
determinismState: output.determinismState,
|
|
1045
|
+
cacheBaselineEventId,
|
|
1046
|
+
workflowType,
|
|
1047
|
+
metadata: {
|
|
1048
|
+
workflowTaskCount,
|
|
1049
|
+
lastDeterminismMarkerHash: markerHash,
|
|
1050
|
+
lastDeterminismMarkerTask: lastMarkerTask,
|
|
1051
|
+
lastDeterminismFullSnapshotTask: lastFullSnapshotTask,
|
|
1052
|
+
...(lastMarkerState ? { lastDeterminismMarkerState: lastMarkerState } : {}),
|
|
1053
|
+
...(resolvedWorkflowArgs !== undefined ? { workflowArguments: resolvedWorkflowArgs } : {}),
|
|
1054
|
+
activityResults: mergedActivityResults,
|
|
1055
|
+
activityScheduleEventIds: mergedScheduleEventIds,
|
|
1056
|
+
timerResults: mergedTimerResults,
|
|
1057
|
+
},
|
|
1058
|
+
};
|
|
1059
|
+
}
|
|
1060
|
+
else {
|
|
1061
|
+
shouldClearSticky = true;
|
|
1062
|
+
}
|
|
833
1063
|
}
|
|
834
1064
|
const shouldRespondWorkflowTask = hasMultiQueries || !hasLegacyQueries;
|
|
1065
|
+
let workflowTaskCommitted = false;
|
|
835
1066
|
if (shouldRespondWorkflowTask) {
|
|
836
1067
|
const completion = create(RespondWorkflowTaskCompletedRequestSchema, {
|
|
837
1068
|
taskToken: response.taskToken,
|
|
838
1069
|
commands: commandsForResponse,
|
|
839
1070
|
identity: this.#identity,
|
|
840
1071
|
namespace: this.#namespace,
|
|
841
|
-
deploymentOptions: this.#
|
|
1072
|
+
deploymentOptions: this.#rpcDeploymentOptions,
|
|
842
1073
|
queryResults: multiQueryResults,
|
|
843
1074
|
...(this.#stickySchedulingEnabled && !hasLegacyQueries ? { stickyAttributes: this.#stickyAttributes } : {}),
|
|
844
1075
|
...(this.#versioningBehavior !== null ? { versioningBehavior: this.#versioningBehavior } : {}),
|
|
@@ -846,6 +1077,7 @@ export class WorkerRuntime {
|
|
|
846
1077
|
});
|
|
847
1078
|
try {
|
|
848
1079
|
await this.#workflowService.respondWorkflowTaskCompleted(completion, { timeoutMs: RESPOND_TIMEOUT_MS });
|
|
1080
|
+
workflowTaskCommitted = true;
|
|
849
1081
|
}
|
|
850
1082
|
catch (rpcError) {
|
|
851
1083
|
this.#log('error', 'debug: respondWorkflowTaskCompleted failed', {
|
|
@@ -854,6 +1086,10 @@ export class WorkerRuntime {
|
|
|
854
1086
|
});
|
|
855
1087
|
if (this.#isTaskNotFoundError(rpcError)) {
|
|
856
1088
|
this.#logWorkflowTaskNotFound('respondWorkflowTaskCompleted', execution);
|
|
1089
|
+
if (stickyKey) {
|
|
1090
|
+
await this.#removeStickyEntry(stickyKey);
|
|
1091
|
+
await this.#removeStickyEntriesForWorkflow(stickyKey.workflowId);
|
|
1092
|
+
}
|
|
857
1093
|
return;
|
|
858
1094
|
}
|
|
859
1095
|
throw rpcError;
|
|
@@ -862,6 +1098,20 @@ export class WorkerRuntime {
|
|
|
862
1098
|
if (legacyQueryResult) {
|
|
863
1099
|
await this.#respondLegacyQueryTask(response, legacyQueryResult);
|
|
864
1100
|
}
|
|
1101
|
+
if (stickyKey && workflowTaskCommitted) {
|
|
1102
|
+
if (pendingStickyUpdate) {
|
|
1103
|
+
await this.#upsertStickyEntry(stickyKey, pendingStickyUpdate.determinismState, pendingStickyUpdate.cacheBaselineEventId, pendingStickyUpdate.workflowType, pendingStickyUpdate.metadata);
|
|
1104
|
+
this.#log('debug', 'sticky cache snapshot persisted', {
|
|
1105
|
+
...baseLogFields,
|
|
1106
|
+
cacheBaselineEventId: pendingStickyUpdate.cacheBaselineEventId,
|
|
1107
|
+
});
|
|
1108
|
+
}
|
|
1109
|
+
else if (shouldClearSticky) {
|
|
1110
|
+
await this.#removeStickyEntry(stickyKey);
|
|
1111
|
+
await this.#removeStickyEntriesForWorkflow(stickyKey.workflowId);
|
|
1112
|
+
this.#log('debug', 'sticky cache entry cleared (workflow completed)', baseLogFields);
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
865
1115
|
}
|
|
866
1116
|
catch (error) {
|
|
867
1117
|
let stickyEntryCleared = false;
|
|
@@ -950,20 +1200,93 @@ export class WorkerRuntime {
|
|
|
950
1200
|
queries: options?.queryRequests,
|
|
951
1201
|
}));
|
|
952
1202
|
}
|
|
953
|
-
async #collectWorkflowHistory(execution,
|
|
1203
|
+
async #collectWorkflowHistory(execution, response, options) {
|
|
954
1204
|
const events = [];
|
|
955
|
-
|
|
956
|
-
|
|
1205
|
+
const initialEvents = response.history?.events ?? [];
|
|
1206
|
+
if (initialEvents.length > 0) {
|
|
1207
|
+
events.push(...initialEvents);
|
|
1208
|
+
}
|
|
1209
|
+
let token = response.nextPageToken && response.nextPageToken.length > 0 ? response.nextPageToken : undefined;
|
|
1210
|
+
while (token && token.length > 0) {
|
|
957
1211
|
const page = await this.#fetchWorkflowHistoryPage(execution, token);
|
|
958
1212
|
if (page.events.length > 0) {
|
|
959
1213
|
events.push(...page.events);
|
|
960
1214
|
}
|
|
961
|
-
|
|
1215
|
+
token = page.nextPageToken && page.nextPageToken.length > 0 ? page.nextPageToken : undefined;
|
|
1216
|
+
}
|
|
1217
|
+
let sorted = this.#sortHistoryEvents(events);
|
|
1218
|
+
const shouldFetchFullHistory = options?.forceFullHistory || (!options?.skipFetchOnMissingStart && !this.#findWorkflowStartedEvent(sorted));
|
|
1219
|
+
if (shouldFetchFullHistory) {
|
|
1220
|
+
const fullHistory = await this.#fetchWorkflowHistoryFromStart(execution);
|
|
1221
|
+
if (fullHistory.length > 0) {
|
|
1222
|
+
sorted = this.#sortHistoryEvents([...fullHistory, ...sorted]);
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
const bounded = this.#limitHistoryToStartedEvent(sorted, response.startedEventId);
|
|
1226
|
+
return this.#dedupeHistoryEvents(bounded);
|
|
1227
|
+
}
|
|
1228
|
+
#sortHistoryEvents(events) {
|
|
1229
|
+
return events.slice().sort((left, right) => {
|
|
1230
|
+
const leftId = this.#resolveEventIdForSort(left.eventId);
|
|
1231
|
+
const rightId = this.#resolveEventIdForSort(right.eventId);
|
|
1232
|
+
if (leftId === rightId) {
|
|
1233
|
+
return 0;
|
|
1234
|
+
}
|
|
1235
|
+
return leftId < rightId ? -1 : 1;
|
|
1236
|
+
});
|
|
1237
|
+
}
|
|
1238
|
+
#dedupeHistoryEvents(events) {
|
|
1239
|
+
if (events.length <= 1) {
|
|
1240
|
+
return events;
|
|
1241
|
+
}
|
|
1242
|
+
const deduped = [];
|
|
1243
|
+
let lastId = null;
|
|
1244
|
+
for (const event of events) {
|
|
1245
|
+
const currentId = this.#resolveEventIdForSort(event.eventId);
|
|
1246
|
+
if (currentId !== 0n) {
|
|
1247
|
+
if (lastId !== null && currentId === lastId) {
|
|
1248
|
+
continue;
|
|
1249
|
+
}
|
|
1250
|
+
lastId = currentId;
|
|
1251
|
+
}
|
|
1252
|
+
deduped.push(event);
|
|
1253
|
+
}
|
|
1254
|
+
return deduped;
|
|
1255
|
+
}
|
|
1256
|
+
#limitHistoryToStartedEvent(events, startedEventId) {
|
|
1257
|
+
const limit = this.#resolveEventIdForSort(startedEventId);
|
|
1258
|
+
if (limit <= 0n) {
|
|
1259
|
+
return events;
|
|
1260
|
+
}
|
|
1261
|
+
const bounded = [];
|
|
1262
|
+
for (const event of events) {
|
|
1263
|
+
const currentId = this.#resolveEventIdForSort(event.eventId);
|
|
1264
|
+
if (currentId !== 0n && currentId > limit) {
|
|
962
1265
|
break;
|
|
963
1266
|
}
|
|
964
|
-
|
|
1267
|
+
bounded.push(event);
|
|
965
1268
|
}
|
|
966
|
-
return
|
|
1269
|
+
return bounded;
|
|
1270
|
+
}
|
|
1271
|
+
#resolveEventIdForSort(value) {
|
|
1272
|
+
if (value === undefined || value === null) {
|
|
1273
|
+
return 0n;
|
|
1274
|
+
}
|
|
1275
|
+
if (typeof value === 'bigint') {
|
|
1276
|
+
return value;
|
|
1277
|
+
}
|
|
1278
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
1279
|
+
return BigInt(value);
|
|
1280
|
+
}
|
|
1281
|
+
if (typeof value === 'string' && value.length > 0) {
|
|
1282
|
+
try {
|
|
1283
|
+
return BigInt(value);
|
|
1284
|
+
}
|
|
1285
|
+
catch {
|
|
1286
|
+
return 0n;
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
return 0n;
|
|
967
1290
|
}
|
|
968
1291
|
async #extractActivityResolutions(events) {
|
|
969
1292
|
const resolutions = new Map();
|
|
@@ -1077,28 +1400,86 @@ export class WorkerRuntime {
|
|
|
1077
1400
|
}
|
|
1078
1401
|
return value.toString();
|
|
1079
1402
|
};
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
if (event.attributes?.case !== 'workflowExecutionSignaledEventAttributes') {
|
|
1085
|
-
continue;
|
|
1403
|
+
const recordChildCompletion = (event, status, attrs) => {
|
|
1404
|
+
const workflowId = attrs.workflowExecution?.workflowId;
|
|
1405
|
+
if (!workflowId) {
|
|
1406
|
+
return;
|
|
1086
1407
|
}
|
|
1087
|
-
const attrs = event.attributes.value;
|
|
1088
|
-
const args = await decodePayloadsToValues(this.#dataConverter, attrs.input?.payloads ?? []);
|
|
1089
|
-
const workflowTaskCompletedEventId = 'workflowTaskCompletedEventId' in attrs
|
|
1090
|
-
? normalizeEventId(attrs
|
|
1091
|
-
.workflowTaskCompletedEventId)
|
|
1092
|
-
: null;
|
|
1093
1408
|
deliveries.push({
|
|
1094
|
-
name:
|
|
1095
|
-
args
|
|
1409
|
+
name: CHILD_WORKFLOW_COMPLETED_SIGNAL,
|
|
1410
|
+
args: [
|
|
1411
|
+
{
|
|
1412
|
+
workflowId,
|
|
1413
|
+
...(attrs.workflowExecution?.runId ? { runId: attrs.workflowExecution.runId } : {}),
|
|
1414
|
+
status,
|
|
1415
|
+
},
|
|
1416
|
+
],
|
|
1096
1417
|
metadata: {
|
|
1097
1418
|
eventId: normalizeEventId(event.eventId),
|
|
1098
|
-
workflowTaskCompletedEventId,
|
|
1099
|
-
identity: attrs.identity ?? null,
|
|
1100
1419
|
},
|
|
1101
1420
|
});
|
|
1421
|
+
};
|
|
1422
|
+
for (const event of events) {
|
|
1423
|
+
switch (event.eventType) {
|
|
1424
|
+
case EventType.WORKFLOW_EXECUTION_SIGNALED: {
|
|
1425
|
+
if (event.attributes?.case !== 'workflowExecutionSignaledEventAttributes') {
|
|
1426
|
+
break;
|
|
1427
|
+
}
|
|
1428
|
+
const attrs = event.attributes.value;
|
|
1429
|
+
const args = await decodePayloadsToValues(this.#dataConverter, attrs.input?.payloads ?? []);
|
|
1430
|
+
const workflowTaskCompletedEventId = 'workflowTaskCompletedEventId' in attrs
|
|
1431
|
+
? normalizeEventId(attrs
|
|
1432
|
+
.workflowTaskCompletedEventId)
|
|
1433
|
+
: null;
|
|
1434
|
+
deliveries.push({
|
|
1435
|
+
name: attrs.signalName ?? 'unknown',
|
|
1436
|
+
args,
|
|
1437
|
+
metadata: {
|
|
1438
|
+
eventId: normalizeEventId(event.eventId),
|
|
1439
|
+
workflowTaskCompletedEventId,
|
|
1440
|
+
identity: attrs.identity ?? null,
|
|
1441
|
+
},
|
|
1442
|
+
});
|
|
1443
|
+
break;
|
|
1444
|
+
}
|
|
1445
|
+
case EventType.CHILD_WORKFLOW_EXECUTION_COMPLETED: {
|
|
1446
|
+
if (event.attributes?.case !== 'childWorkflowExecutionCompletedEventAttributes') {
|
|
1447
|
+
break;
|
|
1448
|
+
}
|
|
1449
|
+
recordChildCompletion(event, 'completed', event.attributes.value);
|
|
1450
|
+
break;
|
|
1451
|
+
}
|
|
1452
|
+
case EventType.CHILD_WORKFLOW_EXECUTION_FAILED: {
|
|
1453
|
+
if (event.attributes?.case !== 'childWorkflowExecutionFailedEventAttributes') {
|
|
1454
|
+
break;
|
|
1455
|
+
}
|
|
1456
|
+
recordChildCompletion(event, 'failed', event.attributes.value);
|
|
1457
|
+
break;
|
|
1458
|
+
}
|
|
1459
|
+
case EventType.CHILD_WORKFLOW_EXECUTION_CANCELED: {
|
|
1460
|
+
if (event.attributes?.case !== 'childWorkflowExecutionCanceledEventAttributes') {
|
|
1461
|
+
break;
|
|
1462
|
+
}
|
|
1463
|
+
recordChildCompletion(event, 'canceled', event.attributes.value);
|
|
1464
|
+
break;
|
|
1465
|
+
}
|
|
1466
|
+
case EventType.CHILD_WORKFLOW_EXECUTION_TERMINATED: {
|
|
1467
|
+
if (event.attributes?.case !== 'childWorkflowExecutionTerminatedEventAttributes') {
|
|
1468
|
+
break;
|
|
1469
|
+
}
|
|
1470
|
+
recordChildCompletion(event, 'terminated', event.attributes.value);
|
|
1471
|
+
break;
|
|
1472
|
+
}
|
|
1473
|
+
case EventType.CHILD_WORKFLOW_EXECUTION_TIMED_OUT: {
|
|
1474
|
+
if (event.attributes?.case !== 'childWorkflowExecutionTimedOutEventAttributes') {
|
|
1475
|
+
break;
|
|
1476
|
+
}
|
|
1477
|
+
recordChildCompletion(event, 'timed_out', event.attributes.value);
|
|
1478
|
+
break;
|
|
1479
|
+
}
|
|
1480
|
+
default:
|
|
1481
|
+
break;
|
|
1482
|
+
}
|
|
1102
1483
|
}
|
|
1103
1484
|
return deliveries;
|
|
1104
1485
|
}
|
|
@@ -1118,6 +1499,56 @@ export class WorkerRuntime {
|
|
|
1118
1499
|
}
|
|
1119
1500
|
return fired;
|
|
1120
1501
|
}
|
|
1502
|
+
async #extractPendingChildWorkflows(events) {
|
|
1503
|
+
const pending = new Map();
|
|
1504
|
+
const normalizeEventId = (value) => {
|
|
1505
|
+
if (value === undefined || value === null) {
|
|
1506
|
+
return null;
|
|
1507
|
+
}
|
|
1508
|
+
if (typeof value === 'string') {
|
|
1509
|
+
return value;
|
|
1510
|
+
}
|
|
1511
|
+
return value.toString();
|
|
1512
|
+
};
|
|
1513
|
+
for (const event of events) {
|
|
1514
|
+
switch (event.eventType) {
|
|
1515
|
+
case EventType.START_CHILD_WORKFLOW_EXECUTION_INITIATED: {
|
|
1516
|
+
if (event.attributes?.case !== 'startChildWorkflowExecutionInitiatedEventAttributes') {
|
|
1517
|
+
break;
|
|
1518
|
+
}
|
|
1519
|
+
const attrs = event.attributes.value;
|
|
1520
|
+
const initiatedId = normalizeEventId(event.eventId);
|
|
1521
|
+
if (initiatedId && attrs.workflowId) {
|
|
1522
|
+
pending.set(initiatedId, attrs.workflowId);
|
|
1523
|
+
}
|
|
1524
|
+
break;
|
|
1525
|
+
}
|
|
1526
|
+
case EventType.CHILD_WORKFLOW_EXECUTION_STARTED: {
|
|
1527
|
+
if (event.attributes?.case !== 'childWorkflowExecutionStartedEventAttributes') {
|
|
1528
|
+
break;
|
|
1529
|
+
}
|
|
1530
|
+
const initiatedId = normalizeEventId(event.attributes.value.initiatedEventId);
|
|
1531
|
+
if (initiatedId) {
|
|
1532
|
+
pending.delete(initiatedId);
|
|
1533
|
+
}
|
|
1534
|
+
break;
|
|
1535
|
+
}
|
|
1536
|
+
case EventType.START_CHILD_WORKFLOW_EXECUTION_FAILED: {
|
|
1537
|
+
if (event.attributes?.case !== 'startChildWorkflowExecutionFailedEventAttributes') {
|
|
1538
|
+
break;
|
|
1539
|
+
}
|
|
1540
|
+
const initiatedId = normalizeEventId(event.attributes.value.initiatedEventId);
|
|
1541
|
+
if (initiatedId) {
|
|
1542
|
+
pending.delete(initiatedId);
|
|
1543
|
+
}
|
|
1544
|
+
break;
|
|
1545
|
+
}
|
|
1546
|
+
default:
|
|
1547
|
+
break;
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
return new Set(pending.values());
|
|
1551
|
+
}
|
|
1121
1552
|
async #extractWorkflowQueryRequests(response) {
|
|
1122
1553
|
const requests = [];
|
|
1123
1554
|
const map = response.queries ?? {};
|
|
@@ -1235,6 +1666,18 @@ export class WorkerRuntime {
|
|
|
1235
1666
|
nextPageToken: historyResponse.nextPageToken ?? new Uint8Array(),
|
|
1236
1667
|
};
|
|
1237
1668
|
}
|
|
1669
|
+
async #fetchWorkflowHistoryFromStart(execution) {
|
|
1670
|
+
const events = [];
|
|
1671
|
+
let token;
|
|
1672
|
+
do {
|
|
1673
|
+
const page = await this.#fetchWorkflowHistoryPage(execution, token);
|
|
1674
|
+
if (page.events.length > 0) {
|
|
1675
|
+
events.push(...page.events);
|
|
1676
|
+
}
|
|
1677
|
+
token = page.nextPageToken && page.nextPageToken.length > 0 ? page.nextPageToken : undefined;
|
|
1678
|
+
} while (token && token.length > 0);
|
|
1679
|
+
return events;
|
|
1680
|
+
}
|
|
1238
1681
|
#buildWorkflowInfo(workflowType, execution) {
|
|
1239
1682
|
return {
|
|
1240
1683
|
namespace: this.#namespace,
|
|
@@ -1247,19 +1690,145 @@ export class WorkerRuntime {
|
|
|
1247
1690
|
async #getStickyEntry(key) {
|
|
1248
1691
|
return await Effect.runPromise(this.#stickyCache.get(key));
|
|
1249
1692
|
}
|
|
1250
|
-
async #upsertStickyEntry(key, state, lastEventId, workflowType) {
|
|
1693
|
+
async #upsertStickyEntry(key, state, lastEventId, workflowType, metadata) {
|
|
1251
1694
|
const entry = {
|
|
1252
1695
|
key,
|
|
1253
1696
|
determinismState: state,
|
|
1254
1697
|
lastEventId,
|
|
1255
1698
|
lastAccessed: Date.now(),
|
|
1256
1699
|
workflowType,
|
|
1700
|
+
...metadata,
|
|
1257
1701
|
};
|
|
1258
1702
|
await Effect.runPromise(this.#stickyCache.upsert(entry));
|
|
1259
1703
|
}
|
|
1260
1704
|
#resolveWorkflowHistoryLastEventId(response) {
|
|
1261
1705
|
return resolveHistoryLastEventId(response.history?.events ?? []);
|
|
1262
1706
|
}
|
|
1707
|
+
#resolveDeterminismMarkerType(taskIndex, stickyEntry) {
|
|
1708
|
+
if (this.#determinismMarkerMode === 'never') {
|
|
1709
|
+
return null;
|
|
1710
|
+
}
|
|
1711
|
+
if (this.#determinismMarkerMode === 'always') {
|
|
1712
|
+
return 'full';
|
|
1713
|
+
}
|
|
1714
|
+
const interval = Math.max(1, this.#determinismMarkerIntervalTasks);
|
|
1715
|
+
const shouldRecord = taskIndex === 1 || interval === 1 || taskIndex % interval === 0;
|
|
1716
|
+
if (!shouldRecord) {
|
|
1717
|
+
return null;
|
|
1718
|
+
}
|
|
1719
|
+
if (this.#determinismMarkerMode === 'delta') {
|
|
1720
|
+
const lastFullSnapshot = stickyEntry?.lastDeterminismFullSnapshotTask ?? 0;
|
|
1721
|
+
const fullInterval = Math.max(1, this.#determinismMarkerFullSnapshotIntervalTasks);
|
|
1722
|
+
const fullDue = taskIndex === 1 || fullInterval === 1 || taskIndex - lastFullSnapshot >= fullInterval;
|
|
1723
|
+
return fullDue ? 'full' : 'delta';
|
|
1724
|
+
}
|
|
1725
|
+
return 'full';
|
|
1726
|
+
}
|
|
1727
|
+
#buildDeterminismDelta(previous, current) {
|
|
1728
|
+
if (!previous) {
|
|
1729
|
+
return undefined;
|
|
1730
|
+
}
|
|
1731
|
+
const normalizeOptional = (value) => (value === undefined ? null : value);
|
|
1732
|
+
const optionalEquals = (left, right) => normalizeOptional(left) === normalizeOptional(right);
|
|
1733
|
+
const signalsEqual = (left, right) => left.signalName === right.signalName &&
|
|
1734
|
+
left.handlerName === right.handlerName &&
|
|
1735
|
+
left.payloadHash === right.payloadHash &&
|
|
1736
|
+
optionalEquals(left.eventId, right.eventId) &&
|
|
1737
|
+
optionalEquals(left.workflowTaskCompletedEventId, right.workflowTaskCompletedEventId) &&
|
|
1738
|
+
optionalEquals(left.identity, right.identity);
|
|
1739
|
+
const queriesEqual = (left, right) => left.queryName === right.queryName &&
|
|
1740
|
+
left.handlerName === right.handlerName &&
|
|
1741
|
+
left.requestHash === right.requestHash &&
|
|
1742
|
+
optionalEquals(left.identity, right.identity) &&
|
|
1743
|
+
optionalEquals(left.queryId, right.queryId) &&
|
|
1744
|
+
left.resultHash === right.resultHash &&
|
|
1745
|
+
left.failureHash === right.failureHash;
|
|
1746
|
+
const updatesEqual = (left, right) => left.updateId === right.updateId &&
|
|
1747
|
+
left.stage === right.stage &&
|
|
1748
|
+
left.handlerName === right.handlerName &&
|
|
1749
|
+
left.identity === right.identity &&
|
|
1750
|
+
left.sequencingEventId === right.sequencingEventId &&
|
|
1751
|
+
left.messageId === right.messageId &&
|
|
1752
|
+
left.acceptedEventId === right.acceptedEventId &&
|
|
1753
|
+
left.outcome === right.outcome &&
|
|
1754
|
+
left.failureMessage === right.failureMessage &&
|
|
1755
|
+
left.historyEventId === right.historyEventId;
|
|
1756
|
+
const sliceAppend = (currentList, previousList, equals = Object.is) => {
|
|
1757
|
+
if (currentList.length < previousList.length) {
|
|
1758
|
+
return undefined;
|
|
1759
|
+
}
|
|
1760
|
+
for (let index = 0; index < previousList.length; index += 1) {
|
|
1761
|
+
if (!equals(previousList[index], currentList[index])) {
|
|
1762
|
+
return undefined;
|
|
1763
|
+
}
|
|
1764
|
+
}
|
|
1765
|
+
return currentList.slice(previousList.length);
|
|
1766
|
+
};
|
|
1767
|
+
const commandHistory = sliceAppend(current.commandHistory, previous.commandHistory, (left, right) => intentsEqual(left?.intent, right?.intent));
|
|
1768
|
+
const randomValues = sliceAppend(current.randomValues, previous.randomValues);
|
|
1769
|
+
const timeValues = sliceAppend(current.timeValues, previous.timeValues);
|
|
1770
|
+
const signals = sliceAppend(current.signals, previous.signals, signalsEqual);
|
|
1771
|
+
const queries = sliceAppend(current.queries, previous.queries, queriesEqual);
|
|
1772
|
+
if (!commandHistory || !randomValues || !timeValues || !signals || !queries) {
|
|
1773
|
+
return undefined;
|
|
1774
|
+
}
|
|
1775
|
+
const updatesPrev = previous.updates ?? [];
|
|
1776
|
+
const updatesNext = current.updates ?? [];
|
|
1777
|
+
if (updatesNext.length < updatesPrev.length) {
|
|
1778
|
+
return undefined;
|
|
1779
|
+
}
|
|
1780
|
+
const updates = sliceAppend(updatesNext, updatesPrev, updatesEqual);
|
|
1781
|
+
if (!updates) {
|
|
1782
|
+
return undefined;
|
|
1783
|
+
}
|
|
1784
|
+
const logCount = current.logCount !== undefined && current.logCount !== previous.logCount ? current.logCount : undefined;
|
|
1785
|
+
const failureMetadata = current.failureMetadata && previous.failureMetadata
|
|
1786
|
+
? current.failureMetadata.eventId !== previous.failureMetadata.eventId ||
|
|
1787
|
+
current.failureMetadata.eventType !== previous.failureMetadata.eventType ||
|
|
1788
|
+
current.failureMetadata.failureType !== previous.failureMetadata.failureType ||
|
|
1789
|
+
current.failureMetadata.failureMessage !== previous.failureMetadata.failureMessage ||
|
|
1790
|
+
current.failureMetadata.retryState !== previous.failureMetadata.retryState
|
|
1791
|
+
? current.failureMetadata
|
|
1792
|
+
: undefined
|
|
1793
|
+
: (current.failureMetadata ?? undefined);
|
|
1794
|
+
return {
|
|
1795
|
+
commandHistory,
|
|
1796
|
+
randomValues,
|
|
1797
|
+
timeValues,
|
|
1798
|
+
signals,
|
|
1799
|
+
queries,
|
|
1800
|
+
...(updates.length > 0 ? { updates } : {}),
|
|
1801
|
+
...(logCount !== undefined ? { logCount } : {}),
|
|
1802
|
+
...(failureMetadata ? { failureMetadata } : {}),
|
|
1803
|
+
};
|
|
1804
|
+
}
|
|
1805
|
+
#isDeterminismDeltaEmpty(delta) {
|
|
1806
|
+
const updatesCount = delta.updates ? delta.updates.length : 0;
|
|
1807
|
+
return ((delta.commandHistory?.length ?? 0) === 0 &&
|
|
1808
|
+
(delta.randomValues?.length ?? 0) === 0 &&
|
|
1809
|
+
(delta.timeValues?.length ?? 0) === 0 &&
|
|
1810
|
+
(delta.signals?.length ?? 0) === 0 &&
|
|
1811
|
+
(delta.queries?.length ?? 0) === 0 &&
|
|
1812
|
+
updatesCount === 0 &&
|
|
1813
|
+
delta.logCount === undefined &&
|
|
1814
|
+
delta.failureMetadata === undefined);
|
|
1815
|
+
}
|
|
1816
|
+
#buildDeterminismMarkerSignature(state) {
|
|
1817
|
+
const failureMetadataHash = state.failureMetadata ? stableStringify(state.failureMetadata) : undefined;
|
|
1818
|
+
return {
|
|
1819
|
+
commandHistoryLength: state.commandHistory.length,
|
|
1820
|
+
randomValuesLength: state.randomValues.length,
|
|
1821
|
+
timeValuesLength: state.timeValues.length,
|
|
1822
|
+
signalsLength: state.signals.length,
|
|
1823
|
+
queriesLength: state.queries.length,
|
|
1824
|
+
updatesLength: state.updates?.length ?? 0,
|
|
1825
|
+
logCount: state.logCount ?? 0,
|
|
1826
|
+
...(failureMetadataHash ? { failureMetadataHash } : {}),
|
|
1827
|
+
};
|
|
1828
|
+
}
|
|
1829
|
+
#hashDeterminismMarker(signature) {
|
|
1830
|
+
return stableStringify(signature);
|
|
1831
|
+
}
|
|
1263
1832
|
#isTaskNotFoundError(error) {
|
|
1264
1833
|
return error instanceof ConnectError && error.code === Code.NotFound;
|
|
1265
1834
|
}
|
|
@@ -1506,7 +2075,7 @@ export class WorkerRuntime {
|
|
|
1506
2075
|
failure: encoded,
|
|
1507
2076
|
identity: this.#identity,
|
|
1508
2077
|
namespace: this.#namespace,
|
|
1509
|
-
deploymentOptions: this.#
|
|
2078
|
+
deploymentOptions: this.#rpcDeploymentOptions,
|
|
1510
2079
|
});
|
|
1511
2080
|
try {
|
|
1512
2081
|
await this.#workflowService.respondWorkflowTaskFailed(failed, { timeoutMs: RESPOND_TIMEOUT_MS });
|
|
@@ -1606,7 +2175,7 @@ export class WorkerRuntime {
|
|
|
1606
2175
|
identity: this.#identity,
|
|
1607
2176
|
namespace: this.#namespace,
|
|
1608
2177
|
result: payloads && payloads.length > 0 ? create(PayloadsSchema, { payloads }) : undefined,
|
|
1609
|
-
deploymentOptions: this.#
|
|
2178
|
+
deploymentOptions: this.#rpcDeploymentOptions,
|
|
1610
2179
|
});
|
|
1611
2180
|
await this.#workflowService.respondActivityTaskCompleted(completion, { timeoutMs: RESPOND_TIMEOUT_MS });
|
|
1612
2181
|
break;
|
|
@@ -1662,7 +2231,7 @@ export class WorkerRuntime {
|
|
|
1662
2231
|
namespace: this.#namespace,
|
|
1663
2232
|
failure: encoded,
|
|
1664
2233
|
lastHeartbeatDetails,
|
|
1665
|
-
deploymentOptions: this.#
|
|
2234
|
+
deploymentOptions: this.#rpcDeploymentOptions,
|
|
1666
2235
|
});
|
|
1667
2236
|
await this.#workflowService.respondActivityTaskFailed(request, { timeoutMs: RESPOND_TIMEOUT_MS });
|
|
1668
2237
|
this.#incrementCounter(this.#metrics.activityFailures);
|
|
@@ -1674,7 +2243,7 @@ export class WorkerRuntime {
|
|
|
1674
2243
|
identity: this.#identity,
|
|
1675
2244
|
namespace: this.#namespace,
|
|
1676
2245
|
details,
|
|
1677
|
-
deploymentOptions: this.#
|
|
2246
|
+
deploymentOptions: this.#rpcDeploymentOptions,
|
|
1678
2247
|
});
|
|
1679
2248
|
await this.#workflowService.respondActivityTaskCanceled(request, { timeoutMs: RESPOND_TIMEOUT_MS });
|
|
1680
2249
|
}
|
|
@@ -1789,6 +2358,10 @@ export class WorkerRuntime {
|
|
|
1789
2358
|
return scheduleDeadline ?? startDeadline ?? undefined;
|
|
1790
2359
|
}
|
|
1791
2360
|
async #flushMetrics() {
|
|
2361
|
+
if (this.#metricsFlushInFlight) {
|
|
2362
|
+
return;
|
|
2363
|
+
}
|
|
2364
|
+
this.#metricsFlushInFlight = true;
|
|
1792
2365
|
try {
|
|
1793
2366
|
await Effect.runPromise(this.#metricsExporter.flush());
|
|
1794
2367
|
}
|
|
@@ -1797,21 +2370,36 @@ export class WorkerRuntime {
|
|
|
1797
2370
|
error: error instanceof Error ? error.message : String(error),
|
|
1798
2371
|
});
|
|
1799
2372
|
}
|
|
2373
|
+
finally {
|
|
2374
|
+
this.#metricsFlushInFlight = false;
|
|
2375
|
+
}
|
|
1800
2376
|
}
|
|
1801
2377
|
async #decodeWorkflowArgs(events) {
|
|
1802
2378
|
const startEvent = this.#findWorkflowStartedEvent(events);
|
|
1803
2379
|
if (!startEvent) {
|
|
1804
|
-
return [];
|
|
2380
|
+
return { args: [], hasStartEvent: false };
|
|
1805
2381
|
}
|
|
2382
|
+
const args = (await this.#decodeWorkflowArgsFromStartEvent(startEvent)) ?? [];
|
|
2383
|
+
return { args, hasStartEvent: true };
|
|
2384
|
+
}
|
|
2385
|
+
async #decodeWorkflowArgsFromStartEvent(startEvent) {
|
|
1806
2386
|
const attributes = startEvent.attributes?.case === 'workflowExecutionStartedEventAttributes'
|
|
1807
2387
|
? startEvent.attributes.value
|
|
1808
2388
|
: undefined;
|
|
1809
2389
|
if (!attributes) {
|
|
1810
|
-
return
|
|
2390
|
+
return undefined;
|
|
1811
2391
|
}
|
|
1812
2392
|
const inputPayloads = attributes.input?.payloads ?? [];
|
|
1813
2393
|
return await decodePayloadsToValues(this.#dataConverter, inputPayloads);
|
|
1814
2394
|
}
|
|
2395
|
+
async #fetchWorkflowStartArguments(execution) {
|
|
2396
|
+
const page = await this.#fetchWorkflowHistoryPage(execution);
|
|
2397
|
+
const startEvent = this.#findWorkflowStartedEvent(page.events);
|
|
2398
|
+
if (!startEvent) {
|
|
2399
|
+
return undefined;
|
|
2400
|
+
}
|
|
2401
|
+
return await this.#decodeWorkflowArgsFromStartEvent(startEvent);
|
|
2402
|
+
}
|
|
1815
2403
|
#resolveWorkflowType(response, events) {
|
|
1816
2404
|
if (response.workflowType?.name) {
|
|
1817
2405
|
return response.workflowType.name;
|