@dbos-inc/dbos-sdk 5.3.10-preview → 5.3.12-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/dbos-executor.d.ts.map +1 -1
- package/dist/src/dbos-executor.js +4 -6
- package/dist/src/dbos-executor.js.map +1 -1
- package/dist/src/enqueue_workflow.d.ts.map +1 -1
- package/dist/src/enqueue_workflow.js +3 -0
- package/dist/src/enqueue_workflow.js.map +1 -1
- package/dist/src/sysdb_migrations/internal/migrations.js +1 -1
- package/dist/src/sysdb_migrations/internal/migrations.js.map +1 -1
- package/dist/src/system_database.d.ts +2 -0
- package/dist/src/system_database.d.ts.map +1 -1
- package/dist/src/system_database.js +109 -26
- package/dist/src/system_database.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -387,6 +387,9 @@ function sqlStateLooksRetryable(sqlstate) {
|
|
|
387
387
|
return false;
|
|
388
388
|
if (RETRY_SQLSTATE_CODES.has(sqlstate))
|
|
389
389
|
return true;
|
|
390
|
+
// query_canceled (a statement timeout or an explicit cancel); retrying would undo it
|
|
391
|
+
if (sqlstate === '57014')
|
|
392
|
+
return false;
|
|
390
393
|
const prefix = sqlstate.toString().slice(0, 2);
|
|
391
394
|
return RETRY_SQLSTATE_PREFIXES.has(prefix);
|
|
392
395
|
}
|
|
@@ -692,7 +695,7 @@ class SystemDatabase {
|
|
|
692
695
|
}
|
|
693
696
|
catch (e) {
|
|
694
697
|
await client.query('ROLLBACK').catch(() => { });
|
|
695
|
-
// No `cause`:
|
|
698
|
+
// No `cause`: the typed timeout replaces the driver's query_canceled error.
|
|
696
699
|
throw isStatementTimeout(e) ? new error_1.DBOSQueryTimeoutError(timeoutMs) : e;
|
|
697
700
|
}
|
|
698
701
|
}
|
|
@@ -1244,31 +1247,71 @@ class SystemDatabase {
|
|
|
1244
1247
|
await (0, debugpoint_1.debugTriggerPoint)(debugpoint_1.DEBUG_TRIGGER_STEP_COMMIT);
|
|
1245
1248
|
}
|
|
1246
1249
|
}
|
|
1247
|
-
|
|
1248
|
-
|
|
1250
|
+
/** Checkpoint an operation's failure so a replay re-throws it instead of re-running. */
|
|
1251
|
+
async recordOperationError(workflowID, functionID, functionName, startTimeEpochMs, error, childWorkflowID) {
|
|
1252
|
+
let serialized;
|
|
1249
1253
|
try {
|
|
1250
|
-
await
|
|
1251
|
-
|
|
1252
|
-
|
|
1254
|
+
serialized = await (0, serialization_1.serializeResErrorWithSerializer)(error, this.serializer, this.serializer.name());
|
|
1255
|
+
await (0, serialization_1.deserializeValue)(serialized.serializedValue, serialized.serialization, this.serializer);
|
|
1256
|
+
}
|
|
1257
|
+
catch (serError) {
|
|
1258
|
+
// A checkpoint replay could not load would wedge the workflow; leave it unrecorded so replay re-runs.
|
|
1259
|
+
this.logger.warn(`Not checkpointing ${functionName} failure in workflow ${workflowID}: its error cannot be serialized: ${String(serError)}`);
|
|
1260
|
+
return;
|
|
1261
|
+
}
|
|
1262
|
+
await this.recordOperationResult(workflowID, functionID, functionName, true, startTimeEpochMs, Date.now(), {
|
|
1263
|
+
error: serialized.serializedValue,
|
|
1264
|
+
serialization: serialized.serialization,
|
|
1265
|
+
childWorkflowID,
|
|
1266
|
+
});
|
|
1267
|
+
}
|
|
1268
|
+
async runTransactionalStep(workflowID, functionID, functionName, callback) {
|
|
1269
|
+
const startTime = Date.now();
|
|
1270
|
+
// The latest attempt's callback failure, told apart from a check or checkpoint failure.
|
|
1271
|
+
let callbackError = undefined;
|
|
1272
|
+
const attempt = async () => {
|
|
1273
|
+
callbackError = undefined;
|
|
1274
|
+
const client = await this.connect();
|
|
1275
|
+
try {
|
|
1276
|
+
await client.query('BEGIN ISOLATION LEVEL READ COMMITTED');
|
|
1277
|
+
const existing = await this.#getOperationResultAndThrowIfCancelled(client, workflowID, functionID);
|
|
1278
|
+
if (existing !== undefined) {
|
|
1279
|
+
await client.query('ROLLBACK');
|
|
1280
|
+
return existing;
|
|
1281
|
+
}
|
|
1282
|
+
let output;
|
|
1283
|
+
try {
|
|
1284
|
+
output = await callback(client);
|
|
1285
|
+
}
|
|
1286
|
+
catch (e) {
|
|
1287
|
+
callbackError = e;
|
|
1288
|
+
throw e;
|
|
1289
|
+
}
|
|
1290
|
+
await this.recordOperationResultInternal(client, workflowID, functionID, functionName, true, startTime, Date.now(), {
|
|
1291
|
+
output,
|
|
1292
|
+
});
|
|
1293
|
+
await client.query('COMMIT');
|
|
1294
|
+
await (0, debugpoint_1.debugTriggerPoint)(debugpoint_1.DEBUG_TRIGGER_STEP_COMMIT);
|
|
1295
|
+
return undefined;
|
|
1296
|
+
}
|
|
1297
|
+
catch (e) {
|
|
1253
1298
|
await client.query('ROLLBACK');
|
|
1254
|
-
|
|
1299
|
+
throw e;
|
|
1255
1300
|
}
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
await
|
|
1262
|
-
await (0, debugpoint_1.debugTriggerPoint)(debugpoint_1.DEBUG_TRIGGER_STEP_COMMIT);
|
|
1263
|
-
return undefined;
|
|
1301
|
+
finally {
|
|
1302
|
+
client.release();
|
|
1303
|
+
}
|
|
1304
|
+
};
|
|
1305
|
+
try {
|
|
1306
|
+
return await withDbRetry(attempt);
|
|
1264
1307
|
}
|
|
1265
1308
|
catch (e) {
|
|
1266
|
-
|
|
1309
|
+
// Retries are done and the transaction rolled back, so record the callback's own failure separately.
|
|
1310
|
+
if (e === callbackError) {
|
|
1311
|
+
await this.recordOperationError(workflowID, functionID, functionName, startTime, e);
|
|
1312
|
+
}
|
|
1267
1313
|
throw e;
|
|
1268
1314
|
}
|
|
1269
|
-
finally {
|
|
1270
|
-
client.release();
|
|
1271
|
-
}
|
|
1272
1315
|
}
|
|
1273
1316
|
async checkPatch(workflowID, functionID, patchName, deprecated) {
|
|
1274
1317
|
// Not doing a cancel check at this point.
|
|
@@ -2086,6 +2129,8 @@ class SystemDatabase {
|
|
|
2086
2129
|
async send(workflowID, functionID, destinationID, message, topic, serialization, idempotencyKey) {
|
|
2087
2130
|
topic = topic ?? this.nullTopic;
|
|
2088
2131
|
const messageUUID = idempotencyKey ? `${idempotencyKey}::${destinationID}` : (0, crypto_1.randomUUID)();
|
|
2132
|
+
const startTime = Date.now();
|
|
2133
|
+
let missing;
|
|
2089
2134
|
const client = await this.connect();
|
|
2090
2135
|
try {
|
|
2091
2136
|
await client.query('BEGIN ISOLATION LEVEL READ COMMITTED');
|
|
@@ -2102,7 +2147,7 @@ class SystemDatabase {
|
|
|
2102
2147
|
const err = error;
|
|
2103
2148
|
if (err.code === '23503') {
|
|
2104
2149
|
// Foreign key constraint violation (only expected for the INSERT query)
|
|
2105
|
-
|
|
2150
|
+
missing = new error_1.DBOSNonExistentWorkflowError(`Sent to non-existent destination workflow UUID: ${destinationID}`);
|
|
2106
2151
|
}
|
|
2107
2152
|
else {
|
|
2108
2153
|
throw err;
|
|
@@ -2111,6 +2156,11 @@ class SystemDatabase {
|
|
|
2111
2156
|
finally {
|
|
2112
2157
|
client.release();
|
|
2113
2158
|
}
|
|
2159
|
+
if (missing) {
|
|
2160
|
+
// A missing destination is the send's answer; the transaction has rolled back, so record it separately.
|
|
2161
|
+
await this.recordOperationError(workflowID, functionID, exports.DBOS_FUNCNAME_SEND, startTime, missing);
|
|
2162
|
+
throw missing;
|
|
2163
|
+
}
|
|
2114
2164
|
}
|
|
2115
2165
|
/** Runs on `client` if given, joining its transaction; otherwise on the pool with retries. */
|
|
2116
2166
|
async sendDirect(destinationID, message, topic, serialization, idempotencyKey, client) {
|
|
@@ -3869,6 +3919,9 @@ class SystemDatabase {
|
|
|
3869
3919
|
if (result.functionName !== functionName) {
|
|
3870
3920
|
throw new error_1.DBOSUnexpectedStepError(workflowID, functionID, functionName, result.functionName);
|
|
3871
3921
|
}
|
|
3922
|
+
if (result.error) {
|
|
3923
|
+
throw await (0, serialization_1.deserializeResError)(result.error, result.serialization ?? null, this.serializer);
|
|
3924
|
+
}
|
|
3872
3925
|
return result.output;
|
|
3873
3926
|
}
|
|
3874
3927
|
const output = await func();
|
|
@@ -4089,27 +4142,45 @@ __decorate([
|
|
|
4089
4142
|
__decorate([
|
|
4090
4143
|
dbRetry(),
|
|
4091
4144
|
__metadata("design:type", Function),
|
|
4092
|
-
__metadata("design:paramtypes", [String, Number,
|
|
4145
|
+
__metadata("design:paramtypes", [String, Number, Number, Boolean]),
|
|
4093
4146
|
__metadata("design:returntype", Promise)
|
|
4094
|
-
], SystemDatabase.prototype, "
|
|
4147
|
+
], SystemDatabase.prototype, "getAllOperationResults", null);
|
|
4095
4148
|
__decorate([
|
|
4096
4149
|
dbRetry(),
|
|
4097
4150
|
__metadata("design:type", Function),
|
|
4098
|
-
__metadata("design:paramtypes", [String, Number, String,
|
|
4151
|
+
__metadata("design:paramtypes", [String, Number, String, Boolean, Number, Number, Object]),
|
|
4099
4152
|
__metadata("design:returntype", Promise)
|
|
4100
|
-
], SystemDatabase.prototype, "
|
|
4153
|
+
], SystemDatabase.prototype, "recordOperationResult", null);
|
|
4101
4154
|
__decorate([
|
|
4102
4155
|
dbRetry(),
|
|
4103
4156
|
__metadata("design:type", Function),
|
|
4104
4157
|
__metadata("design:paramtypes", [String, Number, String, Boolean]),
|
|
4105
4158
|
__metadata("design:returntype", Promise)
|
|
4106
4159
|
], SystemDatabase.prototype, "checkPatch", null);
|
|
4160
|
+
__decorate([
|
|
4161
|
+
dbRetry(),
|
|
4162
|
+
__metadata("design:type", Function),
|
|
4163
|
+
__metadata("design:paramtypes", [Array, Boolean]),
|
|
4164
|
+
__metadata("design:returntype", Promise)
|
|
4165
|
+
], SystemDatabase.prototype, "cancelWorkflows", null);
|
|
4107
4166
|
__decorate([
|
|
4108
4167
|
dbRetry(),
|
|
4109
4168
|
__metadata("design:type", Function),
|
|
4110
4169
|
__metadata("design:paramtypes", [String]),
|
|
4111
4170
|
__metadata("design:returntype", Promise)
|
|
4112
4171
|
], SystemDatabase.prototype, "checkIfCanceled", null);
|
|
4172
|
+
__decorate([
|
|
4173
|
+
dbRetry(),
|
|
4174
|
+
__metadata("design:type", Function),
|
|
4175
|
+
__metadata("design:paramtypes", [Array, String]),
|
|
4176
|
+
__metadata("design:returntype", Promise)
|
|
4177
|
+
], SystemDatabase.prototype, "resumeWorkflows", null);
|
|
4178
|
+
__decorate([
|
|
4179
|
+
dbRetry(),
|
|
4180
|
+
__metadata("design:type", Function),
|
|
4181
|
+
__metadata("design:paramtypes", [String, Number]),
|
|
4182
|
+
__metadata("design:returntype", Promise)
|
|
4183
|
+
], SystemDatabase.prototype, "setWorkflowDelay", null);
|
|
4113
4184
|
__decorate([
|
|
4114
4185
|
dbRetry(),
|
|
4115
4186
|
__metadata("design:type", Function),
|
|
@@ -4119,9 +4190,15 @@ __decorate([
|
|
|
4119
4190
|
__decorate([
|
|
4120
4191
|
dbRetry(),
|
|
4121
4192
|
__metadata("design:type", Function),
|
|
4122
|
-
__metadata("design:paramtypes", [String
|
|
4193
|
+
__metadata("design:paramtypes", [String]),
|
|
4123
4194
|
__metadata("design:returntype", Promise)
|
|
4124
|
-
], SystemDatabase.prototype, "
|
|
4195
|
+
], SystemDatabase.prototype, "getWorkflowChildren", null);
|
|
4196
|
+
__decorate([
|
|
4197
|
+
dbRetry(),
|
|
4198
|
+
__metadata("design:type", Function),
|
|
4199
|
+
__metadata("design:paramtypes", [Array, Boolean]),
|
|
4200
|
+
__metadata("design:returntype", Promise)
|
|
4201
|
+
], SystemDatabase.prototype, "deleteWorkflows", null);
|
|
4125
4202
|
__decorate([
|
|
4126
4203
|
dbRetry()
|
|
4127
4204
|
// A missing row normally means the workflow has not been inserted yet, so
|
|
@@ -4218,6 +4295,12 @@ __decorate([
|
|
|
4218
4295
|
__metadata("design:paramtypes", [String]),
|
|
4219
4296
|
__metadata("design:returntype", Promise)
|
|
4220
4297
|
], SystemDatabase.prototype, "getQueuePartitions", null);
|
|
4298
|
+
__decorate([
|
|
4299
|
+
dbRetry(),
|
|
4300
|
+
__metadata("design:type", Function),
|
|
4301
|
+
__metadata("design:paramtypes", [Object]),
|
|
4302
|
+
__metadata("design:returntype", Promise)
|
|
4303
|
+
], SystemDatabase.prototype, "listWorkflows", null);
|
|
4221
4304
|
__decorate([
|
|
4222
4305
|
dbRetry(),
|
|
4223
4306
|
__metadata("design:type", Function),
|