Skip to content

Commit c3ac968

Browse files
committed
Support edge cases for sessionless transactions
1 parent 10af376 commit c3ac968

File tree

5 files changed

+571
-258
lines changed

5 files changed

+571
-258
lines changed

lib/connection.js

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ class Connection extends EventEmitter {
110110
options.connection = this;
111111
if (options.keepInStmtCache === undefined)
112112
options.keepInStmtCache = true;
113-
if (options.suspendOnSuccess == undefined)
113+
if (options.suspendOnSuccess === undefined)
114114
options.suspendOnSuccess = false;
115115
settings.addToOptions(options,
116116
"autoCommit",
@@ -720,11 +720,12 @@ class Connection extends EventEmitter {
720720
// If transactionId wasn't provided a random-generated transactionId will be
721721
// used and returned.
722722
//---------------------------------------------------------------------------
723-
async beginSessionlessTransaction(options) {
723+
async beginSessionlessTransaction(options = {}) {
724+
errors.assertArgCount(arguments, 0, 1);
724725
errors.assertParamValue(nodbUtil.isObject(options), 1);
725-
if (options.transactionId != undefined)
726-
errors.assertParamValue(
727-
nodbUtil.isTransactionId(options.transactionId), 1);
726+
if (options.transactionId !== undefined)
727+
errors.assertParamPropValue(
728+
nodbUtil.isTransactionId(options.transactionId), 1, 'transactionId');
728729
errors.assertParamPropUnsignedIntNonZero(options, 1, 'timeout');
729730
errors.assertParamPropBool(options, 1, 'deferRoundTrip');
730731
const normalizedTransactionId =
@@ -1458,14 +1459,14 @@ class Connection extends EventEmitter {
14581459
//
14591460
// Resume an existing sessionlesss transaction using given transactionId
14601461
//---------------------------------------------------------------------------
1461-
async resumeSessionlessTransaction(options) {
1462-
errors.assertParamValue(nodbUtil.isObject(options), 1);
1463-
errors.assertParamPropUnsignedInt(options, 1, 'timeout');
1464-
errors.assertParamPropBool(options, 1, 'deferRoundTrip');
1465-
errors.assertParamValue(
1466-
nodbUtil.isTransactionId(options.transactionId), 1);
1462+
async resumeSessionlessTransaction(transactionId, options = {}) {
1463+
errors.assertArgCount(arguments, 1, 2);
1464+
errors.assertParamValue(nodbUtil.isTransactionId(transactionId), 1);
1465+
errors.assertParamValue(nodbUtil.isObject(options), 2);
1466+
errors.assertParamPropUnsignedInt(options, 2, 'timeout');
1467+
errors.assertParamPropBool(options, 2, 'deferRoundTrip');
14671468
const normalizedTransactionId =
1468-
nodbUtil.normalizeTransactionId(options.transactionId);
1469+
nodbUtil.normalizeTransactionId(transactionId);
14691470
const {timeout = 60, deferRoundTrip = false} = options;
14701471
await this._impl.startSessionlessTransaction(normalizedTransactionId,
14711472
timeout, constants.TPC_BEGIN_RESUME, deferRoundTrip);
@@ -1592,6 +1593,7 @@ class Connection extends EventEmitter {
15921593
// Suspend any active sessionless transaction immediately
15931594
//---------------------------------------------------------------------------
15941595
async suspendSessionlessTransaction() {
1596+
errors.assertArgCount(arguments, 0, 0);
15951597
errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
15961598
await this._impl.suspendSessionlessTransaction();
15971599
}

lib/errors.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,7 @@ messages.set(ERR_INVALID_TPC_END_FLAGS, // NJS-151
500500
messages.set(ERR_UNKNOWN_TRANSACTION_STATE, // NJS-152
501501
'internal error: unknown transaction state {state} in Two Phase Commit');
502502
messages.set(ERR_INVALID_TRANSACTION_SIZE, // NJS-153
503-
'size of the transaction ID is %d and cannot exceed 64');
503+
'size of the transaction ID must be non-zero and must not exceed 64. Its current size is %d.');
504504
messages.set(ERR_INVALID_BRANCH_SIZE, // NJS-154
505505
'size of the branch ID is %d and cannot exceed 64');
506506
messages.set(ERR_OPERATION_NOT_SUPPORTED_ON_BFILE, // NJS-155

lib/util.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -473,13 +473,13 @@ function isTransactionId(value) {
473473
//---------------------------------------------------------------------------
474474
function normalizeTransactionId(value) {
475475
let normalizedTransactionId = value;
476-
if (!normalizedTransactionId)
476+
if (normalizedTransactionId === undefined)
477477
normalizedTransactionId = crypto.randomUUID();
478478
if (typeof normalizedTransactionId === 'string') {
479479
normalizedTransactionId = Buffer.from(normalizedTransactionId);
480-
if (normalizedTransactionId.length > 64)
481-
errors.throwErr(errors.ERR_INVALID_TRANSACTION_SIZE,
482-
normalizedTransactionId.length);
480+
const len = normalizedTransactionId.length;
481+
if ((len === 0) || (len > 64))
482+
errors.throwErr(errors.ERR_INVALID_TRANSACTION_SIZE, len);
483483
}
484484
return normalizedTransactionId;
485485
}

test/list.txt

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6306,21 +6306,42 @@ oracledb.OUT_FORMAT_OBJECT and resultSet = true
63066306
315.1 Testing maxLifetimeSession on conn release
63076307
315.2 Testing maxLifetimeSession on conn acquire
63086308
316. sessionless.js
6309-
316.1 Sessionless Functions
6310-
316.1.1 Test server procedures
6311-
316.1.2 Test Client APIs
6312-
316.1.3 transaction timeout behavior
6313-
316.1.4 error handling during sessionless transaction
6314-
316.1.5 multiple concurrent sessionless transactions
6315-
316.1.6 different GTRID formats
6316-
316.1.7 with savepoints
6317-
316.1.8 sessionless transactions with connection pool
6318-
316.1.9 mixing server and client methods
6319-
316.1.10 resuming without suspnding current txn
6320-
316.1.11 suspendOnSuccess error
6321-
316.1.12 sessionless transaction with large operations
6322-
316.1.13 transaction behavior with some DDL operation
6323-
316.1.14 zero timeout behavior
6324-
316.1.15 retrieve GTRID of active sessionless transaction
6325-
316.1.16 Checking behaviour with XA transactions
6326-
316.1.17 Behaviour with local transactions
6309+
316.1 Server and Client API Integration
6310+
316.1.1 test server procedures
6311+
316.1.2 mixing server and client methods
6312+
316.1.3 suspendOnSuccess behaviour
6313+
316.2 Basic Client API Operations
6314+
316.2.1 test client APIs
6315+
316.2.2 resuming without suspending current txn
6316+
316.2.3 retrieve transactionId of active sessionless transaction
6317+
316.2.4 suspend without active sessionless transaction
6318+
316.3 Multiple Concurrent Transactions
6319+
316.3.1 multiple concurrent sessionless transactions
6320+
316.3.2 duplicate transactionId across different connections
6321+
316.3.3 nested transaction operations
6322+
316.3.4 auto-generated transactionId uniqueness
6323+
316.4 Connection Pool Operations
6324+
316.4.1 sessionless transactions with connection pool
6325+
316.5 Timeout and Error Handling
6326+
316.5.1 transaction timeout behavior
6327+
316.5.2 error handling during sessionless transaction
6328+
316.5.3 zero timeout behavior
6329+
316.5.4 resume non-existent transactionId
6330+
316.5.5 maximum timeout value behavior
6331+
316.5.6 negative timeout values
6332+
316.6 Transaction ID Validation
6333+
316.6.1 different transactionId formats
6334+
316.6.2 empty transactionId behavior
6335+
316.6.3 unicode characters in transactionId
6336+
316.6.4 unicode transaction ID with special Oracle characters
6337+
316.6.5 white-space only transactionId
6338+
316.7 Advanced Database Operations
6339+
316.7.1 with savepoints
6340+
316.7.2 sessionless transaction with large operations
6341+
316.7.3 transaction behavior with some DDL operation
6342+
316.7.4 transaction with very long string data
6343+
316.7.5 suspendOnSuccess with executeMany
6344+
316.7.6 suspendOnSuccess with executeMany and bindDefs
6345+
316.8 other Transaction Types
6346+
316.8.1 checking behaviour with XA transactions
6347+
316.8.2 checking behaviour with local transactions

0 commit comments

Comments
 (0)