@dbos-inc/dbos-sdk 2.9.9-preview → 2.9.18-preview
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/client.d.ts +12 -1
- package/dist/src/client.d.ts.map +1 -1
- package/dist/src/client.js +28 -2
- package/dist/src/client.js.map +1 -1
- package/dist/src/conductor/conductor.d.ts.map +1 -1
- package/dist/src/conductor/conductor.js +26 -11
- package/dist/src/conductor/conductor.js.map +1 -1
- package/dist/src/conductor/protocol.d.ts +20 -4
- package/dist/src/conductor/protocol.d.ts.map +1 -1
- package/dist/src/conductor/protocol.js +23 -4
- package/dist/src/conductor/protocol.js.map +1 -1
- package/dist/src/dbos-executor.d.ts +15 -18
- package/dist/src/dbos-executor.d.ts.map +1 -1
- package/dist/src/dbos-executor.js +84 -182
- package/dist/src/dbos-executor.js.map +1 -1
- package/dist/src/dbos-runtime/cli.d.ts.map +1 -1
- package/dist/src/dbos-runtime/cli.js +87 -15
- package/dist/src/dbos-runtime/cli.js.map +1 -1
- package/dist/src/dbos-runtime/workflow_management.d.ts +13 -13
- package/dist/src/dbos-runtime/workflow_management.d.ts.map +1 -1
- package/dist/src/dbos-runtime/workflow_management.js +90 -108
- package/dist/src/dbos-runtime/workflow_management.js.map +1 -1
- package/dist/src/dbos.d.ts +29 -11
- package/dist/src/dbos.d.ts.map +1 -1
- package/dist/src/dbos.js +53 -36
- package/dist/src/dbos.js.map +1 -1
- package/dist/src/error.d.ts +11 -6
- package/dist/src/error.d.ts.map +1 -1
- package/dist/src/error.js +28 -17
- package/dist/src/error.js.map +1 -1
- package/dist/src/eventreceiver.d.ts +13 -8
- package/dist/src/eventreceiver.d.ts.map +1 -1
- package/dist/src/httpServer/server.d.ts.map +1 -1
- package/dist/src/httpServer/server.js +40 -15
- package/dist/src/httpServer/server.js.map +1 -1
- package/dist/src/scheduler/scheduler.js +1 -1
- package/dist/src/scheduler/scheduler.js.map +1 -1
- package/dist/src/system_database.d.ts +68 -59
- package/dist/src/system_database.d.ts.map +1 -1
- package/dist/src/system_database.js +715 -434
- package/dist/src/system_database.js.map +1 -1
- package/dist/src/workflow.d.ts +8 -0
- package/dist/src/workflow.d.ts.map +1 -1
- package/dist/src/workflow.js +7 -38
- package/dist/src/workflow.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
@@ -53,6 +53,7 @@ const wfqueue_1 = require("./wfqueue");
|
|
53
53
|
const debugpoint_1 = require("./debugpoint");
|
54
54
|
const scheduler_1 = require("./scheduler/scheduler");
|
55
55
|
const crypto = __importStar(require("crypto"));
|
56
|
+
const workflow_management_1 = require("./dbos-runtime/workflow_management");
|
56
57
|
exports.dbosNull = {};
|
57
58
|
function isDeprecatedDBOSConfig(config) {
|
58
59
|
const isDeprecated = config.poolConfig !== undefined ||
|
@@ -114,8 +115,6 @@ class DBOSExecutor {
|
|
114
115
|
stepInfoMap = new Map();
|
115
116
|
procedureInfoMap = new Map();
|
116
117
|
registeredOperations = [];
|
117
|
-
pendingWorkflowMap = new Map(); // Map from workflowUUID to workflow promise
|
118
|
-
workflowCancellationMap = new Map(); // Map from workflowUUID to its cancellation status.
|
119
118
|
telemetryCollector;
|
120
119
|
static defaultNotificationTimeoutSec = 60;
|
121
120
|
debugMode;
|
@@ -398,10 +397,7 @@ class DBOSExecutor {
|
|
398
397
|
}
|
399
398
|
async destroy() {
|
400
399
|
try {
|
401
|
-
|
402
|
-
this.logger.info('Waiting for pending workflows to finish.');
|
403
|
-
await Promise.allSettled(this.pendingWorkflowMap.values());
|
404
|
-
}
|
400
|
+
await this.systemDatabase.awaitRunningWorkflows();
|
405
401
|
await this.systemDatabase.destroy();
|
406
402
|
if (this.userDatabase) {
|
407
403
|
await this.userDatabase.destroy();
|
@@ -522,11 +518,11 @@ class DBOSExecutor {
|
|
522
518
|
}
|
523
519
|
// TODO: getProcedureInfoByNames??
|
524
520
|
static reviveResultOrError(r, success) {
|
525
|
-
if (success === true || !r.
|
526
|
-
return utils_1.DBOSJSON.parse(r.
|
521
|
+
if (success === true || !r.error) {
|
522
|
+
return utils_1.DBOSJSON.parse(r.output ?? null);
|
527
523
|
}
|
528
524
|
else {
|
529
|
-
throw (0, serialize_error_1.deserializeError)(utils_1.DBOSJSON.parse(r.
|
525
|
+
throw (0, serialize_error_1.deserializeError)(utils_1.DBOSJSON.parse(r.error));
|
530
526
|
}
|
531
527
|
}
|
532
528
|
async workflow(wf, params, ...args) {
|
@@ -534,7 +530,7 @@ class DBOSExecutor {
|
|
534
530
|
}
|
535
531
|
// If callerUUID and functionID are set, it means the workflow is invoked from within a workflow.
|
536
532
|
async internalWorkflow(wf, params, callerID, callerFunctionID, ...args) {
|
537
|
-
const workflowID = params.workflowUUID ? params.workflowUUID :
|
533
|
+
const workflowID = params.workflowUUID ? params.workflowUUID : (0, node_crypto_1.randomUUID)();
|
538
534
|
const presetID = params.workflowUUID ? true : false;
|
539
535
|
const wInfo = this.getWorkflowInfo(wf);
|
540
536
|
if (wInfo === undefined) {
|
@@ -569,34 +565,31 @@ class DBOSExecutor {
|
|
569
565
|
// Synchronously set the workflow's status to PENDING and record workflow inputs.
|
570
566
|
// We have to do it for all types of workflows because operation_outputs table has a foreign key constraint on workflow status table.
|
571
567
|
if (this.isDebugging) {
|
572
|
-
// TODO: remove call to getWorkflowInputs after #871 is merged
|
573
568
|
const wfStatus = await this.systemDatabase.getWorkflowStatus(workflowID);
|
574
|
-
|
575
|
-
if (!wfStatus || !wfInputs) {
|
569
|
+
if (!wfStatus) {
|
576
570
|
throw new error_1.DBOSDebuggerError(`Failed to find inputs for workflow UUID ${workflowID}`);
|
577
571
|
}
|
578
572
|
// Make sure we use the same input.
|
579
|
-
if (utils_1.DBOSJSON.stringify(args) !==
|
580
|
-
throw new error_1.DBOSDebuggerError(`Detected different inputs for workflow UUID ${workflowID}.\n Received: ${utils_1.DBOSJSON.stringify(args)}\n Original: ${
|
573
|
+
if (utils_1.DBOSJSON.stringify(args) !== wfStatus.input) {
|
574
|
+
throw new error_1.DBOSDebuggerError(`Detected different inputs for workflow UUID ${workflowID}.\n Received: ${utils_1.DBOSJSON.stringify(args)}\n Original: ${wfStatus.input}`);
|
581
575
|
}
|
582
576
|
status = wfStatus.status;
|
583
577
|
}
|
584
578
|
else {
|
585
579
|
// TODO: Make this transactional (and with the queue step below)
|
586
580
|
if (callerFunctionID !== undefined && callerID !== undefined) {
|
587
|
-
const
|
588
|
-
if (
|
589
|
-
return new workflow_1.RetrievedHandle(this.systemDatabase,
|
581
|
+
const result = await this.systemDatabase.getOperationResultAndThrowIfCancelled(callerID, callerFunctionID);
|
582
|
+
if (result) {
|
583
|
+
return new workflow_1.RetrievedHandle(this.systemDatabase, result.childWorkflowID, callerID, callerFunctionID);
|
590
584
|
}
|
591
585
|
}
|
592
|
-
const ires = await this.systemDatabase.initWorkflowStatus(internalStatus, args, wCtxt.maxRecoveryAttempts);
|
586
|
+
const ires = await this.systemDatabase.initWorkflowStatus(internalStatus, utils_1.DBOSJSON.stringify(args), wCtxt.maxRecoveryAttempts);
|
593
587
|
if (callerFunctionID !== undefined && callerID !== undefined) {
|
594
|
-
await this.systemDatabase.recordOperationResult(callerID, callerFunctionID, {
|
595
|
-
|
596
|
-
|
597
|
-
}, true);
|
588
|
+
await this.systemDatabase.recordOperationResult(callerID, callerFunctionID, internalStatus.workflowName, true, {
|
589
|
+
childWorkflowID: workflowID,
|
590
|
+
});
|
598
591
|
}
|
599
|
-
args = ires.
|
592
|
+
args = utils_1.DBOSJSON.parse(ires.serializedInputs);
|
600
593
|
status = ires.status;
|
601
594
|
await (0, debugpoint_1.debugTriggerPoint)(debugpoint_1.DEBUG_TRIGGER_WORKFLOW_ENQUEUE);
|
602
595
|
}
|
@@ -637,7 +630,7 @@ class DBOSExecutor {
|
|
637
630
|
wCtxt.span.setStatus({ code: api_1.SpanStatusCode.OK });
|
638
631
|
}
|
639
632
|
catch (err) {
|
640
|
-
if (err instanceof error_1.
|
633
|
+
if (err instanceof error_1.DBOSWorkflowConflictError) {
|
641
634
|
// Retrieve the handle and wait for the result.
|
642
635
|
const retrievedHandle = this.retrieveWorkflow(workflowID);
|
643
636
|
result = await retrievedHandle.getResult();
|
@@ -683,16 +676,7 @@ class DBOSExecutor {
|
|
683
676
|
if (this.isDebugging ||
|
684
677
|
(status !== 'SUCCESS' && status !== 'ERROR' && (params.queueName === undefined || params.executeWorkflow))) {
|
685
678
|
const workflowPromise = runWorkflow();
|
686
|
-
|
687
|
-
const awaitWorkflowPromise = workflowPromise
|
688
|
-
.catch((error) => {
|
689
|
-
this.logger.debug('Captured error in awaitWorkflowPromise: ' + error);
|
690
|
-
})
|
691
|
-
.finally(() => {
|
692
|
-
// Remove itself from pending workflow map.
|
693
|
-
this.pendingWorkflowMap.delete(workflowID);
|
694
|
-
});
|
695
|
-
this.pendingWorkflowMap.set(workflowID, awaitWorkflowPromise);
|
679
|
+
this.systemDatabase.registerRunningWorkflow(workflowID, workflowPromise);
|
696
680
|
// Return the normal handle that doesn't capture errors.
|
697
681
|
return new workflow_1.InvokedHandle(this.systemDatabase, workflowPromise, workflowID, wf.name, callerID, callerFunctionID);
|
698
682
|
}
|
@@ -769,7 +753,7 @@ class DBOSExecutor {
|
|
769
753
|
catch (error) {
|
770
754
|
if (isKeyConflict(error)) {
|
771
755
|
// Serialization and primary key conflict (Postgres).
|
772
|
-
throw new error_1.
|
756
|
+
throw new error_1.DBOSWorkflowConflictError(workflowUUID);
|
773
757
|
}
|
774
758
|
else {
|
775
759
|
throw error;
|
@@ -790,7 +774,7 @@ class DBOSExecutor {
|
|
790
774
|
catch (error) {
|
791
775
|
if (isKeyConflict(error)) {
|
792
776
|
// Serialization and primary key conflict (Postgres).
|
793
|
-
throw new error_1.
|
777
|
+
throw new error_1.DBOSWorkflowConflictError(workflowUUID);
|
794
778
|
}
|
795
779
|
else {
|
796
780
|
throw error;
|
@@ -826,9 +810,7 @@ class DBOSExecutor {
|
|
826
810
|
if (txnInfo === undefined) {
|
827
811
|
throw new error_1.DBOSNotRegisteredError(txn.name);
|
828
812
|
}
|
829
|
-
|
830
|
-
throw new error_1.DBOSWorkflowCancelledError(wfCtx.workflowUUID);
|
831
|
-
}
|
813
|
+
await this.systemDatabase.checkIfCanceled(wfCtx.workflowUUID);
|
832
814
|
let retryWaitMillis = 1;
|
833
815
|
const backoffFactor = 1.5;
|
834
816
|
const maxRetryWaitMs = 2000; // Maximum wait 2 seconds.
|
@@ -842,9 +824,7 @@ class DBOSExecutor {
|
|
842
824
|
isolationLevel: txnInfo.config.isolationLevel,
|
843
825
|
}, wfCtx.span);
|
844
826
|
while (true) {
|
845
|
-
|
846
|
-
throw new error_1.DBOSWorkflowCancelledError(wfCtx.workflowUUID);
|
847
|
-
}
|
827
|
+
await this.systemDatabase.checkIfCanceled(wfCtx.workflowUUID);
|
848
828
|
let txn_snapshot = 'invalid';
|
849
829
|
const workflowUUID = wfCtx.workflowUUID;
|
850
830
|
const wrappedTransaction = async (client) => {
|
@@ -978,9 +958,7 @@ class DBOSExecutor {
|
|
978
958
|
if (procInfo === undefined) {
|
979
959
|
throw new error_1.DBOSNotRegisteredError(proc.name);
|
980
960
|
}
|
981
|
-
|
982
|
-
throw new error_1.DBOSWorkflowCancelledError(wfCtx.workflowUUID);
|
983
|
-
}
|
961
|
+
await this.systemDatabase.checkIfCanceled(wfCtx.workflowUUID);
|
984
962
|
const executeLocally = this.isDebugging || (procInfo.config.executeLocally ?? false);
|
985
963
|
const funcId = wfCtx.functionIDGetIncrement();
|
986
964
|
const span = this.tracer.startSpan(proc.name, {
|
@@ -1013,9 +991,7 @@ class DBOSExecutor {
|
|
1013
991
|
const backoffFactor = 1.5;
|
1014
992
|
const maxRetryWaitMs = 2000; // Maximum wait 2 seconds.
|
1015
993
|
while (true) {
|
1016
|
-
|
1017
|
-
throw new error_1.DBOSWorkflowCancelledError(wfCtx.workflowUUID);
|
1018
|
-
}
|
994
|
+
await this.systemDatabase.checkIfCanceled(wfCtx.workflowUUID);
|
1019
995
|
let txn_snapshot = 'invalid';
|
1020
996
|
const wrappedProcedure = async (client) => {
|
1021
997
|
const ctxt = new procedure_1.StoredProcedureContextImpl(client, wfCtx, span, this.logger, funcId, proc.name);
|
@@ -1124,9 +1100,7 @@ class DBOSExecutor {
|
|
1124
1100
|
if (this.isDebugging) {
|
1125
1101
|
throw new error_1.DBOSDebuggerError("Can't invoke stored procedure in debug mode.");
|
1126
1102
|
}
|
1127
|
-
|
1128
|
-
throw new error_1.DBOSWorkflowCancelledError(wfCtx.workflowUUID);
|
1129
|
-
}
|
1103
|
+
await this.systemDatabase.checkIfCanceled(wfCtx.workflowUUID);
|
1130
1104
|
const $jsonCtx = {
|
1131
1105
|
request: wfCtx.request,
|
1132
1106
|
authenticatedUser: wfCtx.authenticatedUser,
|
@@ -1217,9 +1191,7 @@ class DBOSExecutor {
|
|
1217
1191
|
if (commInfo === undefined) {
|
1218
1192
|
throw new error_1.DBOSNotRegisteredError(stepFn.name);
|
1219
1193
|
}
|
1220
|
-
|
1221
|
-
throw new error_1.DBOSWorkflowCancelledError(wfCtx.workflowUUID);
|
1222
|
-
}
|
1194
|
+
await this.systemDatabase.checkIfCanceled(wfCtx.workflowUUID);
|
1223
1195
|
const funcID = wfCtx.functionIDGetIncrement();
|
1224
1196
|
const maxRetryIntervalSec = 3600; // Maximum retry interval: 1 hour
|
1225
1197
|
const span = this.tracer.startSpan(stepFn.name, {
|
@@ -1235,12 +1207,12 @@ class DBOSExecutor {
|
|
1235
1207
|
}, wfCtx.span);
|
1236
1208
|
const ctxt = new step_1.StepContextImpl(wfCtx, funcID, span, this.logger, commInfo.config, stepFn.name);
|
1237
1209
|
// Check if this execution previously happened, returning its original result if it did.
|
1238
|
-
const checkr = await this.systemDatabase.
|
1239
|
-
if (checkr
|
1240
|
-
if (checkr.
|
1241
|
-
throw new error_1.DBOSUnexpectedStepError(ctxt.workflowUUID, ctxt.functionID, ctxt.operationName, checkr.
|
1210
|
+
const checkr = await this.systemDatabase.getOperationResultAndThrowIfCancelled(wfCtx.workflowUUID, ctxt.functionID);
|
1211
|
+
if (checkr) {
|
1212
|
+
if (checkr.functionName !== ctxt.operationName) {
|
1213
|
+
throw new error_1.DBOSUnexpectedStepError(ctxt.workflowUUID, ctxt.functionID, ctxt.operationName, checkr.functionName ?? '?');
|
1242
1214
|
}
|
1243
|
-
const check = DBOSExecutor.reviveResultOrError(checkr
|
1215
|
+
const check = DBOSExecutor.reviveResultOrError(checkr);
|
1244
1216
|
ctxt.span.setAttribute('cached', true);
|
1245
1217
|
ctxt.span.setStatus({ code: api_1.SpanStatusCode.OK });
|
1246
1218
|
this.tracer.endSpan(ctxt.span);
|
@@ -1262,9 +1234,7 @@ class DBOSExecutor {
|
|
1262
1234
|
}
|
1263
1235
|
while (result === exports.dbosNull && numAttempts++ < ctxt.maxAttempts) {
|
1264
1236
|
try {
|
1265
|
-
|
1266
|
-
throw new error_1.DBOSWorkflowCancelledError(wfCtx.workflowUUID);
|
1267
|
-
}
|
1237
|
+
await this.systemDatabase.checkIfCanceled(wfCtx.workflowUUID);
|
1268
1238
|
let cresult;
|
1269
1239
|
if (commInfo.registration.passContext) {
|
1270
1240
|
await (0, context_1.runWithStepContext)(ctxt, numAttempts, async () => {
|
@@ -1318,20 +1288,18 @@ class DBOSExecutor {
|
|
1318
1288
|
if (result === exports.dbosNull) {
|
1319
1289
|
// Record the error, then throw it.
|
1320
1290
|
err = err === exports.dbosNull ? new error_1.DBOSMaxStepRetriesError(stepFn.name, ctxt.maxAttempts, errors) : err;
|
1321
|
-
await this.systemDatabase.recordOperationResult(wfCtx.workflowUUID, ctxt.functionID, {
|
1322
|
-
|
1323
|
-
|
1324
|
-
}, true);
|
1291
|
+
await this.systemDatabase.recordOperationResult(wfCtx.workflowUUID, ctxt.functionID, ctxt.operationName, true, {
|
1292
|
+
error: utils_1.DBOSJSON.stringify((0, serialize_error_1.serializeError)(err)),
|
1293
|
+
});
|
1325
1294
|
ctxt.span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: err.message });
|
1326
1295
|
this.tracer.endSpan(ctxt.span);
|
1327
1296
|
throw err;
|
1328
1297
|
}
|
1329
1298
|
else {
|
1330
1299
|
// Record the execution and return.
|
1331
|
-
await this.systemDatabase.recordOperationResult(wfCtx.workflowUUID, ctxt.functionID, {
|
1332
|
-
|
1333
|
-
|
1334
|
-
}, true);
|
1300
|
+
await this.systemDatabase.recordOperationResult(wfCtx.workflowUUID, ctxt.functionID, ctxt.operationName, true, {
|
1301
|
+
output: utils_1.DBOSJSON.stringify(result),
|
1302
|
+
});
|
1335
1303
|
ctxt.span.setStatus({ code: api_1.SpanStatusCode.OK });
|
1336
1304
|
this.tracer.endSpan(ctxt.span);
|
1337
1305
|
return result;
|
@@ -1355,49 +1323,13 @@ class DBOSExecutor {
|
|
1355
1323
|
async getEvent(workflowUUID, key, timeoutSeconds = DBOSExecutor.defaultNotificationTimeoutSec) {
|
1356
1324
|
return utils_1.DBOSJSON.parse(await this.systemDatabase.getEvent(workflowUUID, key, timeoutSeconds));
|
1357
1325
|
}
|
1358
|
-
async getMaxFunctionID(workflowID) {
|
1359
|
-
const rows = await this.userDatabase.query(`SELECT max(function_id) as max_function_id FROM ${DBOSExecutor.systemDBSchemaName}.transaction_outputs WHERE workflow_uuid=$1`, workflowID);
|
1360
|
-
if (rows.length === 0) {
|
1361
|
-
return 0;
|
1362
|
-
}
|
1363
|
-
else {
|
1364
|
-
return rows[0].max_function_id;
|
1365
|
-
}
|
1366
|
-
}
|
1367
|
-
async cloneWorkflowTransactions(workflowID, forkedWorkflowUUID, startStep) {
|
1368
|
-
const query = `
|
1369
|
-
INSERT INTO dbos.transaction_outputs
|
1370
|
-
(workflow_uuid,
|
1371
|
-
function_id,
|
1372
|
-
output,
|
1373
|
-
error,
|
1374
|
-
txn_id,
|
1375
|
-
txn_snapshot,
|
1376
|
-
function_name)
|
1377
|
-
SELECT $1 AS workflow_uuid,
|
1378
|
-
function_id,
|
1379
|
-
output,
|
1380
|
-
error,
|
1381
|
-
txn_id,
|
1382
|
-
txn_snapshot,
|
1383
|
-
function_name
|
1384
|
-
FROM dbos.transaction_outputs WHERE workflow_uuid= $2 AND function_id < $3`;
|
1385
|
-
await this.userDatabase.query(query, forkedWorkflowUUID, workflowID, startStep);
|
1386
|
-
}
|
1387
|
-
async getMaxStepID(workflowID) {
|
1388
|
-
const maxAppFunctionID = await this.getMaxFunctionID(workflowID);
|
1389
|
-
const maxSystemFunctionID = await this.systemDatabase.getMaxFunctionID(workflowID);
|
1390
|
-
return Math.max(maxAppFunctionID, maxSystemFunctionID);
|
1391
|
-
}
|
1392
1326
|
/**
|
1393
1327
|
* Fork a workflow.
|
1394
1328
|
* The forked workflow will be assigned a new ID.
|
1395
1329
|
*/
|
1396
|
-
|
1397
|
-
const
|
1398
|
-
|
1399
|
-
await this.systemDatabase.forkWorkflow(workflowID, forkedWorkflowID, startStep);
|
1400
|
-
return forkedWorkflowID;
|
1330
|
+
forkWorkflow(workflowID, startStep, options = {}) {
|
1331
|
+
const newWorkflowID = options.newWorkflowID ?? (0, context_1.getNextWFID)(undefined);
|
1332
|
+
return (0, workflow_management_1.forkWorkflow)(this.systemDatabase, this.userDatabase, workflowID, startStep, { ...options, newWorkflowID });
|
1401
1333
|
}
|
1402
1334
|
/**
|
1403
1335
|
* Retrieve a handle for a workflow UUID.
|
@@ -1405,41 +1337,49 @@ class DBOSExecutor {
|
|
1405
1337
|
retrieveWorkflow(workflowID) {
|
1406
1338
|
return new workflow_1.RetrievedHandle(this.systemDatabase, workflowID);
|
1407
1339
|
}
|
1408
|
-
async runAsStep(callback, functionName, workflowID, functionID) {
|
1340
|
+
async runAsStep(callback, functionName, workflowID, functionID, childWfId) {
|
1409
1341
|
if (workflowID !== undefined && functionID !== undefined) {
|
1410
|
-
const
|
1411
|
-
if (
|
1412
|
-
if (
|
1413
|
-
throw new error_1.DBOSUnexpectedStepError(workflowID, functionID, functionName,
|
1342
|
+
const result = await this.systemDatabase.getOperationResultAndThrowIfCancelled(workflowID, functionID);
|
1343
|
+
if (result) {
|
1344
|
+
if (result.functionName !== functionName) {
|
1345
|
+
throw new error_1.DBOSUnexpectedStepError(workflowID, functionID, functionName, result.functionName);
|
1414
1346
|
}
|
1415
|
-
return DBOSExecutor.reviveResultOrError(
|
1347
|
+
return DBOSExecutor.reviveResultOrError(result);
|
1416
1348
|
}
|
1417
1349
|
}
|
1418
1350
|
try {
|
1419
1351
|
const output = await callback();
|
1420
1352
|
if (workflowID !== undefined && functionID !== undefined) {
|
1421
|
-
await this.systemDatabase.recordOperationResult(workflowID, functionID,
|
1353
|
+
await this.systemDatabase.recordOperationResult(workflowID, functionID, functionName, true, {
|
1354
|
+
output: utils_1.DBOSJSON.stringify(output),
|
1355
|
+
childWorkflowID: childWfId,
|
1356
|
+
});
|
1422
1357
|
}
|
1423
1358
|
return output;
|
1424
1359
|
}
|
1425
1360
|
catch (e) {
|
1426
1361
|
if (workflowID !== undefined && functionID !== undefined) {
|
1427
|
-
await this.systemDatabase.recordOperationResult(workflowID, functionID,
|
1362
|
+
await this.systemDatabase.recordOperationResult(workflowID, functionID, functionName, false, {
|
1363
|
+
error: utils_1.DBOSJSON.stringify((0, serialize_error_1.serializeError)(e)),
|
1364
|
+
childWorkflowID: childWfId,
|
1365
|
+
});
|
1428
1366
|
}
|
1429
1367
|
throw e;
|
1430
1368
|
}
|
1431
1369
|
}
|
1432
1370
|
async getWorkflowStatus(workflowID, callerID, callerFN) {
|
1371
|
+
// use sysdb getWorkflowStatus directly in order to support caller ID/FN params
|
1433
1372
|
const status = await this.systemDatabase.getWorkflowStatus(workflowID, callerID, callerFN);
|
1434
|
-
return status ?
|
1373
|
+
return status ? (0, workflow_management_1.toWorkflowStatus)(status) : null;
|
1435
1374
|
}
|
1436
1375
|
async listWorkflows(input) {
|
1437
|
-
|
1438
|
-
return wfs.map((wf) => DBOSExecutor.toWorkflowStatus(wf, true));
|
1376
|
+
return (0, workflow_management_1.listWorkflows)(this.systemDatabase, input);
|
1439
1377
|
}
|
1440
1378
|
async listQueuedWorkflows(input) {
|
1441
|
-
|
1442
|
-
|
1379
|
+
return (0, workflow_management_1.listQueuedWorkflows)(this.systemDatabase, input);
|
1380
|
+
}
|
1381
|
+
async listWorkflowSteps(workflowID) {
|
1382
|
+
return (0, workflow_management_1.listWorkflowSteps)(this.systemDatabase, this.userDatabase, workflowID);
|
1443
1383
|
}
|
1444
1384
|
getWorkflowQueue(input) {
|
1445
1385
|
return this.systemDatabase.getWorkflowQueue(input);
|
@@ -1473,9 +1413,6 @@ class DBOSExecutor {
|
|
1473
1413
|
};
|
1474
1414
|
}
|
1475
1415
|
/* INTERNAL HELPERS */
|
1476
|
-
#generateUUID() {
|
1477
|
-
return (0, node_crypto_1.randomUUID)();
|
1478
|
-
}
|
1479
1416
|
/**
|
1480
1417
|
* A recovery process that by default runs during executor init time.
|
1481
1418
|
* It runs to completion all pending workflows that were executing when the previous executor failed.
|
@@ -1526,7 +1463,7 @@ class DBOSExecutor {
|
|
1526
1463
|
await evtRcvr.initialize(this);
|
1527
1464
|
}
|
1528
1465
|
}
|
1529
|
-
async deactivateEventReceivers() {
|
1466
|
+
async deactivateEventReceivers(stopQueueThread = true) {
|
1530
1467
|
this.logger.debug('Deactivating event receivers');
|
1531
1468
|
for (const evtRcvr of this.eventReceivers || []) {
|
1532
1469
|
try {
|
@@ -1544,23 +1481,28 @@ class DBOSExecutor {
|
|
1544
1481
|
const e = err;
|
1545
1482
|
this.logger.warn(`Error destroying scheduler: ${e.message}`);
|
1546
1483
|
}
|
1547
|
-
|
1548
|
-
|
1549
|
-
|
1550
|
-
|
1551
|
-
|
1552
|
-
|
1553
|
-
|
1484
|
+
if (stopQueueThread) {
|
1485
|
+
try {
|
1486
|
+
wfqueue_1.wfQueueRunner.stop();
|
1487
|
+
await this.wfqEnded;
|
1488
|
+
}
|
1489
|
+
catch (err) {
|
1490
|
+
const e = err;
|
1491
|
+
this.logger.warn(`Error destroying wf queue runner: ${e.message}`);
|
1492
|
+
}
|
1554
1493
|
}
|
1555
1494
|
}
|
1556
1495
|
async executeWorkflowUUID(workflowID, startNewWorkflow = false) {
|
1557
|
-
// TODO: remove call to getWorkflowInputs after #871 is merged
|
1558
1496
|
const wfStatus = await this.systemDatabase.getWorkflowStatus(workflowID);
|
1559
|
-
|
1560
|
-
|
1497
|
+
if (!wfStatus) {
|
1498
|
+
this.logger.error(`Failed to find workflow status for workflowUUID: ${workflowID}`);
|
1499
|
+
throw new error_1.DBOSError(`Failed to find workflow status for workflow UUID: ${workflowID}`);
|
1500
|
+
}
|
1501
|
+
if (!wfStatus?.input) {
|
1561
1502
|
this.logger.error(`Failed to find inputs for workflowUUID: ${workflowID}`);
|
1562
1503
|
throw new error_1.DBOSError(`Failed to find inputs for workflow UUID: ${workflowID}`);
|
1563
1504
|
}
|
1505
|
+
const inputs = utils_1.DBOSJSON.parse(wfStatus.input);
|
1564
1506
|
const parentCtx = this.#getRecoveryContext(workflowID, wfStatus);
|
1565
1507
|
const { wfInfo, configuredInst } = this.getWorkflowInfoByStatus(wfStatus);
|
1566
1508
|
// If starting a new workflow, assign a new UUID. Otherwise, use the workflow's original UUID.
|
@@ -1572,9 +1514,7 @@ class DBOSExecutor {
|
|
1572
1514
|
configuredInstance: configuredInst,
|
1573
1515
|
queueName: wfStatus.queueName,
|
1574
1516
|
executeWorkflow: true,
|
1575
|
-
},
|
1576
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
1577
|
-
...inputs);
|
1517
|
+
}, ...inputs);
|
1578
1518
|
}
|
1579
1519
|
// Should be temporary workflows. Parse the name of the workflow.
|
1580
1520
|
const wfName = wfStatus.workflowName;
|
@@ -1596,9 +1536,7 @@ class DBOSExecutor {
|
|
1596
1536
|
configuredInstance: clsInst,
|
1597
1537
|
queueName: wfStatus.queueName,
|
1598
1538
|
executeWorkflow: true,
|
1599
|
-
}, undefined, undefined,
|
1600
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
1601
|
-
...inputs);
|
1539
|
+
}, undefined, undefined, ...inputs);
|
1602
1540
|
}
|
1603
1541
|
else if (nameArr[1] === exports.TempWorkflowType.step) {
|
1604
1542
|
const { commInfo, clsInst } = this.getStepInfoByNames(wfStatus.workflowClassName, nameArr[2], wfStatus.workflowConfigName);
|
@@ -1612,9 +1550,7 @@ class DBOSExecutor {
|
|
1612
1550
|
configuredInstance: clsInst,
|
1613
1551
|
queueName: wfStatus.queueName, // Probably null
|
1614
1552
|
executeWorkflow: true,
|
1615
|
-
}, undefined, undefined,
|
1616
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
1617
|
-
...inputs);
|
1553
|
+
}, undefined, undefined, ...inputs);
|
1618
1554
|
}
|
1619
1555
|
else if (nameArr[1] === exports.TempWorkflowType.send) {
|
1620
1556
|
temp_workflow = async (ctxt, ...args) => {
|
@@ -1626,9 +1562,7 @@ class DBOSExecutor {
|
|
1626
1562
|
tempWfType: exports.TempWorkflowType.send,
|
1627
1563
|
queueName: wfStatus.queueName,
|
1628
1564
|
executeWorkflow: true,
|
1629
|
-
},
|
1630
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
1631
|
-
...inputs);
|
1565
|
+
}, ...inputs);
|
1632
1566
|
}
|
1633
1567
|
else {
|
1634
1568
|
this.logger.error(`Unrecognized temporary workflow! UUID ${workflowID}, name ${wfName}`);
|
@@ -1654,7 +1588,6 @@ class DBOSExecutor {
|
|
1654
1588
|
async cancelWorkflow(workflowID) {
|
1655
1589
|
await this.systemDatabase.cancelWorkflow(workflowID);
|
1656
1590
|
this.logger.info(`Cancelling workflow ${workflowID}`);
|
1657
|
-
this.workflowCancellationMap.set(workflowID, true);
|
1658
1591
|
}
|
1659
1592
|
async getWorkflowSteps(workflowID) {
|
1660
1593
|
const outputs = await this.systemDatabase.getAllOperationResults(workflowID);
|
@@ -1668,15 +1601,7 @@ class DBOSExecutor {
|
|
1668
1601
|
};
|
1669
1602
|
});
|
1670
1603
|
}
|
1671
|
-
async listWorkflowSteps(workflowID) {
|
1672
|
-
const steps = await this.getWorkflowSteps(workflowID);
|
1673
|
-
const transactions = await this.getTransactions(workflowID);
|
1674
|
-
const merged = [...steps, ...transactions];
|
1675
|
-
merged.sort((a, b) => a.function_id - b.function_id);
|
1676
|
-
return merged;
|
1677
|
-
}
|
1678
1604
|
async resumeWorkflow(workflowID) {
|
1679
|
-
this.workflowCancellationMap.delete(workflowID);
|
1680
1605
|
await this.systemDatabase.resumeWorkflow(workflowID);
|
1681
1606
|
}
|
1682
1607
|
logRegisteredHTTPUrls() {
|
@@ -1722,30 +1647,7 @@ class DBOSExecutor {
|
|
1722
1647
|
if (DBOSExecutor.internalQueue !== undefined) {
|
1723
1648
|
return;
|
1724
1649
|
}
|
1725
|
-
DBOSExecutor.internalQueue = new wfqueue_1.WorkflowQueue(utils_1.INTERNAL_QUEUE_NAME);
|
1726
|
-
}
|
1727
|
-
static toWorkflowStatus(internal, getRequest = true) {
|
1728
|
-
return {
|
1729
|
-
workflowID: internal.workflowUUID,
|
1730
|
-
status: internal.status,
|
1731
|
-
workflowName: internal.workflowName,
|
1732
|
-
workflowClassName: internal.workflowClassName,
|
1733
|
-
workflowConfigName: internal.workflowConfigName,
|
1734
|
-
queueName: internal.queueName,
|
1735
|
-
authenticatedUser: internal.authenticatedUser,
|
1736
|
-
assumedRole: internal.assumedRole,
|
1737
|
-
authenticatedRoles: internal.authenticatedRoles,
|
1738
|
-
input: internal.input ? utils_1.DBOSJSON.parse(internal.input) : undefined,
|
1739
|
-
output: internal.output ? utils_1.DBOSJSON.parse(internal.output ?? null) : undefined,
|
1740
|
-
error: internal.error ? (0, serialize_error_1.deserializeError)(utils_1.DBOSJSON.parse(internal.error)) : undefined,
|
1741
|
-
request: getRequest ? internal.request : undefined,
|
1742
|
-
executorId: internal.executorId,
|
1743
|
-
applicationVersion: internal.applicationVersion,
|
1744
|
-
applicationID: internal.applicationID,
|
1745
|
-
recoveryAttempts: internal.recoveryAttempts,
|
1746
|
-
createdAt: internal.createdAt,
|
1747
|
-
updatedAt: internal.updatedAt,
|
1748
|
-
};
|
1650
|
+
DBOSExecutor.internalQueue = new wfqueue_1.WorkflowQueue(utils_1.INTERNAL_QUEUE_NAME, {});
|
1749
1651
|
}
|
1750
1652
|
}
|
1751
1653
|
exports.DBOSExecutor = DBOSExecutor;
|