| 573 | /** @internal */ |
| 574 | async abortTransaction(options?: { timeoutMS?: number; throwTimeout?: true }): Promise<void>; |
| 575 | async abortTransaction(options?: { timeoutMS?: number; throwTimeout?: true }): Promise<void> { |
| 576 | if (this.transaction.state === TxnState.NO_TRANSACTION) { |
| 577 | throw new MongoTransactionError('No transaction started'); |
| 578 | } |
| 579 | |
| 580 | if (this.transaction.state === TxnState.STARTING_TRANSACTION) { |
| 581 | // the transaction was never started, we can safely exit here |
| 582 | this.transaction.transition(TxnState.TRANSACTION_ABORTED); |
| 583 | return; |
| 584 | } |
| 585 | |
| 586 | if (this.transaction.state === TxnState.TRANSACTION_ABORTED) { |
| 587 | throw new MongoTransactionError('Cannot call abortTransaction twice'); |
| 588 | } |
| 589 | |
| 590 | if ( |
| 591 | this.transaction.state === TxnState.TRANSACTION_COMMITTED || |
| 592 | this.transaction.state === TxnState.TRANSACTION_COMMITTED_EMPTY |
| 593 | ) { |
| 594 | throw new MongoTransactionError( |
| 595 | 'Cannot call abortTransaction after calling commitTransaction' |
| 596 | ); |
| 597 | } |
| 598 | |
| 599 | const command: { |
| 600 | abortTransaction: 1; |
| 601 | writeConcern?: WriteConcernOptions; |
| 602 | recoveryToken?: Document; |
| 603 | } = { abortTransaction: 1 }; |
| 604 | |
| 605 | const timeoutMS = |
| 606 | typeof options?.timeoutMS === 'number' |
| 607 | ? options.timeoutMS |
| 608 | : this.timeoutContext?.csotEnabled() |
| 609 | ? this.timeoutContext.timeoutMS // refresh timeoutMS for abort operation |
| 610 | : typeof this.timeoutMS === 'number' |
| 611 | ? this.timeoutMS |
| 612 | : null; |
| 613 | |
| 614 | const timeoutContext = |
| 615 | timeoutMS != null |
| 616 | ? TimeoutContext.create({ |
| 617 | timeoutMS, |
| 618 | serverSelectionTimeoutMS: this.clientOptions.serverSelectionTimeoutMS, |
| 619 | socketTimeoutMS: this.clientOptions.socketTimeoutMS |
| 620 | }) |
| 621 | : null; |
| 622 | |
| 623 | const wc = this.transaction.options.writeConcern ?? this.clientOptions?.writeConcern; |
| 624 | if (wc != null && timeoutMS == null) { |
| 625 | WriteConcern.apply(command, { wtimeoutMS: 10000, w: 'majority', ...wc }); |
| 626 | } |
| 627 | |
| 628 | if (this.transaction.recoveryToken) { |
| 629 | command.recoveryToken = this.transaction.recoveryToken; |
| 630 | } |
| 631 | |
| 632 | const operation = new RunCommandOperation(new MongoDBNamespace('admin'), command, { |