You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
138 lines
5.0 KiB
JavaScript
138 lines
5.0 KiB
JavaScript
2 years ago
|
"use strict";
|
||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||
|
exports.isTransactionCommand = exports.Transaction = exports.TxnState = void 0;
|
||
|
const error_1 = require("./error");
|
||
|
const read_concern_1 = require("./read_concern");
|
||
|
const read_preference_1 = require("./read_preference");
|
||
|
const write_concern_1 = require("./write_concern");
|
||
|
/** @internal */
|
||
|
exports.TxnState = Object.freeze({
|
||
|
NO_TRANSACTION: 'NO_TRANSACTION',
|
||
|
STARTING_TRANSACTION: 'STARTING_TRANSACTION',
|
||
|
TRANSACTION_IN_PROGRESS: 'TRANSACTION_IN_PROGRESS',
|
||
|
TRANSACTION_COMMITTED: 'TRANSACTION_COMMITTED',
|
||
|
TRANSACTION_COMMITTED_EMPTY: 'TRANSACTION_COMMITTED_EMPTY',
|
||
|
TRANSACTION_ABORTED: 'TRANSACTION_ABORTED'
|
||
|
});
|
||
|
const stateMachine = {
|
||
|
[exports.TxnState.NO_TRANSACTION]: [exports.TxnState.NO_TRANSACTION, exports.TxnState.STARTING_TRANSACTION],
|
||
|
[exports.TxnState.STARTING_TRANSACTION]: [
|
||
|
exports.TxnState.TRANSACTION_IN_PROGRESS,
|
||
|
exports.TxnState.TRANSACTION_COMMITTED,
|
||
|
exports.TxnState.TRANSACTION_COMMITTED_EMPTY,
|
||
|
exports.TxnState.TRANSACTION_ABORTED
|
||
|
],
|
||
|
[exports.TxnState.TRANSACTION_IN_PROGRESS]: [
|
||
|
exports.TxnState.TRANSACTION_IN_PROGRESS,
|
||
|
exports.TxnState.TRANSACTION_COMMITTED,
|
||
|
exports.TxnState.TRANSACTION_ABORTED
|
||
|
],
|
||
|
[exports.TxnState.TRANSACTION_COMMITTED]: [
|
||
|
exports.TxnState.TRANSACTION_COMMITTED,
|
||
|
exports.TxnState.TRANSACTION_COMMITTED_EMPTY,
|
||
|
exports.TxnState.STARTING_TRANSACTION,
|
||
|
exports.TxnState.NO_TRANSACTION
|
||
|
],
|
||
|
[exports.TxnState.TRANSACTION_ABORTED]: [exports.TxnState.STARTING_TRANSACTION, exports.TxnState.NO_TRANSACTION],
|
||
|
[exports.TxnState.TRANSACTION_COMMITTED_EMPTY]: [
|
||
|
exports.TxnState.TRANSACTION_COMMITTED_EMPTY,
|
||
|
exports.TxnState.NO_TRANSACTION
|
||
|
]
|
||
|
};
|
||
|
const ACTIVE_STATES = new Set([
|
||
|
exports.TxnState.STARTING_TRANSACTION,
|
||
|
exports.TxnState.TRANSACTION_IN_PROGRESS
|
||
|
]);
|
||
|
const COMMITTED_STATES = new Set([
|
||
|
exports.TxnState.TRANSACTION_COMMITTED,
|
||
|
exports.TxnState.TRANSACTION_COMMITTED_EMPTY,
|
||
|
exports.TxnState.TRANSACTION_ABORTED
|
||
|
]);
|
||
|
/**
|
||
|
* @public
|
||
|
* A class maintaining state related to a server transaction. Internal Only
|
||
|
*/
|
||
|
class Transaction {
|
||
|
/** Create a transaction @internal */
|
||
|
constructor(options) {
|
||
|
options = options ?? {};
|
||
|
this.state = exports.TxnState.NO_TRANSACTION;
|
||
|
this.options = {};
|
||
|
const writeConcern = write_concern_1.WriteConcern.fromOptions(options);
|
||
|
if (writeConcern) {
|
||
|
if (writeConcern.w === 0) {
|
||
|
throw new error_1.MongoTransactionError('Transactions do not support unacknowledged write concern');
|
||
|
}
|
||
|
this.options.writeConcern = writeConcern;
|
||
|
}
|
||
|
if (options.readConcern) {
|
||
|
this.options.readConcern = read_concern_1.ReadConcern.fromOptions(options);
|
||
|
}
|
||
|
if (options.readPreference) {
|
||
|
this.options.readPreference = read_preference_1.ReadPreference.fromOptions(options);
|
||
|
}
|
||
|
if (options.maxCommitTimeMS) {
|
||
|
this.options.maxTimeMS = options.maxCommitTimeMS;
|
||
|
}
|
||
|
// TODO: This isn't technically necessary
|
||
|
this._pinnedServer = undefined;
|
||
|
this._recoveryToken = undefined;
|
||
|
}
|
||
|
/** @internal */
|
||
|
get server() {
|
||
|
return this._pinnedServer;
|
||
|
}
|
||
|
get recoveryToken() {
|
||
|
return this._recoveryToken;
|
||
|
}
|
||
|
get isPinned() {
|
||
|
return !!this.server;
|
||
|
}
|
||
|
/** @returns Whether the transaction has started */
|
||
|
get isStarting() {
|
||
|
return this.state === exports.TxnState.STARTING_TRANSACTION;
|
||
|
}
|
||
|
/**
|
||
|
* @returns Whether this session is presently in a transaction
|
||
|
*/
|
||
|
get isActive() {
|
||
|
return ACTIVE_STATES.has(this.state);
|
||
|
}
|
||
|
get isCommitted() {
|
||
|
return COMMITTED_STATES.has(this.state);
|
||
|
}
|
||
|
/**
|
||
|
* Transition the transaction in the state machine
|
||
|
* @internal
|
||
|
* @param nextState - The new state to transition to
|
||
|
*/
|
||
|
transition(nextState) {
|
||
|
const nextStates = stateMachine[this.state];
|
||
|
if (nextStates && nextStates.includes(nextState)) {
|
||
|
this.state = nextState;
|
||
|
if (this.state === exports.TxnState.NO_TRANSACTION ||
|
||
|
this.state === exports.TxnState.STARTING_TRANSACTION ||
|
||
|
this.state === exports.TxnState.TRANSACTION_ABORTED) {
|
||
|
this.unpinServer();
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
throw new error_1.MongoRuntimeError(`Attempted illegal state transition from [${this.state}] to [${nextState}]`);
|
||
|
}
|
||
|
/** @internal */
|
||
|
pinServer(server) {
|
||
|
if (this.isActive) {
|
||
|
this._pinnedServer = server;
|
||
|
}
|
||
|
}
|
||
|
/** @internal */
|
||
|
unpinServer() {
|
||
|
this._pinnedServer = undefined;
|
||
|
}
|
||
|
}
|
||
|
exports.Transaction = Transaction;
|
||
|
function isTransactionCommand(command) {
|
||
|
return !!(command.commitTransaction || command.abortTransaction);
|
||
|
}
|
||
|
exports.isTransactionCommand = isTransactionCommand;
|
||
|
//# sourceMappingURL=transactions.js.map
|