Socket
Socket
Sign inDemoInstall

@temporalio/workflow

Package Overview
Dependencies
Maintainers
4
Versions
79
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@temporalio/workflow - npm Package Compare versions

Comparing version 0.3.2 to 0.4.0

lib/async-local-storage.d.ts

4

lib/cancellation-scope.d.ts

@@ -104,6 +104,2 @@ /** Magic symbol used to create the root scope - intentionally not exported */

export declare const ROOT_SCOPE: CancellationScope;
/** Push a scope onto the scope stack */
export declare function pushScope(scope: CancellationScope): void;
/** Pop the last scope off the scope stack */
export declare function popScope(): void;
/** This function is here to avoid a circular dependency between this module and workflow.ts */

@@ -110,0 +106,0 @@ declare let sleep: (_: number) => Promise<void>;

@@ -17,3 +17,4 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.registerSleepImplementation = exports.popScope = exports.pushScope = exports.ROOT_SCOPE = exports.CancellationScope = void 0;
exports.registerSleepImplementation = exports.ROOT_SCOPE = exports.CancellationScope = void 0;
const async_local_storage_1 = require("./async-local-storage");
const errors_1 = require("./errors");

@@ -92,9 +93,8 @@ /** Magic symbol used to create the root scope - intentionally not exported */

run(fn) {
pushScope(this);
if (this.timeout) {
sleep(this.timeout).then(() => this.cancel());
}
const promise = fn();
popScope();
return promise;
return storage.run(this, async () => {
if (this.timeout) {
sleep(this.timeout).then(() => this.cancel());
}
return await fn();
});
}

@@ -111,7 +111,3 @@ /**

static current() {
const scope = scopeStack[scopeStack.length - 1];
if (scope === undefined) {
throw new errors_1.IllegalStateError('No scopes in stack');
}
return scope;
return storage.getStore() ?? exports.ROOT_SCOPE;
}

@@ -133,16 +129,5 @@ /** Alias to `new CancellationScope({ cancellable: true }).run(fn)` */

_cancelRequested = new WeakMap();
const storage = new async_local_storage_1.AsyncLocalStorage();
/** There can only be one of these */
exports.ROOT_SCOPE = new CancellationScope({ cancellable: true, parent: NO_PARENT });
/** Used by CancellationScope.run and PromiseHooks to track the current scope */
const scopeStack = [exports.ROOT_SCOPE];
/** Push a scope onto the scope stack */
function pushScope(scope) {
scopeStack.push(scope);
}
exports.pushScope = pushScope;
/** Pop the last scope off the scope stack */
function popScope() {
scopeStack.pop();
}
exports.popScope = popScope;
/** This function is here to avoid a circular dependency between this module and workflow.ts */

@@ -149,0 +134,0 @@ let sleep = (_) => {

@@ -55,4 +55,5 @@ /**

export * from './interceptors';
export { AsyncLocalStorage } from './async-local-storage';
export { CancellationScope, CancellationScopeOptions } from './cancellation-scope';
export { Trigger } from './trigger';
export { defaultDataConverter, DataConverter } from './converter/data-converter';

@@ -62,3 +62,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultDataConverter = exports.Trigger = exports.CancellationScope = exports.scheduleActivity = exports.validateActivityOptions = exports.uuid4 = exports.sleep = exports.ContextImpl = exports.Context = exports.IllegalStateError = exports.DeterminismViolationError = exports.CancelledError = exports.ApplyMode = void 0;
exports.defaultDataConverter = exports.Trigger = exports.CancellationScope = exports.AsyncLocalStorage = exports.scheduleActivity = exports.validateActivityOptions = exports.uuid4 = exports.sleep = exports.ContextImpl = exports.Context = exports.IllegalStateError = exports.DeterminismViolationError = exports.CancelledError = exports.ApplyMode = void 0;
require("./global-overrides");

@@ -79,2 +79,4 @@ var interfaces_1 = require("./interfaces");

__exportStar(require("./interceptors"), exports);
var async_local_storage_1 = require("./async-local-storage");
Object.defineProperty(exports, "AsyncLocalStorage", { enumerable: true, get: function () { return async_local_storage_1.AsyncLocalStorage; } });
var cancellation_scope_1 = require("./cancellation-scope");

@@ -81,0 +83,0 @@ Object.defineProperty(exports, "CancellationScope", { enumerable: true, get: function () { return cancellation_scope_1.CancellationScope; } });

@@ -1,5 +0,4 @@

import ivm from 'isolated-vm';
import { coresdk } from '@temporalio/proto';
import { RNG } from './alea';
import { ActivityOptions, ApplyMode, ExternalDependencyFunction, ExternalDependencies, Workflow, WorkflowInfo } from './interfaces';
import { ActivityOptions, ExternalDependencies, Workflow, WorkflowInfo } from './interfaces';
import { WorkflowInterceptors } from './interceptors';

@@ -26,12 +25,2 @@ export declare type ResolveFunction<T = any> = (val: T) => any;

}
declare type ActivationJobResult = {
pendingExternalCalls: ExternalCall[];
processed: boolean;
};
/**
* Run a single activation job.
* @param jobIndex index of job to process in the activation's job array.
* @returns a boolean indicating whether the job was processed or ignored
*/
export declare function activate(encodedActivation: Uint8Array, jobIndex: number): ActivationJobResult;
export interface ExternalCall {

@@ -59,2 +48,9 @@ ifaceName: string;

readonly completions: Map<number, Completion>;
/**
* Overridden on WF initialization
*/
interceptorModules: string[];
/**
* Loaded from `interceptorModules`
*/
interceptors: WorkflowInterceptors;

@@ -101,34 +97,10 @@ /**

getAndResetPendingExternalCalls(): ExternalCall[];
/**
* Used to require user code
*
* Injected on isolate startup
*/
require?: (filename: string) => Record<string, unknown>;
}
export declare const state: State;
declare type ActivationConclusion = {
type: 'pending';
pendingExternalCalls: ExternalCall[];
} | {
type: 'complete';
encoded: Uint8Array;
};
/**
* Conclude a single activation.
* Should be called after processing all activation jobs and queued microtasks.
*
* Activation may be in either `complete` or `pending` state according to pending external dependency calls.
* Activation failures are handled in the main NodeJS isolate.
*/
export declare function concludeActivation(): ActivationConclusion;
export declare function getAndResetPendingExternalCalls(): ExternalCall[];
/**
* Inject an external dependency function into the Workflow via global state.
* The injected function is available via {@link Context.dependencies}.
*/
export declare function inject(ifaceName: string, fnName: string, dependency: ivm.Reference<ExternalDependencyFunction>, applyMode: ApplyMode, transferOptions: ivm.TransferOptionsBidirectional): void;
export interface ExternalDependencyResult {
seq: number;
result: any;
error: any;
}
/**
* Resolve external dependency function calls with given results.
*/
export declare function resolveExternalDependencies(results: ExternalDependencyResult[]): void;
export {};
export declare function consumeCompletion(taskSeq: number): Completion;

@@ -39,9 +39,7 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveExternalDependencies = exports.inject = exports.getAndResetPendingExternalCalls = exports.concludeActivation = exports.state = exports.State = exports.activate = exports.Activator = void 0;
exports.consumeCompletion = exports.state = exports.State = exports.Activator = void 0;
const long_1 = __importDefault(require("long"));
const protobufjs = __importStar(require("protobufjs/minimal"));
const proto_1 = require("@temporalio/proto");
const data_converter_1 = require("./converter/data-converter");
const alea_1 = require("./alea");
const interfaces_1 = require("./interfaces");
const interceptors_1 = require("./interceptors");

@@ -56,6 +54,14 @@ const errors_1 = require("./errors");

startWorkflow(activation) {
const { require: req, info } = exports.state;
if (req === undefined || info === undefined) {
throw new errors_1.IllegalStateError('Workflow has not been initialized');
}
for (const mod of exports.state.interceptorModules) {
const { interceptors } = req(mod);
exports.state.interceptors.inbound.push(...interceptors.inbound);
exports.state.interceptors.outbound.push(...interceptors.outbound);
}
const execute = interceptors_1.composeInterceptors(exports.state.interceptors.inbound, 'execute', async (input) => {
if (exports.state.workflow === undefined) {
throw new errors_1.IllegalStateError('state.workflow is not defined');
}
const mod = req(info.filename);
exports.state.workflow = (mod.workflow ?? mod);
return exports.state.workflow.main(...input.args);

@@ -161,33 +167,2 @@ });

/**
* Run a single activation job.
* @param jobIndex index of job to process in the activation's job array.
* @returns a boolean indicating whether the job was processed or ignored
*/
function activate(encodedActivation, jobIndex) {
const activation = proto_1.coresdk.workflow_activation.WFActivation.decodeDelimited(encodedActivation);
// job's type is IWFActivationJob which doesn't have the `attributes` property.
const job = activation.jobs[jobIndex];
exports.state.now = time_1.tsToMs(activation.timestamp);
if (exports.state.info === undefined) {
throw new errors_1.IllegalStateError('Workflow has not been initialized');
}
exports.state.info.isReplaying = activation.isReplaying ?? false;
if (job.variant === undefined) {
throw new TypeError('Expected job.variant to be defined');
}
const variant = job[job.variant];
if (!variant) {
throw new TypeError(`Expected job.${job.variant} to be set`);
}
// The only job that can be executed on a completed workflow is a query.
// We might get other jobs after completion for instance when a single
// activation contains multiple jobs and the first one completes the workflow.
if (exports.state.completed && job.variant !== 'queryWorkflow') {
return { processed: false, pendingExternalCalls: exports.state.getAndResetPendingExternalCalls() };
}
exports.state.activator[job.variant](variant);
return { processed: true, pendingExternalCalls: exports.state.getAndResetPendingExternalCalls() };
}
exports.activate = activate;
/**
* Keeps all of the Workflow runtime state like pending completions for activities and timers and the scope stack.

@@ -207,2 +182,9 @@ *

this.completions = new Map();
/**
* Overridden on WF initialization
*/
this.interceptorModules = [];
/**
* Loaded from `interceptorModules`
*/
this.interceptors = { inbound: [], outbound: [] };

@@ -296,2 +278,3 @@ /**

}
exports.consumeCompletion = consumeCompletion;
function idToSeq(id) {

@@ -303,68 +286,2 @@ if (!id) {

}
/**
* Conclude a single activation.
* Should be called after processing all activation jobs and queued microtasks.
*
* Activation may be in either `complete` or `pending` state according to pending external dependency calls.
* Activation failures are handled in the main NodeJS isolate.
*/
function concludeActivation() {
const pendingExternalCalls = exports.state.getAndResetPendingExternalCalls();
if (pendingExternalCalls.length > 0) {
return { type: 'pending', pendingExternalCalls };
}
const { commands, info } = exports.state;
const encoded = proto_1.coresdk.workflow_completion.WFActivationCompletion.encodeDelimited({
runId: info?.runId,
successful: { commands },
}).finish();
exports.state.commands = [];
return { type: 'complete', encoded };
}
exports.concludeActivation = concludeActivation;
function getAndResetPendingExternalCalls() {
return exports.state.getAndResetPendingExternalCalls();
}
exports.getAndResetPendingExternalCalls = getAndResetPendingExternalCalls;
/**
* Inject an external dependency function into the Workflow via global state.
* The injected function is available via {@link Context.dependencies}.
*/
function inject(ifaceName, fnName, dependency, applyMode, transferOptions) {
if (exports.state.dependencies[ifaceName] === undefined) {
exports.state.dependencies[ifaceName] = {};
}
if (applyMode === interfaces_1.ApplyMode.ASYNC) {
exports.state.dependencies[ifaceName][fnName] = (...args) => new Promise((resolve, reject) => {
const seq = exports.state.nextSeq++;
exports.state.completions.set(seq, {
resolve,
reject,
});
exports.state.pendingExternalCalls.push({ ifaceName, fnName, args, seq });
});
}
else if (applyMode === interfaces_1.ApplyMode.ASYNC_IGNORED) {
exports.state.dependencies[ifaceName][fnName] = (...args) => exports.state.pendingExternalCalls.push({ ifaceName, fnName, args });
}
else {
exports.state.dependencies[ifaceName][fnName] = (...args) => dependency[applyMode](undefined, args, transferOptions);
}
}
exports.inject = inject;
/**
* Resolve external dependency function calls with given results.
*/
function resolveExternalDependencies(results) {
for (const { seq, result, error } of results) {
const completion = consumeCompletion(seq);
if (error) {
completion.reject(error);
}
else {
completion.resolve(result);
}
}
}
exports.resolveExternalDependencies = resolveExternalDependencies;
//# sourceMappingURL=internals.js.map

@@ -1,2 +0,1 @@

import { CancellationScope } from './cancellation-scope';
/** v8 hook types */

@@ -11,6 +10,6 @@ export declare type HookType = 'init' | 'resolve' | 'before' | 'after';

registerPromiseHook(hook: PromiseHook): void;
/** Associate a Promise with its CancellationScope */
setPromiseData(p: Promise<any>, s: CancellationScope): void;
/** Get the CancellationScope associated with a Promise */
getPromiseData(p: Promise<any>): CancellationScope | undefined;
/** Associate a Promise with each hook's custom data */
setPromiseData(p: Promise<any>, s: Map<PromiseHook, any>): void;
/** Get the custom hook data associated with a Promise */
getPromiseData(p: Promise<any>): Map<PromiseHook, any> | undefined;
}

@@ -20,12 +19,38 @@ /**

*/
export declare class ScopeHookManager {
protected readonly isolateExtension: IsolateExtension;
protected readonly childScopes: Map<CancellationScope, Set<CancellationScope>>;
constructor(isolateExtension: IsolateExtension);
export declare class HookManager {
protected readonly registeredHooks: Set<PromiseHook>;
/**
* The PromiseHook implementation
*
* Note that the parent promise is unused as it was not found neccessary for the implementation
* A reference to the native isolate extension, lazily initialized along with the Workflow
*/
hook(t: HookType, p: Promise<any>, _pp?: Promise<any>): void;
protected isolateExtension?: IsolateExtension;
protected constructor();
static instance: HookManager;
/**
* To be called from the Workflow runtime library to set the native module reference
*/
setIsolateExtension(isolateExtension: IsolateExtension): void;
/**
* Helper that ensures isolateExtension has been set
*/
getIsolateExtension(): IsolateExtension;
/**
* Register a single promise hook callback
*/
register(hook: PromiseHook): void;
/**
* Deregister a single promise hook callback
*/
deregister(hook: PromiseHook): void;
/**
* The PromiseHook implementation, calls all registered hooks
*/
protected hook(t: HookType, p: Promise<any>, pp?: Promise<any>): void;
/**
* Get custom promise data for a promise hook
*/
getPromiseData(p: Promise<any>, hook: PromiseHook): unknown;
/**
* Set custom promise data for a promise hook
*/
setPromiseData(p: Promise<any>, hook: PromiseHook, data: unknown): void;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ScopeHookManager = void 0;
const cancellation_scope_1 = require("./cancellation-scope");
exports.HookManager = void 0;
const errors_1 = require("./errors");
/**
* Uses the v8 PromiseHook callback to track the current `CancellationScope`
*/
class ScopeHookManager {
constructor(isolateExtension) {
class HookManager {
constructor() {
this.registeredHooks = new Set();
// Prevent construction other than the singleton
}
/**
* To be called from the Workflow runtime library to set the native module reference
*/
setIsolateExtension(isolateExtension) {
this.isolateExtension = isolateExtension;
this.childScopes = new Map();
isolateExtension.registerPromiseHook(this.hook.bind(this));
}
/**
* The PromiseHook implementation
*
* Note that the parent promise is unused as it was not found neccessary for the implementation
* Helper that ensures isolateExtension has been set
*/
hook(t, p, _pp) {
switch (t) {
// When a Promise is created associate it with a CancellationScope
case 'init':
this.isolateExtension.setPromiseData(p, cancellation_scope_1.CancellationScope.current());
break;
// Called at the beginning of the PromiseReactionJob,
// p is the promise about to execute, resume its scope.
case 'before':
cancellation_scope_1.pushScope(this.isolateExtension.getPromiseData(p) || cancellation_scope_1.ROOT_SCOPE);
break;
// Called at the end of the PromiseReactionJob,
// pop the current Promise off the scope stack.
case 'after':
cancellation_scope_1.popScope();
break;
getIsolateExtension() {
if (this.isolateExtension === undefined) {
throw new errors_1.IllegalStateError('HookManager has not been properly initialized');
}
return this.isolateExtension;
}
/**
* Register a single promise hook callback
*/
register(hook) {
this.registeredHooks.add(hook);
}
/**
* Deregister a single promise hook callback
*/
deregister(hook) {
this.registeredHooks.delete(hook);
}
/**
* The PromiseHook implementation, calls all registered hooks
*/
hook(t, p, pp) {
for (const hook of this.registeredHooks) {
hook(t, p, pp);
}
}
/**
* Get custom promise data for a promise hook
*/
getPromiseData(p, hook) {
const data = this.getIsolateExtension().getPromiseData(p);
if (data) {
return data.get(hook);
}
}
/**
* Set custom promise data for a promise hook
*/
setPromiseData(p, hook, data) {
const isolateExtension = this.getIsolateExtension();
let mapping = isolateExtension.getPromiseData(p);
if (!mapping) {
mapping = new Map();
isolateExtension.setPromiseData(p, mapping);
}
mapping.set(hook, data);
}
}
exports.ScopeHookManager = ScopeHookManager;
exports.HookManager = HookManager;
// Singleton instance
HookManager.instance = new HookManager();
//# sourceMappingURL=promise-hooks.js.map

@@ -24,3 +24,3 @@ import { ActivityFunction, ActivityOptions, ExternalDependencies, RemoteActivityOptions, WorkflowInfo } from './interfaces';

*/
export declare function scheduleActivity<R>(activityType: string, args: any[], options: ActivityOptions): Promise<R>;
export declare function scheduleActivity<R>(activityType: string, args: any[], options?: ActivityOptions | undefined): Promise<R>;
export declare class ContextImpl {

@@ -75,5 +75,2 @@ /**

*
* **IMPOTANT**: dependencies may not be called at the top level because they require the Workflow to be initialized.
* You may reference them as demonstrated below but trying to call them at the top level will throw an `IllegalStateError`.
*
* @example

@@ -85,7 +82,7 @@ * ```ts

* const { logger } = Context.dependencies<MyDependencies>();
* logger.info('...'); // <-- IllegalStateError
* logger.info('setting up');
*
* export function main(): void {
* logger.info('hey ho'); // <-- OK
* logger.error('lets go'); // <-- OK
* logger.info('hey ho');
* logger.error('lets go');
* }

@@ -92,0 +89,0 @@ * ```

@@ -129,5 +129,8 @@ "use strict";

*/
function scheduleActivity(activityType, args, options) {
function scheduleActivity(activityType, args, options = internals_1.state.activityDefaults) {
const seq = internals_1.state.nextSeq++;
const execute = interceptors_1.composeInterceptors(internals_1.state.interceptors.outbound, 'scheduleActivity', scheduleActivityNextHandler);
if (options === undefined) {
throw new TypeError('Got empty activity options');
}
return execute({

@@ -226,5 +229,2 @@ activityType: activityType,

*
* **IMPOTANT**: dependencies may not be called at the top level because they require the Workflow to be initialized.
* You may reference them as demonstrated below but trying to call them at the top level will throw an `IllegalStateError`.
*
* @example

@@ -236,7 +236,7 @@ * ```ts

* const { logger } = Context.dependencies<MyDependencies>();
* logger.info('...'); // <-- IllegalStateError
* logger.info('setting up');
*
* export function main(): void {
* logger.info('hey ho'); // <-- OK
* logger.error('lets go'); // <-- OK
* logger.info('hey ho');
* logger.error('lets go');
* }

@@ -243,0 +243,0 @@ * ```

{
"name": "@temporalio/workflow",
"version": "0.3.2",
"version": "0.4.0",
"description": "Temporal.io SDK Workflow sub-package",

@@ -16,3 +16,3 @@ "main": "lib/index.js",

"dependencies": {
"@temporalio/proto": "^0.2.2"
"@temporalio/proto": "^0.2.3"
},

@@ -29,3 +29,3 @@ "bugs": {

},
"gitHead": "0a8ce07819391da5e9923a9202e77ef9dac1211d"
"gitHead": "766f94c1154962fe367f5b2d8737a50bc3badde9"
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc