opusdev/vector-similarity-api
1
1import type { Document } from './bson';2import { MongoRuntimeError, MongoTransactionError } from './error';3import type { CommandOperationOptions } from './operations/command';4import { ReadConcern, type ReadConcernLike } from './read_concern';5import { ReadPreference, type ReadPreferenceLike } from './read_preference';6import type { Server } from './sdam/server';7import { WriteConcern } from './write_concern';8 9/** @internal */10export const TxnState = Object.freeze({11 NO_TRANSACTION: 'NO_TRANSACTION',12 STARTING_TRANSACTION: 'STARTING_TRANSACTION',13 TRANSACTION_IN_PROGRESS: 'TRANSACTION_IN_PROGRESS',14 TRANSACTION_COMMITTED: 'TRANSACTION_COMMITTED',15 TRANSACTION_COMMITTED_EMPTY: 'TRANSACTION_COMMITTED_EMPTY',16 TRANSACTION_ABORTED: 'TRANSACTION_ABORTED'17} as const);18 19/** @internal */20export type TxnState = (typeof TxnState)[keyof typeof TxnState];21 22const stateMachine: { [state in TxnState]: TxnState[] } = {23 [TxnState.NO_TRANSACTION]: [TxnState.NO_TRANSACTION, TxnState.STARTING_TRANSACTION],24 [TxnState.STARTING_TRANSACTION]: [25 TxnState.TRANSACTION_IN_PROGRESS,26 TxnState.TRANSACTION_COMMITTED,27 TxnState.TRANSACTION_COMMITTED_EMPTY,28 TxnState.TRANSACTION_ABORTED29 ],30 [TxnState.TRANSACTION_IN_PROGRESS]: [31 TxnState.TRANSACTION_IN_PROGRESS,32 TxnState.TRANSACTION_COMMITTED,33 TxnState.TRANSACTION_ABORTED34 ],35 [TxnState.TRANSACTION_COMMITTED]: [36 TxnState.TRANSACTION_COMMITTED,37 TxnState.TRANSACTION_COMMITTED_EMPTY,38 TxnState.STARTING_TRANSACTION,39 TxnState.NO_TRANSACTION40 ],41 [TxnState.TRANSACTION_ABORTED]: [TxnState.STARTING_TRANSACTION, TxnState.NO_TRANSACTION],42 [TxnState.TRANSACTION_COMMITTED_EMPTY]: [43 TxnState.TRANSACTION_COMMITTED_EMPTY,44 TxnState.NO_TRANSACTION45 ]46};47 48const ACTIVE_STATES: Set<TxnState> = new Set([49 TxnState.STARTING_TRANSACTION,50 TxnState.TRANSACTION_IN_PROGRESS51]);52 53const COMMITTED_STATES: Set<TxnState> = new Set([54 TxnState.TRANSACTION_COMMITTED,55 TxnState.TRANSACTION_COMMITTED_EMPTY,56 TxnState.TRANSACTION_ABORTED57]);58 59/**60 * Configuration options for a transaction.61 * @public62 */63export interface TransactionOptions extends Omit<CommandOperationOptions, 'timeoutMS'> {64 // TODO(NODE-3344): These options use the proper class forms of these settings, it should accept the basic enum values too65 /** A default read concern for commands in this transaction */66 readConcern?: ReadConcernLike;67 /** A default writeConcern for commands in this transaction */68 writeConcern?: WriteConcern;69 /** A default read preference for commands in this transaction */70 readPreference?: ReadPreferenceLike;71 /** Specifies the maximum amount of time to allow a commit action on a transaction to run in milliseconds */72 maxCommitTimeMS?: number;73}74 75/**76 * @public77 * @deprecated - Will be made internal in a future major release.78 * A class maintaining state related to a server transaction. Internal Only79 */80export class Transaction {81 /** @internal */82 state: TxnState;83 /** @deprecated - Will be made internal in a future major release. */84 options: TransactionOptions;85 /** @internal */86 _pinnedServer?: Server;87 /** @internal */88 _recoveryToken?: Document;89 90 /** Create a transaction @internal */91 constructor(options?: TransactionOptions) {92 options = options ?? {};93 this.state = TxnState.NO_TRANSACTION;94 this.options = {};95 96 const writeConcern = WriteConcern.fromOptions(options);97 if (writeConcern) {98 if (writeConcern.w === 0) {99 throw new MongoTransactionError('Transactions do not support unacknowledged write concern');100 }101 102 this.options.writeConcern = writeConcern;103 }104 105 if (options.readConcern) {106 this.options.readConcern = ReadConcern.fromOptions(options);107 }108 109 if (options.readPreference) {110 this.options.readPreference = ReadPreference.fromOptions(options);111 }112 113 if (options.maxCommitTimeMS) {114 this.options.maxTimeMS = options.maxCommitTimeMS;115 }116 117 // TODO: This isn't technically necessary118 this._pinnedServer = undefined;119 this._recoveryToken = undefined;120 }121 122 /** @internal */123 get server(): Server | undefined {124 return this._pinnedServer;125 }126 127 /** @deprecated - Will be made internal in a future major release. */128 get recoveryToken(): Document | undefined {129 return this._recoveryToken;130 }131 132 /** @deprecated - Will be made internal in a future major release. */133 get isPinned(): boolean {134 return !!this.server;135 }136 137 /**138 * @deprecated - Will be made internal in a future major release.139 * @returns Whether the transaction has started140 */141 get isStarting(): boolean {142 return this.state === TxnState.STARTING_TRANSACTION;143 }144 145 /**146 * @deprecated - Will be made internal in a future major release.147 * @returns Whether this session is presently in a transaction148 */149 get isActive(): boolean {150 return ACTIVE_STATES.has(this.state);151 }152 153 /** @deprecated - Will be made internal in a future major release. */154 get isCommitted(): boolean {155 return COMMITTED_STATES.has(this.state);156 }157 /**158 * Transition the transaction in the state machine159 * @internal160 * @param nextState - The new state to transition to161 */162 transition(nextState: TxnState): void {163 const nextStates = stateMachine[this.state];164 if (nextStates && nextStates.includes(nextState)) {165 this.state = nextState;166 if (167 this.state === TxnState.NO_TRANSACTION ||168 this.state === TxnState.STARTING_TRANSACTION ||169 this.state === TxnState.TRANSACTION_ABORTED170 ) {171 this.unpinServer();172 }173 return;174 }175 176 throw new MongoRuntimeError(177 `Attempted illegal state transition from [${this.state}] to [${nextState}]`178 );179 }180 181 /** @internal */182 pinServer(server: Server): void {183 if (this.isActive) {184 this._pinnedServer = server;185 }186 }187 188 /** @internal */189 unpinServer(): void {190 this._pinnedServer = undefined;191 }192}193 194export function isTransactionCommand(command: Document): boolean {195 return !!(command.commitTransaction || command.abortTransaction);196}197 