Skip to content

Commit a5eedca

Browse files
authored
chore: Use require instead of import to make worker-interface methods sync (#946)
1 parent 59d5e62 commit a5eedca

File tree

6 files changed

+30
-41
lines changed

6 files changed

+30
-41
lines changed

packages/interceptors-opentelemetry/src/workflow/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,6 @@ export class OpenTelemetryInternalsInterceptor implements WorkflowInternalsInter
130130
if (contextManager !== undefined) {
131131
contextManager.disable();
132132
}
133-
await next(input);
133+
next(input);
134134
}
135135
}

packages/test/src/integration-tests.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1321,12 +1321,13 @@ export function runIntegrationTests(codec?: PayloadCodec): void {
13211321
workflowId,
13221322
});
13231323
await handle.query(workflows.mutateWorkflowStateQuery);
1324+
await handle.terminate();
13241325
// Worker did not crash
13251326
t.pass();
13261327
});
13271328

13281329
/**
1329-
* NOTE: this test uses the `list` API which requires advanced visibility as of server 1.18.
1330+
* NOTE: this test uses the `IN` operator API which requires advanced visibility as of server 1.18.
13301331
* Run with docker-compose
13311332
*/
13321333
test('Download and replay multiple executions with client list method', async (t) => {

packages/worker/src/workflow/bundler.ts

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -125,11 +125,11 @@ export class WorkflowCodeBundler {
125125
if (stat.isFile()) {
126126
// workflowsPath is a file; make the entrypoint a sibling of that file
127127
const { root, dir, name } = path.parse(workflowsPath);
128-
return path.format({ root, dir, base: `${name}-autogenerated-entrypoint.js` });
128+
return path.format({ root, dir, base: `${name}-autogenerated-entrypoint.cjs` });
129129
} else {
130130
// workflowsPath is a directory; make the entrypoint a sibling of that directory
131131
const { root, dir, base } = path.parse(workflowsPath);
132-
return path.format({ root, dir, base: `${base}-autogenerated-entrypoint.js` });
132+
return path.format({ root, dir, base: `${base}-autogenerated-entrypoint.cjs` });
133133
}
134134
}
135135

@@ -140,25 +140,24 @@ export class WorkflowCodeBundler {
140140
*/
141141
protected genEntrypoint(vol: typeof memfs.vol, target: string): void {
142142
const interceptorImports = [...new Set(this.workflowInterceptorModules)]
143-
.map((v) => `import(/* webpackMode: "eager" */ ${JSON.stringify(v)})`)
143+
.map((v) => `require(/* webpackMode: "eager" */ ${JSON.stringify(v)})`)
144144
.join(', \n');
145145

146146
const code = `
147-
import * as api from '@temporalio/workflow/lib/worker-interface.js';
147+
const api = require('@temporalio/workflow/lib/worker-interface.js');
148148
149-
// Bundle all Workflows and interceptor modules for lazy evaluation
150149
api.overrideGlobals();
151150
152-
export { api };
151+
exports.api = api;
153152
154-
export function importWorkflows() {
155-
return import(/* webpackMode: "eager" */ ${JSON.stringify(this.workflowsPath)});
153+
exports.importWorkflows = function importWorkflows() {
154+
return require(/* webpackMode: "eager" */ ${JSON.stringify(this.workflowsPath)});
156155
}
157156
158-
export function importInterceptors() {
159-
return Promise.all([
157+
exports.importInterceptors = function importInterceptors() {
158+
return [
160159
${interceptorImports}
161-
]);
160+
];
162161
}
163162
`;
164163
try {

packages/worker/src/workflow/vm.ts

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -121,34 +121,23 @@ export class VMWorkflowCreator implements WorkflowCreator {
121121
const context = await this.getContext();
122122
const activationContext = { isReplaying: options.info.unsafe.isReplaying };
123123
this.injectConsole(context, options.info, activationContext);
124-
const { hasSeparateMicrotaskQueue, isolateExecutionTimeoutMs } = this;
124+
const { isolateExecutionTimeoutMs } = this;
125125
const workflowModule: WorkflowModule = new Proxy(
126126
{},
127127
{
128128
get(_: any, fn: string) {
129129
return (...args: any[]) => {
130130
context.__TEMPORAL__.args = args;
131-
const ret = vm.runInContext(`__TEMPORAL__.api.${fn}(...__TEMPORAL__.args)`, context, {
131+
return vm.runInContext(`__TEMPORAL__.api.${fn}(...__TEMPORAL__.args)`, context, {
132132
timeout: isolateExecutionTimeoutMs,
133133
displayErrors: true,
134134
});
135-
136-
// When running with microtaskMode `afterEvaluate`, promises from context cannot be directly awaited outside of it.
137-
if (
138-
hasSeparateMicrotaskQueue &&
139-
typeof ret === 'object' &&
140-
ret != null &&
141-
ret.constructor.name === 'Promise'
142-
) {
143-
return new Promise((resolve, reject) => ret.then(resolve, reject));
144-
}
145-
return ret;
146135
};
147136
},
148137
}
149138
) as any;
150139

151-
await workflowModule.initRuntime({ ...options, sourceMap: this.sourceMap });
140+
workflowModule.initRuntime({ ...options, sourceMap: this.sourceMap });
152141

153142
const newVM = new VMWorkflow(
154143
options.info,

packages/workflow/src/interceptors.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ export interface WorkflowInternalsInterceptor {
206206
*
207207
* Implement this method to perform any resource cleanup.
208208
*/
209-
dispose?(input: DisposeInput, next: Next<this, 'dispose'>): Promise<void>;
209+
dispose?(input: DisposeInput, next: Next<this, 'dispose'>): void;
210210
}
211211

212212
/**

packages/workflow/src/worker-interface.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ export function overrideGlobals(): void {
9292
*
9393
* Sets required internal state and instantiates the workflow and interceptors.
9494
*/
95-
export async function initRuntime(options: WorkflowCreateOptionsWithSourceMap): Promise<void> {
95+
export function initRuntime(options: WorkflowCreateOptionsWithSourceMap): void {
9696
const { info } = options;
9797
info.unsafe.now = OriginalDate.now;
9898
const activator = new Activator(options);
@@ -101,18 +101,18 @@ export async function initRuntime(options: WorkflowCreateOptionsWithSourceMap):
101101
// as well as Date and Math.random.
102102
global.__TEMPORAL__.activator = activator;
103103

104-
// TODO(bergundy): check if we can use `require` with the ESM sample and make all of the runtime methods sync.
105-
106-
// @ts-expect-error this is a webpack alias to payloadConverterPath
107-
const customPayloadConverter = (await import('__temporal_custom_payload_converter')).payloadConverter;
104+
// webpack alias to payloadConverterPath
105+
// eslint-disable-next-line @typescript-eslint/no-var-requires
106+
const customPayloadConverter = require('__temporal_custom_payload_converter').payloadConverter;
108107
// The `payloadConverter` export is validated in the Worker
109-
if (customPayloadConverter !== undefined) {
108+
if (customPayloadConverter != null) {
110109
activator.payloadConverter = customPayloadConverter;
111110
}
112-
// @ts-expect-error this is a webpack alias to failureConverterPath
113-
const customFailureConverter = (await import('__temporal_custom_failure_converter')).failureConverter;
111+
// webpack alias to failureConverterPath
112+
// eslint-disable-next-line @typescript-eslint/no-var-requires
113+
const customFailureConverter = require('__temporal_custom_failure_converter').failureConverter;
114114
// The `failureConverter` export is validated in the Worker
115-
if (customFailureConverter !== undefined) {
115+
if (customFailureConverter != null) {
116116
activator.failureConverter = customFailureConverter;
117117
}
118118

@@ -121,7 +121,7 @@ export async function initRuntime(options: WorkflowCreateOptionsWithSourceMap):
121121
throw new IllegalStateError('Workflow bundle did not register import hooks');
122122
}
123123

124-
const interceptors = await importInterceptors();
124+
const interceptors = importInterceptors();
125125
for (const mod of interceptors) {
126126
const factory: WorkflowInterceptorsFactory = mod.interceptors;
127127
if (factory !== undefined) {
@@ -135,7 +135,7 @@ export async function initRuntime(options: WorkflowCreateOptionsWithSourceMap):
135135
}
136136
}
137137

138-
const mod = await importWorkflows();
138+
const mod = importWorkflows();
139139
const workflow = mod[info.workflowType];
140140
if (typeof workflow !== 'function') {
141141
throw new TypeError(`'${info.workflowType}' is not a function`);
@@ -248,9 +248,9 @@ export function showUnblockConditions(job: coresdk.workflow_activation.IWorkflow
248248
return !job.queryWorkflow && !job.notifyHasPatch;
249249
}
250250

251-
export async function dispose(): Promise<void> {
251+
export function dispose(): void {
252252
const dispose = composeInterceptors(getActivator().interceptors.internals, 'dispose', async () => {
253253
storage.disable();
254254
});
255-
await dispose({});
255+
dispose({});
256256
}

0 commit comments

Comments
 (0)