UNPKG

@temporalio/workflow

Version:
92 lines 4.46 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createNexusClient = createNexusClient; const time_1 = require("@temporalio/common/lib/time"); const user_metadata_1 = require("@temporalio/common/lib/user-metadata"); const interceptors_1 = require("@temporalio/common/lib/interceptors"); const cancellation_scope_1 = require("./cancellation-scope"); const global_attributes_1 = require("./global-attributes"); const stack_helpers_1 = require("./stack-helpers"); /** * Create a Nexus client for invoking Nexus Operations from a Workflow. * * @experimental Nexus support in Temporal SDK is experimental. */ function createNexusClient(options) { class NexusClientImpl { async executeOperation(operation, input, operationOptions) { const handle = await this.startOperation(operation, input, operationOptions); return await handle.result(); } async startOperation(operation, input, operationOptions) { const opName = typeof operation === 'string' ? options.service.operations[operation]?.name : operation.name; const activator = (0, global_attributes_1.getActivator)(); const seq = activator.nextSeqs.nexusOperation++; const execute = (0, interceptors_1.composeInterceptors)(activator.interceptors.outbound, 'startNexusOperation', startNexusOperationNextHandler); // TODO: Do we want to make the interceptor async like we do for child workflow? That seems redundant. // REVIEW: I ended up changing this so that the interceptor returns a Promise<StartNexusOperationOutput>, // and the result promise is contained in that Output object. As a consequence of this, // the result promise/completion does not exist until the StartNexusOperation event is received. // That's totally different from what we did in ChildWorkflow, but I think that's cleaner from // interceptors point of view, and will make it easier to extend the API in the future. const { token, result: resultPromise } = await execute({ endpoint: options.endpoint, service: options.service.name, operation: opName, options: operationOptions ?? {}, headers: {}, seq, input, }); return { service: options.service.name, operation: opName, token, async result() { return resultPromise; }, }; } } return new NexusClientImpl(); } function startNexusOperationNextHandler({ input, endpoint, service, options, operation, seq, headers, }) { const activator = (0, global_attributes_1.getActivator)(); return new Promise((resolve, reject) => { const scope = cancellation_scope_1.CancellationScope.current(); if (scope.consideredCancelled) { (0, stack_helpers_1.untrackPromise)(scope.cancelRequested.catch(reject)); return; } if (scope.cancellable) { (0, stack_helpers_1.untrackPromise)(scope.cancelRequested.catch(() => { const completed = !activator.completions.nexusOperationStart.has(seq) && !activator.completions.nexusOperationComplete.has(seq); if (!completed) { activator.pushCommand({ requestCancelNexusOperation: { seq }, }); } // Nothing to cancel otherwise })); } activator.pushCommand({ scheduleNexusOperation: { seq, endpoint, service, operation, nexusHeader: headers, input: activator.payloadConverter.toPayload(input), scheduleToCloseTimeout: (0, time_1.msOptionalToTs)(options?.scheduleToCloseTimeout), // FIXME(nexus-post-initial-release): cancellationType is not supported yet }, userMetadata: (0, user_metadata_1.userMetadataToPayload)(activator.payloadConverter, options?.summary, undefined), }); activator.completions.nexusOperationStart.set(seq, { resolve, reject, }); }); } //# sourceMappingURL=nexus.js.map