Skip to content

Commit 18d4c15

Browse files
authored
chore: Refactor module scoped state variable to use globals (#944)
1 parent eb76568 commit 18d4c15

File tree

10 files changed

+531
-549
lines changed

10 files changed

+531
-549
lines changed

packages/worker/src/workflow/bundler.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -148,18 +148,18 @@ import * as api from '@temporalio/workflow/lib/worker-interface.js';
148148
149149
// Bundle all Workflows and interceptor modules for lazy evaluation
150150
api.overrideGlobals();
151-
api.setImportFuncs({
152-
importWorkflows: () => {
153-
return import(/* webpackMode: "eager" */ ${JSON.stringify(this.workflowsPath)});
154-
},
155-
importInterceptors: () => {
156-
return Promise.all([
157-
${interceptorImports}
158-
]);
159-
}
160-
});
161151
162152
export { api };
153+
154+
export function importWorkflows() {
155+
return import(/* webpackMode: "eager" */ ${JSON.stringify(this.workflowsPath)});
156+
}
157+
158+
export function importInterceptors() {
159+
return Promise.all([
160+
${interceptorImports}
161+
]);
162+
}
163163
`;
164164
try {
165165
vol.mkdirSync(path.dirname(target), { recursive: true });

packages/worker/src/workflow/interface.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { coresdk } from '@temporalio/proto';
22
import { SinkCall } from '@temporalio/workflow';
3-
import { WorkflowCreateOptions } from '@temporalio/workflow/lib/worker-interface';
3+
import { WorkflowCreateOptions } from '@temporalio/workflow/lib/interfaces';
44

55
export { WorkflowCreateOptions };
66

packages/worker/src/workflow/vm.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ function getPromiseStackStore(promise: Promise<any>): internals.PromiseStackStor
4646
// Access the global scope associated with the promise (unique per workflow - vm.context)
4747
// See for reference https://github.com/patriksimek/vm2/issues/32
4848
const ctor = promise.constructor.constructor;
49-
return ctor('return globalThis.__TEMPORAL__?.promiseStackStore')();
49+
return ctor('return globalThis.__TEMPORAL__?.activator?.promiseStackStore')();
5050
}
5151

5252
/**
@@ -72,7 +72,7 @@ export function setUnhandledRejectionHandler(): void {
7272
// Get the runId associated with the vm context.
7373
// See for reference https://github.com/patriksimek/vm2/issues/32
7474
const ctor = promise.constructor.constructor;
75-
const runId = ctor('return globalThis.__TEMPORAL__?.runId')();
75+
const runId = ctor('return globalThis.__TEMPORAL__?.activator?.info?.runId')();
7676
if (runId !== undefined) {
7777
const workflow = VMWorkflowCreator.workflowByRunId.get(runId);
7878
if (workflow !== undefined) {
@@ -127,11 +127,12 @@ export class VMWorkflowCreator implements WorkflowCreator {
127127
{
128128
get(_: any, fn: string) {
129129
return (...args: any[]) => {
130-
context.args = args;
131-
const ret = vm.runInContext(`__TEMPORAL__.api.${fn}(...globalThis.args)`, context, {
130+
context.__TEMPORAL__.args = args;
131+
const ret = vm.runInContext(`__TEMPORAL__.api.${fn}(...__TEMPORAL__.args)`, context, {
132132
timeout: isolateExecutionTimeoutMs,
133133
displayErrors: true,
134134
});
135+
135136
// When running with microtaskMode `afterEvaluate`, promises from context cannot be directly awaited outside of it.
136137
if (
137138
hasSeparateMicrotaskQueue &&
@@ -348,7 +349,7 @@ export class VMWorkflow implements Workflow {
348349

349350
constructor(
350351
public readonly info: WorkflowInfo,
351-
protected context: vm.Context | undefined,
352+
protected context: any | undefined,
352353
readonly workflowModule: WorkflowModule,
353354
public readonly isolateExecutionTimeoutMs: number,
354355
public readonly hasSeparateMicrotaskQueue: boolean,
@@ -407,7 +408,7 @@ export class VMWorkflow implements Workflow {
407408
if (this.unhandledRejection) {
408409
return coresdk.workflow_completion.WorkflowActivationCompletion.encodeDelimited({
409410
runId: activation.runId,
410-
failed: { failure: this.workflowModule.errorToFailure(this.unhandledRejection) },
411+
failed: { failure: this.context.__TEMPORAL__.activator.errorToFailure(this.unhandledRejection) },
411412
}).finish();
412413
}
413414
return coresdk.workflow_completion.WorkflowActivationCompletion.encodeDelimited(completion).finish();

packages/workflow/src/cancellation-scope.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,8 @@ export class CancellationScope {
162162
* Get the current "active" scope
163163
*/
164164
static current(): CancellationScope {
165-
return storage.getStore() ?? ROOT_SCOPE;
165+
// Using globals directly instead of a helper function to avoid circular import
166+
return storage.getStore() ?? (globalThis as any).__TEMPORAL__.activator.rootScope;
166167
}
167168

168169
/** Alias to `new CancellationScope({ cancellable: true }).run(fn)` */
@@ -187,14 +188,15 @@ export class CancellationScope {
187188
export const storage = new AsyncLocalStorage<CancellationScope>();
188189

189190
export class RootCancellationScope extends CancellationScope {
191+
constructor() {
192+
super({ cancellable: true, parent: NO_PARENT });
193+
}
194+
190195
cancel(): void {
191196
this.reject(new CancelledFailure('Workflow cancelled'));
192197
}
193198
}
194199

195-
/** There can only be one of these */
196-
export const ROOT_SCOPE = new RootCancellationScope({ cancellable: true, parent: NO_PARENT });
197-
198200
/** This function is here to avoid a circular dependency between this module and workflow.ts */
199201
let sleep = (_: number | string): Promise<void> => {
200202
throw new IllegalStateError('Workflow has not been properly initialized');

packages/workflow/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export {
8080
} from '@temporalio/common/lib/interfaces';
8181
export * from '@temporalio/common/lib/workflow-handle';
8282
export * from '@temporalio/common/lib/workflow-options';
83-
export { AsyncLocalStorage, CancellationScope, CancellationScopeOptions, ROOT_SCOPE } from './cancellation-scope';
83+
export { AsyncLocalStorage, CancellationScope, CancellationScopeOptions } from './cancellation-scope';
8484
export * from './errors';
8585
export * from './interceptors';
8686
export {

packages/workflow/src/interfaces.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { RawSourceMap } from 'source-map';
12
import { RetryPolicy, TemporalFailure, CommonWorkflowOptions, SearchAttributes } from '@temporalio/common';
23
import { checkExtends } from '@temporalio/common/lib/type-helpers';
34
import type { coresdk } from '@temporalio/proto';
@@ -363,3 +364,15 @@ export interface EnhancedStackTrace {
363364
sources: Record<string, FileSlice[]>;
364365
stacks: StackTrace[];
365366
}
367+
368+
export interface WorkflowCreateOptions {
369+
info: WorkflowInfo;
370+
randomnessSeed: number[];
371+
now: number;
372+
patches: string[];
373+
showStackTraceSources: boolean;
374+
}
375+
376+
export interface WorkflowCreateOptionsWithSourceMap extends WorkflowCreateOptions {
377+
sourceMap: RawSourceMap;
378+
}

0 commit comments

Comments
 (0)