@dbos-inc/dbos-sdk 2.11.7-preview.gc208400219 → 2.11.15-preview.gd8ed483d92
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/dist/src/authdecorators.js +3 -3
- package/dist/src/authdecorators.js.map +1 -1
- package/dist/src/client.d.ts +7 -1
- package/dist/src/client.d.ts.map +1 -1
- package/dist/src/client.js +3 -3
- package/dist/src/client.js.map +1 -1
- package/dist/src/conductor/conductor.d.ts.map +1 -1
- package/dist/src/conductor/conductor.js +18 -0
- package/dist/src/conductor/conductor.js.map +1 -1
- package/dist/src/conductor/protocol.d.ts +17 -1
- package/dist/src/conductor/protocol.d.ts.map +1 -1
- package/dist/src/conductor/protocol.js +20 -1
- package/dist/src/conductor/protocol.js.map +1 -1
- package/dist/src/context.d.ts +1 -0
- package/dist/src/context.d.ts.map +1 -1
- package/dist/src/context.js +11 -1
- package/dist/src/context.js.map +1 -1
- package/dist/src/datasource.d.ts +104 -0
- package/dist/src/datasource.d.ts.map +1 -0
- package/dist/src/datasource.js +141 -0
- package/dist/src/datasource.js.map +1 -0
- package/dist/src/dbos-executor.d.ts +1 -1
- package/dist/src/dbos-executor.d.ts.map +1 -1
- package/dist/src/dbos-executor.js +14 -20
- package/dist/src/dbos-executor.js.map +1 -1
- package/dist/src/dbos-runtime/workflow_management.d.ts +1 -1
- package/dist/src/dbos-runtime/workflow_management.d.ts.map +1 -1
- package/dist/src/dbos-runtime/workflow_management.js +1 -2
- package/dist/src/dbos-runtime/workflow_management.js.map +1 -1
- package/dist/src/dbos.d.ts +53 -3
- package/dist/src/dbos.d.ts.map +1 -1
- package/dist/src/dbos.js +216 -199
- package/dist/src/dbos.js.map +1 -1
- package/dist/src/decorators.d.ts +8 -1
- package/dist/src/decorators.d.ts.map +1 -1
- package/dist/src/decorators.js +32 -7
- package/dist/src/decorators.js.map +1 -1
- package/dist/src/httpServer/server.d.ts +18 -0
- package/dist/src/httpServer/server.d.ts.map +1 -1
- package/dist/src/httpServer/server.js +113 -1
- package/dist/src/httpServer/server.js.map +1 -1
- package/dist/src/paramdecorators.js +12 -12
- package/dist/src/paramdecorators.js.map +1 -1
- package/dist/src/system_database.d.ts +1 -1
- package/dist/src/system_database.d.ts.map +1 -1
- package/dist/src/workflow.js +1 -1
- package/dist/src/workflow.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +13 -1
package/dist/src/dbos.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.InitContext = exports.DBOS = exports.
|
3
|
+
exports.InitContext = exports.DBOS = exports.runInternalStep = exports.getExecutor = void 0;
|
4
4
|
const context_1 = require("./context");
|
5
5
|
const dbos_executor_1 = require("./dbos-executor");
|
6
6
|
const logs_1 = require("./telemetry/logs");
|
@@ -14,6 +14,7 @@ const middleware_1 = require("./httpServer/middleware");
|
|
14
14
|
const user_database_1 = require("./user_database");
|
15
15
|
const node_crypto_1 = require("node:crypto");
|
16
16
|
const _1 = require(".");
|
17
|
+
const _2 = require(".");
|
17
18
|
const handlerTypes_1 = require("./httpServer/handlerTypes");
|
18
19
|
const lodash_1 = require("lodash");
|
19
20
|
const conductor_1 = require("./conductor/conductor");
|
@@ -63,23 +64,24 @@ function getExecutor() {
|
|
63
64
|
return dbos_executor_1.DBOSExecutor.globalInstance;
|
64
65
|
}
|
65
66
|
exports.getExecutor = getExecutor;
|
66
|
-
function
|
67
|
+
function runInternalStep(callback, funcName, childWFID) {
|
67
68
|
if (DBOS.isWithinWorkflow()) {
|
68
69
|
if (DBOS.isInStep()) {
|
69
70
|
// OK to use directly
|
70
|
-
return
|
71
|
+
return callback();
|
71
72
|
}
|
72
73
|
else if (DBOS.isInWorkflow()) {
|
73
74
|
const wfctx = (0, context_1.assertCurrentWorkflowContext)();
|
74
|
-
return dbos_executor_1.DBOSExecutor.globalInstance.
|
75
|
+
return dbos_executor_1.DBOSExecutor.globalInstance.runInternalStep(callback, funcName, DBOS.workflowID, // assume DBOS.workflowID is defined because of assertCurrentWorkflowContext call above
|
76
|
+
wfctx.functionIDGetIncrement(), childWFID);
|
75
77
|
}
|
76
78
|
else {
|
77
79
|
throw new error_1.DBOSInvalidWorkflowTransitionError(`Invalid call to \`${funcName}\` inside a \`transaction\` or \`procedure\``);
|
78
80
|
}
|
79
81
|
}
|
80
|
-
return
|
82
|
+
return callback();
|
81
83
|
}
|
82
|
-
exports.
|
84
|
+
exports.runInternalStep = runInternalStep;
|
83
85
|
class DBOS {
|
84
86
|
///////
|
85
87
|
// Lifecycle
|
@@ -204,6 +206,9 @@ class DBOS {
|
|
204
206
|
return; // return for cases where process.exit is mocked
|
205
207
|
}
|
206
208
|
await dbos_executor_1.DBOSExecutor.globalInstance.initEventReceivers();
|
209
|
+
for (const [_n, ds] of decorators_1.transactionalDataSources) {
|
210
|
+
await ds.initialize();
|
211
|
+
}
|
207
212
|
if (options?.conductorKey) {
|
208
213
|
if (!options.conductorURL) {
|
209
214
|
const dbosDomain = process.env.DBOS_DOMAIN || 'cloud.dbos.dev';
|
@@ -310,6 +315,9 @@ class DBOS {
|
|
310
315
|
await dbos_executor_1.DBOSExecutor.globalInstance.destroy();
|
311
316
|
dbos_executor_1.DBOSExecutor.globalInstance = undefined;
|
312
317
|
}
|
318
|
+
for (const [_n, ds] of decorators_1.transactionalDataSources) {
|
319
|
+
await ds.destroy();
|
320
|
+
}
|
313
321
|
// Reset the global app version and executor ID
|
314
322
|
utils_1.globalParams.appVersion = process.env.DBOS__APPVERSION || '';
|
315
323
|
utils_1.globalParams.wasComputed = false;
|
@@ -636,9 +644,6 @@ class DBOS {
|
|
636
644
|
//////
|
637
645
|
// Workflow and other operations
|
638
646
|
//////
|
639
|
-
static #runAsWorkflowStep(callback, funcName) {
|
640
|
-
return runAsWorkflowStep(callback, funcName);
|
641
|
-
}
|
642
647
|
/**
|
643
648
|
* Get the workflow status given a workflow ID
|
644
649
|
* @param workflowID - ID of the workflow
|
@@ -671,7 +676,7 @@ class DBOS {
|
|
671
676
|
if (DBOS.isWithinWorkflow() && timeoutSeconds !== undefined) {
|
672
677
|
timerFuncID = (0, context_1.assertCurrentWorkflowContext)().functionIDGetIncrement();
|
673
678
|
}
|
674
|
-
return await
|
679
|
+
return await runInternalStep(async () => {
|
675
680
|
const rres = await dbos_executor_1.DBOSExecutor.globalInstance.systemDatabase.awaitWorkflowResult(workflowID, timeoutSeconds, DBOS.workflowID, timerFuncID);
|
676
681
|
if (!rres)
|
677
682
|
return null;
|
@@ -704,7 +709,7 @@ class DBOS {
|
|
704
709
|
* @deprecated Use `DBOS.listWorkflows` instead
|
705
710
|
*/
|
706
711
|
static async getWorkflows(input) {
|
707
|
-
return await
|
712
|
+
return await runInternalStep(async () => {
|
708
713
|
const wfs = await DBOS.#executor.listWorkflows(input);
|
709
714
|
return { workflowUUIDs: wfs.map((wf) => wf.workflowID) };
|
710
715
|
}, 'DBOS.getWorkflows');
|
@@ -715,7 +720,7 @@ class DBOS {
|
|
715
720
|
* @returns `WorkflowStatus` array containing details of the matching workflows
|
716
721
|
*/
|
717
722
|
static async listWorkflows(input) {
|
718
|
-
return await
|
723
|
+
return await runInternalStep(async () => {
|
719
724
|
return await DBOS.#executor.listWorkflows(input);
|
720
725
|
}, 'DBOS.listWorkflows');
|
721
726
|
}
|
@@ -725,7 +730,7 @@ class DBOS {
|
|
725
730
|
* @returns `WorkflowStatus` array containing details of the matching workflows
|
726
731
|
*/
|
727
732
|
static async listQueuedWorkflows(input) {
|
728
|
-
return await
|
733
|
+
return await runInternalStep(async () => {
|
729
734
|
return await DBOS.#executor.listQueuedWorkflows(input);
|
730
735
|
}, 'DBOS.listQueuedWorkflows');
|
731
736
|
}
|
@@ -735,7 +740,7 @@ class DBOS {
|
|
735
740
|
* @returns `StepInfo` array listing the executed steps of the workflow. If the workflow is not found, `undefined` is returned.
|
736
741
|
*/
|
737
742
|
static async listWorkflowSteps(workflowID) {
|
738
|
-
return await
|
743
|
+
return await runInternalStep(async () => {
|
739
744
|
return await DBOS.#executor.listWorkflowSteps(workflowID);
|
740
745
|
}, 'DBOS.listWorkflowSteps');
|
741
746
|
}
|
@@ -746,7 +751,7 @@ class DBOS {
|
|
746
751
|
* @param workflowID - ID of the workflow
|
747
752
|
*/
|
748
753
|
static async cancelWorkflow(workflowID) {
|
749
|
-
return await
|
754
|
+
return await runInternalStep(async () => {
|
750
755
|
return await DBOS.#executor.cancelWorkflow(workflowID);
|
751
756
|
}, 'DBOS.cancelWorkflow');
|
752
757
|
}
|
@@ -755,7 +760,7 @@ class DBOS {
|
|
755
760
|
* @param workflowID - ID of the workflow
|
756
761
|
*/
|
757
762
|
static async resumeWorkflow(workflowID) {
|
758
|
-
await
|
763
|
+
await runInternalStep(async () => {
|
759
764
|
return await DBOS.#executor.resumeWorkflow(workflowID);
|
760
765
|
}, 'DBOS.resumeWorkflow');
|
761
766
|
return this.retrieveWorkflow(workflowID);
|
@@ -769,7 +774,7 @@ class DBOS {
|
|
769
774
|
* @throws DBOSInvalidStepIDError if the `startStep` is greater than the maximum step ID of the workflow
|
770
775
|
*/
|
771
776
|
static async forkWorkflow(workflowID, startStep, options) {
|
772
|
-
const forkedID = await
|
777
|
+
const forkedID = await runInternalStep(async () => {
|
773
778
|
return await DBOS.#executor.forkWorkflow(workflowID, startStep, options);
|
774
779
|
}, 'DBOS.forkWorkflow');
|
775
780
|
return this.retrieveWorkflow(forkedID);
|
@@ -929,114 +934,39 @@ class DBOS {
|
|
929
934
|
}, callback);
|
930
935
|
}
|
931
936
|
}
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
937
|
+
/**
|
938
|
+
* Start a workflow in the background, returning a handle that can be used to check status,
|
939
|
+
* await the result, or otherwise interact with the workflow.
|
940
|
+
* @param func - The function to start. If a class or instance method, supply `this` within `params`.
|
941
|
+
* @param params - `StartWorkflowFunctionParams` which may specify the ID, queue, `this`, or other parameters
|
942
|
+
* @param args - Arguments passed to `func`
|
943
|
+
* @returns `WorkflowHandle` which can be used to interact with the started workflow
|
944
|
+
*/
|
945
|
+
static async startWorkflowFunction(params, func, ...args) {
|
946
|
+
const regOp = (0, decorators_1.getRegistrationForFunction)(func);
|
947
|
+
if (!regOp) {
|
948
|
+
throw new error_1.DBOSNotRegisteredError(func.name, `${func.name} is not a registered DBOS workflow function`);
|
938
949
|
}
|
950
|
+
return await DBOS.#invokeWorkflow(params?.instance, regOp, args, params ?? {});
|
939
951
|
}
|
940
|
-
static
|
941
|
-
const
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
const funcId = wfctx.functionIDGetIncrement();
|
953
|
-
wfId = wfId || wfctx.workflowUUID + '-' + funcId;
|
954
|
-
const wfParams = {
|
955
|
-
workflowUUID: wfId,
|
956
|
-
parentCtx: wfctx,
|
957
|
-
configuredInstance,
|
958
|
-
queueName: inParams?.queueName ?? pctx?.queueAssignedForWorkflows,
|
959
|
-
timeoutMS: inParams?.timeoutMS ?? pctx?.workflowTimeoutMS,
|
960
|
-
deadlineEpochMS: wfctx.deadlineEpochMS,
|
961
|
-
enqueueOptions: inParams?.enqueueOptions,
|
962
|
-
};
|
963
|
-
// Detach child deadline if a null timeout is configured
|
964
|
-
// We must check the inParams but also pctx (if the workflow was called withWorkflowTimeout)
|
965
|
-
if (inParams?.timeoutMS === null || pctx?.workflowTimeoutMS === null) {
|
966
|
-
wfParams.deadlineEpochMS = undefined;
|
967
|
-
}
|
968
|
-
for (const op of ops) {
|
969
|
-
if (op.workflowConfig) {
|
970
|
-
proxy[op.name] = (...args) => dbos_executor_1.DBOSExecutor.globalInstance.internalWorkflow(op.registeredFunction, wfParams, wfctx.workflowUUID, funcId, ...args);
|
971
|
-
}
|
972
|
-
else if (op.txnConfig) {
|
973
|
-
const txn = op.registeredFunction;
|
974
|
-
proxy[op.name] = (...args) => dbos_executor_1.DBOSExecutor.globalInstance.startTransactionTempWF(txn, wfParams, wfctx.workflowUUID, funcId, ...args);
|
975
|
-
}
|
976
|
-
else if (op.stepConfig) {
|
977
|
-
const step = op.registeredFunction;
|
978
|
-
proxy[op.name] = (...args) => {
|
979
|
-
return dbos_executor_1.DBOSExecutor.globalInstance.startStepTempWF(step, wfParams, wfctx.workflowUUID, funcId, ...args);
|
980
|
-
};
|
981
|
-
}
|
982
|
-
else {
|
983
|
-
proxy[op.name] = (..._args) => {
|
984
|
-
throw new error_1.DBOSNotRegisteredError(op.name, `${op.name} is not a registered DBOS workflow, step, or transaction function`);
|
985
|
-
};
|
952
|
+
static startWorkflow(target, params) {
|
953
|
+
const instance = typeof target === 'function' ? null : target;
|
954
|
+
if (instance && !(instance instanceof _2.ConfiguredInstance)) {
|
955
|
+
throw new error_1.DBOSInvalidWorkflowTransitionError('Attempt to call `startWorkflow` on an object that is not a `ConfiguredInstance`');
|
956
|
+
}
|
957
|
+
const regOps = (0, decorators_1.getRegisteredOperations)(target);
|
958
|
+
const handler = {
|
959
|
+
get(target, p, receiver) {
|
960
|
+
const func = Reflect.get(target, p, receiver);
|
961
|
+
const regOp = (0, decorators_1.getRegistrationForFunction)(func) ?? regOps.find((op) => op.name === p);
|
962
|
+
if (regOp) {
|
963
|
+
return (...args) => DBOS.#invokeWorkflow(instance, regOp, args, params);
|
986
964
|
}
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
}
|
991
|
-
// Else, we setup a parent context that includes all the potential metadata the application could have set in DBOSLocalCtx
|
992
|
-
let parentCtx = undefined;
|
993
|
-
if (pctx) {
|
994
|
-
// If pctx has no span, e.g., has not been setup through `withTracedContext`, set up a parent span for the workflow here.
|
995
|
-
let span = pctx.span;
|
996
|
-
if (!span) {
|
997
|
-
span = DBOS.#executor.tracer.startSpan(pctx.operationCaller || 'startWorkflow', {
|
998
|
-
operationUUID: wfId,
|
999
|
-
operationType: pctx.operationType,
|
1000
|
-
authenticatedUser: pctx.authenticatedUser,
|
1001
|
-
assumedRole: pctx.assumedRole,
|
1002
|
-
authenticatedRoles: pctx.authenticatedRoles,
|
1003
|
-
});
|
1004
|
-
}
|
1005
|
-
parentCtx = new context_1.DBOSContextImpl(pctx.operationCaller || 'startWorkflow', span, DBOS.logger);
|
1006
|
-
parentCtx.request = pctx.request || {};
|
1007
|
-
parentCtx.authenticatedUser = pctx.authenticatedUser || '';
|
1008
|
-
parentCtx.assumedRole = pctx.assumedRole || '';
|
1009
|
-
parentCtx.authenticatedRoles = pctx.authenticatedRoles || [];
|
1010
|
-
parentCtx.workflowUUID = wfId || '';
|
1011
|
-
}
|
1012
|
-
const wfParams = {
|
1013
|
-
workflowUUID: wfId,
|
1014
|
-
queueName: inParams?.queueName ?? pctx?.queueAssignedForWorkflows,
|
1015
|
-
enqueueOptions: inParams?.enqueueOptions,
|
1016
|
-
configuredInstance,
|
1017
|
-
parentCtx,
|
1018
|
-
timeoutMS: inParams?.timeoutMS ?? pctx?.workflowTimeoutMS,
|
965
|
+
const name = typeof p === 'string' ? p : String(p);
|
966
|
+
throw new error_1.DBOSNotRegisteredError(name, `${name} is not a registered DBOS workflow function`);
|
967
|
+
},
|
1019
968
|
};
|
1020
|
-
|
1021
|
-
if (op.workflowConfig) {
|
1022
|
-
proxy[op.name] = (...args) => DBOS.#executor.workflow(op.registeredFunction, wfParams, ...args);
|
1023
|
-
}
|
1024
|
-
else if (op.txnConfig) {
|
1025
|
-
const txn = op.registeredFunction;
|
1026
|
-
proxy[op.name] = (...args) => dbos_executor_1.DBOSExecutor.globalInstance.startTransactionTempWF(txn, wfParams, undefined, undefined, ...args);
|
1027
|
-
}
|
1028
|
-
else if (op.stepConfig) {
|
1029
|
-
const step = op.registeredFunction;
|
1030
|
-
proxy[op.name] = (...args) => dbos_executor_1.DBOSExecutor.globalInstance.startStepTempWF(step, wfParams, undefined, undefined, ...args);
|
1031
|
-
}
|
1032
|
-
else {
|
1033
|
-
proxy[op.name] = (..._args) => {
|
1034
|
-
throw new error_1.DBOSNotRegisteredError(op.name, `${op.name} is not a registered DBOS workflow, step, or transaction function`);
|
1035
|
-
};
|
1036
|
-
}
|
1037
|
-
}
|
1038
|
-
augmentProxy(configuredInstance ?? object, proxy);
|
1039
|
-
return proxy;
|
969
|
+
return new Proxy(target, handler);
|
1040
970
|
}
|
1041
971
|
static invoke(object) {
|
1042
972
|
if (!DBOS.isWithinWorkflow()) {
|
@@ -1244,85 +1174,113 @@ class DBOS {
|
|
1244
1174
|
static workflow(config = {}) {
|
1245
1175
|
function decorator(target, propertyKey, inDescriptor) {
|
1246
1176
|
const { descriptor, registration } = (0, decorators_1.registerAndWrapDBOSFunction)(target, propertyKey, inDescriptor);
|
1247
|
-
registration
|
1248
|
-
|
1249
|
-
|
1250
|
-
let inst = undefined;
|
1251
|
-
if (this === undefined || typeof this === 'function') {
|
1252
|
-
// This is static
|
1253
|
-
}
|
1254
|
-
else {
|
1255
|
-
inst = this;
|
1256
|
-
if (!('name' in inst)) {
|
1257
|
-
throw new error_1.DBOSInvalidWorkflowTransitionError('Attempt to call a `workflow` function on an object that is not a `ConfiguredInstance`');
|
1258
|
-
}
|
1259
|
-
}
|
1260
|
-
let wfId = (0, context_1.getNextWFID)(undefined);
|
1261
|
-
// If this is called from within a workflow, this is a child workflow,
|
1262
|
-
// For OAOO, we will need a consistent ID formed from the parent WF and call number
|
1263
|
-
if (DBOS.isWithinWorkflow()) {
|
1264
|
-
if (!DBOS.isInWorkflow()) {
|
1265
|
-
throw new error_1.DBOSInvalidWorkflowTransitionError('Invalid call to a `workflow` function from within a `step` or `transaction`');
|
1266
|
-
}
|
1267
|
-
const wfctx = (0, context_1.assertCurrentWorkflowContext)();
|
1268
|
-
const funcId = wfctx.functionIDGetIncrement();
|
1269
|
-
wfId = wfId || wfctx.workflowUUID + '-' + funcId;
|
1270
|
-
const params = {
|
1271
|
-
workflowUUID: wfId,
|
1272
|
-
parentCtx: wfctx,
|
1273
|
-
configuredInstance: inst,
|
1274
|
-
queueName: pctx?.queueAssignedForWorkflows,
|
1275
|
-
timeoutMS: pctx?.workflowTimeoutMS,
|
1276
|
-
deadlineEpochMS: wfctx.deadlineEpochMS,
|
1277
|
-
};
|
1278
|
-
// Detach child deadline if a null timeout is configured
|
1279
|
-
if (pctx?.workflowTimeoutMS === null) {
|
1280
|
-
params.deadlineEpochMS = undefined;
|
1281
|
-
}
|
1282
|
-
const cwfh = await dbos_executor_1.DBOSExecutor.globalInstance.internalWorkflow(registration.registeredFunction, params, wfctx.workflowUUID, funcId, ...rawArgs);
|
1283
|
-
return await cwfh.getResult();
|
1284
|
-
}
|
1285
|
-
// Else, we setup a parent context that includes all the potential metadata the application could have set in DBOSLocalCtx
|
1286
|
-
let parentCtx = undefined;
|
1287
|
-
if (pctx) {
|
1288
|
-
// If pctx has no span, e.g., has not been setup through `withTracedContext`, set up a parent span for the workflow here.
|
1289
|
-
let span = pctx.span;
|
1290
|
-
if (!span) {
|
1291
|
-
span = DBOS.#executor.tracer.startSpan(pctx.operationCaller || 'workflowCaller', {
|
1292
|
-
operationUUID: wfId,
|
1293
|
-
operationType: pctx.operationType,
|
1294
|
-
authenticatedUser: pctx.authenticatedUser,
|
1295
|
-
assumedRole: pctx.assumedRole,
|
1296
|
-
authenticatedRoles: pctx.authenticatedRoles,
|
1297
|
-
});
|
1298
|
-
}
|
1299
|
-
parentCtx = new context_1.DBOSContextImpl(pctx.operationCaller || 'workflowCaller', span, DBOS.logger);
|
1300
|
-
parentCtx.request = pctx.request || {};
|
1301
|
-
parentCtx.authenticatedUser = pctx.authenticatedUser || '';
|
1302
|
-
parentCtx.assumedRole = pctx.assumedRole || '';
|
1303
|
-
parentCtx.authenticatedRoles = pctx.authenticatedRoles || [];
|
1304
|
-
parentCtx.workflowUUID = wfId || '';
|
1305
|
-
}
|
1306
|
-
const wfParams = {
|
1307
|
-
workflowUUID: wfId,
|
1308
|
-
queueName: pctx?.queueAssignedForWorkflows,
|
1309
|
-
configuredInstance: inst,
|
1310
|
-
parentCtx,
|
1311
|
-
timeoutMS: pctx?.workflowTimeoutMS,
|
1312
|
-
};
|
1313
|
-
const handle = await DBOS.#executor.workflow(registration.registeredFunction, wfParams, ...rawArgs);
|
1314
|
-
return await handle.getResult();
|
1315
|
-
};
|
1316
|
-
descriptor.value = invokeWrapper;
|
1317
|
-
registration.wrappedFunction = invokeWrapper;
|
1318
|
-
Object.defineProperty(invokeWrapper, 'name', {
|
1319
|
-
value: registration.name,
|
1320
|
-
});
|
1321
|
-
(0, decorators_1.registerFunctionWrapper)(invokeWrapper, registration);
|
1177
|
+
const invoker = DBOS.#getWorkflowInvoker(registration, config);
|
1178
|
+
descriptor.value = invoker;
|
1179
|
+
registration.wrappedFunction = invoker;
|
1322
1180
|
return descriptor;
|
1323
1181
|
}
|
1324
1182
|
return decorator;
|
1325
1183
|
}
|
1184
|
+
/**
|
1185
|
+
* Create a DBOS workflow function from a provided function.
|
1186
|
+
* Similar to the DBOS.workflow, but without requiring a decorator
|
1187
|
+
* Durable execution will be applied to calls to the function returned by registerWorkflow
|
1188
|
+
* This also registers the function so that it is available during recovery
|
1189
|
+
* @param func - The function to register as a workflow
|
1190
|
+
* @param name - The name of the registered workflow
|
1191
|
+
* @param options - Configuration information for the registered workflow
|
1192
|
+
*/
|
1193
|
+
static registerWorkflow(func, name, options = {}) {
|
1194
|
+
const { registration } = (0, decorators_1.registerAndWrapDBOSFunctionByName)(options.classOrInst, options.className, name, func);
|
1195
|
+
return DBOS.#getWorkflowInvoker(registration, options.config);
|
1196
|
+
}
|
1197
|
+
static async #invokeWorkflow($this, regOP, args, params = {}) {
|
1198
|
+
const wfId = (0, context_1.getNextWFID)(params.workflowID);
|
1199
|
+
const pctx = (0, context_1.getCurrentContextStore)();
|
1200
|
+
const queueName = params.queueName ?? pctx?.queueAssignedForWorkflows;
|
1201
|
+
const timeoutMS = params.timeoutMS ?? pctx?.workflowTimeoutMS;
|
1202
|
+
const instance = $this === undefined || typeof $this === 'function' ? undefined : $this;
|
1203
|
+
if (instance && !(instance instanceof _2.ConfiguredInstance)) {
|
1204
|
+
throw new error_1.DBOSInvalidWorkflowTransitionError('Attempt to call a `workflow` function on an object that is not a `ConfiguredInstance`');
|
1205
|
+
}
|
1206
|
+
// If this is called from within a workflow, this is a child workflow,
|
1207
|
+
// For OAOO, we will need a consistent ID formed from the parent WF and call number
|
1208
|
+
if (DBOS.isWithinWorkflow()) {
|
1209
|
+
if (!DBOS.isInWorkflow()) {
|
1210
|
+
throw new error_1.DBOSInvalidWorkflowTransitionError('Invalid call to a `workflow` function from within a `step` or `transaction`');
|
1211
|
+
}
|
1212
|
+
const wfctx = (0, context_1.assertCurrentWorkflowContext)();
|
1213
|
+
const funcId = wfctx.functionIDGetIncrement();
|
1214
|
+
const wfParams = {
|
1215
|
+
workflowUUID: wfId || wfctx.workflowUUID + '-' + funcId,
|
1216
|
+
parentCtx: wfctx,
|
1217
|
+
configuredInstance: instance,
|
1218
|
+
queueName,
|
1219
|
+
timeoutMS,
|
1220
|
+
// Detach child deadline if a null timeout is configured
|
1221
|
+
deadlineEpochMS: params.timeoutMS === null || pctx?.workflowTimeoutMS === null ? undefined : wfctx.deadlineEpochMS,
|
1222
|
+
enqueueOptions: params.enqueueOptions,
|
1223
|
+
};
|
1224
|
+
return await invokeRegOp(wfParams, wfctx.workflowUUID, funcId);
|
1225
|
+
}
|
1226
|
+
else {
|
1227
|
+
// Else, we setup a parent context that includes all the potential metadata the application could have set in DBOSLocalCtx
|
1228
|
+
let parentCtx = undefined;
|
1229
|
+
if (pctx) {
|
1230
|
+
// If pctx has no span, e.g., has not been setup through `withTracedContext`, set up a parent span for the workflow here.
|
1231
|
+
const span = pctx.span ??
|
1232
|
+
DBOS.#executor.tracer.startSpan(pctx.operationCaller || 'workflowCaller', {
|
1233
|
+
operationUUID: wfId,
|
1234
|
+
operationType: pctx.operationType,
|
1235
|
+
authenticatedUser: pctx.authenticatedUser,
|
1236
|
+
assumedRole: pctx.assumedRole,
|
1237
|
+
authenticatedRoles: pctx.authenticatedRoles,
|
1238
|
+
});
|
1239
|
+
parentCtx = new context_1.DBOSContextImpl(pctx.operationCaller || 'workflowCaller', span, DBOS.logger);
|
1240
|
+
parentCtx.request = pctx.request ?? {};
|
1241
|
+
parentCtx.authenticatedUser = pctx.authenticatedUser ?? '';
|
1242
|
+
parentCtx.assumedRole = pctx.assumedRole ?? '';
|
1243
|
+
parentCtx.authenticatedRoles = pctx.authenticatedRoles ?? [];
|
1244
|
+
parentCtx.workflowUUID = wfId ?? '';
|
1245
|
+
}
|
1246
|
+
const wfParams = {
|
1247
|
+
workflowUUID: wfId,
|
1248
|
+
queueName,
|
1249
|
+
enqueueOptions: params.enqueueOptions,
|
1250
|
+
configuredInstance: instance,
|
1251
|
+
parentCtx,
|
1252
|
+
timeoutMS,
|
1253
|
+
};
|
1254
|
+
return await invokeRegOp(wfParams, undefined, undefined);
|
1255
|
+
}
|
1256
|
+
function invokeRegOp(wfParams, workflowID, funcNum) {
|
1257
|
+
if (regOP.workflowConfig) {
|
1258
|
+
const func = regOP.registeredFunction;
|
1259
|
+
return dbos_executor_1.DBOSExecutor.globalInstance.internalWorkflow(func, wfParams, workflowID, funcNum, ...args);
|
1260
|
+
}
|
1261
|
+
if (regOP.txnConfig) {
|
1262
|
+
const func = regOP.registeredFunction;
|
1263
|
+
return dbos_executor_1.DBOSExecutor.globalInstance.startTransactionTempWF(func, wfParams, workflowID, funcNum, ...args);
|
1264
|
+
}
|
1265
|
+
if (regOP.stepConfig) {
|
1266
|
+
const func = regOP.registeredFunction;
|
1267
|
+
return dbos_executor_1.DBOSExecutor.globalInstance.startStepTempWF(func, wfParams, workflowID, funcNum, ...args);
|
1268
|
+
}
|
1269
|
+
throw new error_1.DBOSNotRegisteredError(regOP.name, `${regOP.name} is not a registered DBOS workflow, step, or transaction function`);
|
1270
|
+
}
|
1271
|
+
}
|
1272
|
+
static #getWorkflowInvoker(registration, config) {
|
1273
|
+
registration.setWorkflowConfig(config ?? {});
|
1274
|
+
const invoker = async function (...rawArgs) {
|
1275
|
+
const handle = await DBOS.#invokeWorkflow(this, registration, rawArgs);
|
1276
|
+
return await handle.getResult();
|
1277
|
+
};
|
1278
|
+
(0, decorators_1.registerFunctionWrapper)(invoker, registration);
|
1279
|
+
Object.defineProperty(invoker, 'name', {
|
1280
|
+
value: registration.name,
|
1281
|
+
});
|
1282
|
+
return invoker;
|
1283
|
+
}
|
1326
1284
|
/**
|
1327
1285
|
* Decorator designating a method as a DBOS transaction, making SQL clients available.
|
1328
1286
|
* A durable execution checkpoint will be applied to to the underlying database transaction
|
@@ -1340,7 +1298,7 @@ class DBOS {
|
|
1340
1298
|
}
|
1341
1299
|
else {
|
1342
1300
|
inst = this;
|
1343
|
-
if (!(
|
1301
|
+
if (!(inst instanceof _2.ConfiguredInstance)) {
|
1344
1302
|
throw new error_1.DBOSInvalidWorkflowTransitionError('Attempt to call a `transaction` function on an object that is not a `ConfiguredInstance`');
|
1345
1303
|
}
|
1346
1304
|
}
|
@@ -1466,7 +1424,7 @@ class DBOS {
|
|
1466
1424
|
}
|
1467
1425
|
else {
|
1468
1426
|
inst = this;
|
1469
|
-
if (!(
|
1427
|
+
if (!(inst instanceof _2.ConfiguredInstance)) {
|
1470
1428
|
throw new error_1.DBOSInvalidWorkflowTransitionError('Attempt to call a `step` function on an object that is not a `ConfiguredInstance`');
|
1471
1429
|
}
|
1472
1430
|
}
|
@@ -1519,6 +1477,65 @@ class DBOS {
|
|
1519
1477
|
}
|
1520
1478
|
return decorator;
|
1521
1479
|
}
|
1480
|
+
/**
|
1481
|
+
* Create a check pointed DBOS step function from a provided function
|
1482
|
+
* Similar to the DBOS.step decorator, but without requiring a decorator
|
1483
|
+
* A durable checkpoint will be made after the step completes
|
1484
|
+
* This ensures "at least once" execution of the step, and that the step will not
|
1485
|
+
* be executed again once the checkpoint is recorded
|
1486
|
+
* @param func - The function to register as a step
|
1487
|
+
* @param config - Configuration information for the step, particularly the retry policy
|
1488
|
+
* @param config.name - The name of the step; if not provided, the function name will be used
|
1489
|
+
*/
|
1490
|
+
static registerStep(func, config = {}) {
|
1491
|
+
const name = config.name ?? func.name;
|
1492
|
+
const invokeWrapper = async function (...rawArgs) {
|
1493
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
1494
|
+
const inst = this;
|
1495
|
+
if (DBOS.isWithinWorkflow()) {
|
1496
|
+
if (DBOS.isInTransaction()) {
|
1497
|
+
throw new error_1.DBOSInvalidWorkflowTransitionError('Invalid call to a `step` function from within a `transaction`');
|
1498
|
+
}
|
1499
|
+
if (DBOS.isInStep()) {
|
1500
|
+
// There should probably be checks here about the compatibility of the StepConfig...
|
1501
|
+
return func.call(this, ...rawArgs);
|
1502
|
+
}
|
1503
|
+
const wfctx = (0, context_1.assertCurrentWorkflowContext)();
|
1504
|
+
return await dbos_executor_1.DBOSExecutor.globalInstance.callStepFunction(func, name, config, inst ?? null, wfctx, ...rawArgs);
|
1505
|
+
}
|
1506
|
+
if ((0, context_1.getNextWFID)(undefined)) {
|
1507
|
+
throw new error_1.DBOSInvalidWorkflowTransitionError(`Invalid call to step '${name}' outside of a workflow; with directive to start a workflow.`);
|
1508
|
+
}
|
1509
|
+
return func.call(this, ...rawArgs);
|
1510
|
+
};
|
1511
|
+
Object.defineProperty(invokeWrapper, 'name', { value: name });
|
1512
|
+
return invokeWrapper;
|
1513
|
+
}
|
1514
|
+
/**
|
1515
|
+
* Run the enclosed `callback` as a checkpointed step within a DBOS workflow
|
1516
|
+
* @param callback - function containing code to run
|
1517
|
+
* @param config - Configuration information for the step, particularly the retry policy
|
1518
|
+
* @param config.name - The name of the step; if not provided, the function name will be used
|
1519
|
+
* @returns - result (either obtained from invoking function, or retrieved if run before)
|
1520
|
+
*/
|
1521
|
+
static runStep(func, config = {}) {
|
1522
|
+
const name = config.name ?? func.name;
|
1523
|
+
if (DBOS.isWithinWorkflow()) {
|
1524
|
+
if (DBOS.isInTransaction()) {
|
1525
|
+
throw new error_1.DBOSInvalidWorkflowTransitionError('Invalid call to a runStep from within a `transaction`');
|
1526
|
+
}
|
1527
|
+
if (DBOS.isInStep()) {
|
1528
|
+
// There should probably be checks here about the compatibility of the StepConfig...
|
1529
|
+
return func();
|
1530
|
+
}
|
1531
|
+
const wfctx = (0, context_1.assertCurrentWorkflowContext)();
|
1532
|
+
return dbos_executor_1.DBOSExecutor.globalInstance.callStepFunction(func, name, config, null, wfctx);
|
1533
|
+
}
|
1534
|
+
if ((0, context_1.getNextWFID)(undefined)) {
|
1535
|
+
throw new error_1.DBOSInvalidWorkflowTransitionError(`Invalid call to step '${name}' outside of a workflow; with directive to start a workflow.`);
|
1536
|
+
}
|
1537
|
+
return func();
|
1538
|
+
}
|
1522
1539
|
/** Decorator indicating that the method is the target of HTTP GET operations for `url` */
|
1523
1540
|
static getApi(url) {
|
1524
1541
|
return httpApiDec(handlerTypes_1.APITypes.GET, url);
|
@@ -1589,7 +1606,7 @@ class DBOS {
|
|
1589
1606
|
* Register a middleware provider
|
1590
1607
|
*/
|
1591
1608
|
static registerMiddlewareInstaller(mwp) {
|
1592
|
-
(0, decorators_1.
|
1609
|
+
(0, decorators_1.registerMiddlewareInstaller)(mwp);
|
1593
1610
|
}
|
1594
1611
|
/**
|
1595
1612
|
* Register information to be associated with a DBOS class
|