@dbos-inc/dbos-sdk 2.9.9-preview → 2.9.17-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 +14 -17
- package/dist/src/dbos-executor.d.ts.map +1 -1
- package/dist/src/dbos-executor.js +74 -174
- 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 +38 -12
- 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.
|
@@ -1554,13 +1491,16 @@ class DBOSExecutor {
|
|
1554
1491
|
}
|
1555
1492
|
}
|
1556
1493
|
async executeWorkflowUUID(workflowID, startNewWorkflow = false) {
|
1557
|
-
// TODO: remove call to getWorkflowInputs after #871 is merged
|
1558
1494
|
const wfStatus = await this.systemDatabase.getWorkflowStatus(workflowID);
|
1559
|
-
|
1560
|
-
|
1495
|
+
if (!wfStatus) {
|
1496
|
+
this.logger.error(`Failed to find workflow status for workflowUUID: ${workflowID}`);
|
1497
|
+
throw new error_1.DBOSError(`Failed to find workflow status for workflow UUID: ${workflowID}`);
|
1498
|
+
}
|
1499
|
+
if (!wfStatus?.input) {
|
1561
1500
|
this.logger.error(`Failed to find inputs for workflowUUID: ${workflowID}`);
|
1562
1501
|
throw new error_1.DBOSError(`Failed to find inputs for workflow UUID: ${workflowID}`);
|
1563
1502
|
}
|
1503
|
+
const inputs = utils_1.DBOSJSON.parse(wfStatus.input);
|
1564
1504
|
const parentCtx = this.#getRecoveryContext(workflowID, wfStatus);
|
1565
1505
|
const { wfInfo, configuredInst } = this.getWorkflowInfoByStatus(wfStatus);
|
1566
1506
|
// If starting a new workflow, assign a new UUID. Otherwise, use the workflow's original UUID.
|
@@ -1572,9 +1512,7 @@ class DBOSExecutor {
|
|
1572
1512
|
configuredInstance: configuredInst,
|
1573
1513
|
queueName: wfStatus.queueName,
|
1574
1514
|
executeWorkflow: true,
|
1575
|
-
},
|
1576
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
1577
|
-
...inputs);
|
1515
|
+
}, ...inputs);
|
1578
1516
|
}
|
1579
1517
|
// Should be temporary workflows. Parse the name of the workflow.
|
1580
1518
|
const wfName = wfStatus.workflowName;
|
@@ -1596,9 +1534,7 @@ class DBOSExecutor {
|
|
1596
1534
|
configuredInstance: clsInst,
|
1597
1535
|
queueName: wfStatus.queueName,
|
1598
1536
|
executeWorkflow: true,
|
1599
|
-
}, undefined, undefined,
|
1600
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
1601
|
-
...inputs);
|
1537
|
+
}, undefined, undefined, ...inputs);
|
1602
1538
|
}
|
1603
1539
|
else if (nameArr[1] === exports.TempWorkflowType.step) {
|
1604
1540
|
const { commInfo, clsInst } = this.getStepInfoByNames(wfStatus.workflowClassName, nameArr[2], wfStatus.workflowConfigName);
|
@@ -1612,9 +1548,7 @@ class DBOSExecutor {
|
|
1612
1548
|
configuredInstance: clsInst,
|
1613
1549
|
queueName: wfStatus.queueName, // Probably null
|
1614
1550
|
executeWorkflow: true,
|
1615
|
-
}, undefined, undefined,
|
1616
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
1617
|
-
...inputs);
|
1551
|
+
}, undefined, undefined, ...inputs);
|
1618
1552
|
}
|
1619
1553
|
else if (nameArr[1] === exports.TempWorkflowType.send) {
|
1620
1554
|
temp_workflow = async (ctxt, ...args) => {
|
@@ -1626,9 +1560,7 @@ class DBOSExecutor {
|
|
1626
1560
|
tempWfType: exports.TempWorkflowType.send,
|
1627
1561
|
queueName: wfStatus.queueName,
|
1628
1562
|
executeWorkflow: true,
|
1629
|
-
},
|
1630
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
1631
|
-
...inputs);
|
1563
|
+
}, ...inputs);
|
1632
1564
|
}
|
1633
1565
|
else {
|
1634
1566
|
this.logger.error(`Unrecognized temporary workflow! UUID ${workflowID}, name ${wfName}`);
|
@@ -1654,7 +1586,6 @@ class DBOSExecutor {
|
|
1654
1586
|
async cancelWorkflow(workflowID) {
|
1655
1587
|
await this.systemDatabase.cancelWorkflow(workflowID);
|
1656
1588
|
this.logger.info(`Cancelling workflow ${workflowID}`);
|
1657
|
-
this.workflowCancellationMap.set(workflowID, true);
|
1658
1589
|
}
|
1659
1590
|
async getWorkflowSteps(workflowID) {
|
1660
1591
|
const outputs = await this.systemDatabase.getAllOperationResults(workflowID);
|
@@ -1668,15 +1599,7 @@ class DBOSExecutor {
|
|
1668
1599
|
};
|
1669
1600
|
});
|
1670
1601
|
}
|
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
1602
|
async resumeWorkflow(workflowID) {
|
1679
|
-
this.workflowCancellationMap.delete(workflowID);
|
1680
1603
|
await this.systemDatabase.resumeWorkflow(workflowID);
|
1681
1604
|
}
|
1682
1605
|
logRegisteredHTTPUrls() {
|
@@ -1722,30 +1645,7 @@ class DBOSExecutor {
|
|
1722
1645
|
if (DBOSExecutor.internalQueue !== undefined) {
|
1723
1646
|
return;
|
1724
1647
|
}
|
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
|
-
};
|
1648
|
+
DBOSExecutor.internalQueue = new wfqueue_1.WorkflowQueue(utils_1.INTERNAL_QUEUE_NAME, {});
|
1749
1649
|
}
|
1750
1650
|
}
|
1751
1651
|
exports.DBOSExecutor = DBOSExecutor;
|