mongodb 6.8.0-dev.20240905.sha.65e0e15c → 6.8.1
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/README.md +1 -14
- package/lib/bson.js +13 -4
- package/lib/bson.js.map +1 -1
- package/lib/bulk/common.js +21 -16
- package/lib/bulk/common.js.map +1 -1
- package/lib/bulk/ordered.js.map +1 -1
- package/lib/bulk/unordered.js.map +1 -1
- package/lib/change_stream.js +8 -10
- package/lib/change_stream.js.map +1 -1
- package/lib/client-side-encryption/auto_encrypter.js +3 -14
- package/lib/client-side-encryption/auto_encrypter.js.map +1 -1
- package/lib/client-side-encryption/client_encryption.js +7 -25
- package/lib/client-side-encryption/client_encryption.js.map +1 -1
- package/lib/client-side-encryption/crypto_callbacks.js +6 -6
- package/lib/client-side-encryption/crypto_callbacks.js.map +1 -1
- package/lib/client-side-encryption/mongocryptd_manager.js +5 -9
- package/lib/client-side-encryption/mongocryptd_manager.js.map +1 -1
- package/lib/client-side-encryption/providers/aws.js +2 -1
- package/lib/client-side-encryption/providers/aws.js.map +1 -1
- package/lib/client-side-encryption/providers/azure.js +5 -5
- package/lib/client-side-encryption/providers/azure.js.map +1 -1
- package/lib/client-side-encryption/providers/gcp.js +2 -1
- package/lib/client-side-encryption/providers/gcp.js.map +1 -1
- package/lib/client-side-encryption/providers/index.js +3 -2
- package/lib/client-side-encryption/providers/index.js.map +1 -1
- package/lib/client-side-encryption/state_machine.js +4 -9
- package/lib/client-side-encryption/state_machine.js.map +1 -1
- package/lib/cmap/auth/auth_provider.js.map +1 -1
- package/lib/cmap/auth/aws_temporary_credentials.js.map +1 -1
- package/lib/cmap/auth/gssapi.js +4 -4
- package/lib/cmap/auth/gssapi.js.map +1 -1
- package/lib/cmap/auth/mongo_credentials.js.map +1 -1
- package/lib/cmap/auth/mongocr.js.map +1 -1
- package/lib/cmap/auth/mongodb_aws.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/automated_callback_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/azure_machine_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/callback_workflow.js +2 -0
- package/lib/cmap/auth/mongodb_oidc/callback_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/command_builders.js +3 -2
- package/lib/cmap/auth/mongodb_oidc/command_builders.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/gcp_machine_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/human_callback_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/machine_workflow.js +2 -0
- package/lib/cmap/auth/mongodb_oidc/machine_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/token_cache.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/token_machine_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc.js.map +1 -1
- package/lib/cmap/auth/plain.js.map +1 -1
- package/lib/cmap/auth/scram.js.map +1 -1
- package/lib/cmap/auth/x509.js.map +1 -1
- package/lib/cmap/command_monitoring_events.js.map +1 -1
- package/lib/cmap/commands.js +5 -62
- package/lib/cmap/commands.js.map +1 -1
- package/lib/cmap/connect.js +7 -9
- package/lib/cmap/connect.js.map +1 -1
- package/lib/cmap/connection.js +5 -3
- package/lib/cmap/connection.js.map +1 -1
- package/lib/cmap/connection_pool.js +9 -11
- package/lib/cmap/connection_pool.js.map +1 -1
- package/lib/cmap/connection_pool_events.js +3 -7
- package/lib/cmap/connection_pool_events.js.map +1 -1
- package/lib/cmap/handshake/client_metadata.js +5 -5
- package/lib/cmap/handshake/client_metadata.js.map +1 -1
- package/lib/cmap/metrics.js +1 -1
- package/lib/cmap/metrics.js.map +1 -1
- package/lib/cmap/stream_description.js.map +1 -1
- package/lib/cmap/wire_protocol/compression.js +5 -5
- package/lib/cmap/wire_protocol/compression.js.map +1 -1
- package/lib/cmap/wire_protocol/constants.js +2 -2
- package/lib/cmap/wire_protocol/on_data.js +2 -1
- package/lib/cmap/wire_protocol/on_data.js.map +1 -1
- package/lib/cmap/wire_protocol/on_demand/document.js +3 -12
- package/lib/cmap/wire_protocol/on_demand/document.js.map +1 -1
- package/lib/cmap/wire_protocol/responses.js +15 -6
- package/lib/cmap/wire_protocol/responses.js.map +1 -1
- package/lib/cmap/wire_protocol/shared.js +3 -2
- package/lib/cmap/wire_protocol/shared.js.map +1 -1
- package/lib/collection.js.map +1 -1
- package/lib/connection_string.js +5 -10
- package/lib/connection_string.js.map +1 -1
- package/lib/constants.js +0 -1
- package/lib/constants.js.map +1 -1
- package/lib/cursor/abstract_cursor.js +16 -25
- package/lib/cursor/abstract_cursor.js.map +1 -1
- package/lib/cursor/aggregation_cursor.js +2 -2
- package/lib/cursor/aggregation_cursor.js.map +1 -1
- package/lib/cursor/change_stream_cursor.js.map +1 -1
- package/lib/cursor/find_cursor.js +4 -4
- package/lib/cursor/find_cursor.js.map +1 -1
- package/lib/db.js +1 -1
- package/lib/db.js.map +1 -1
- package/lib/deps.js +8 -16
- package/lib/deps.js.map +1 -1
- package/lib/encrypter.js.map +1 -1
- package/lib/error.js +14 -19
- package/lib/error.js.map +1 -1
- package/lib/explain.js.map +1 -1
- package/lib/gridfs/download.js +4 -1
- package/lib/gridfs/download.js.map +1 -1
- package/lib/gridfs/index.js +1 -1
- package/lib/gridfs/index.js.map +1 -1
- package/lib/gridfs/upload.js +4 -0
- package/lib/gridfs/upload.js.map +1 -1
- package/lib/index.js +2 -4
- package/lib/index.js.map +1 -1
- package/lib/mongo_client.js +1 -15
- package/lib/mongo_client.js.map +1 -1
- package/lib/mongo_client_auth_providers.js.map +1 -1
- package/lib/mongo_logger.js +8 -8
- package/lib/mongo_logger.js.map +1 -1
- package/lib/mongo_types.js +0 -1
- package/lib/mongo_types.js.map +1 -1
- package/lib/operations/aggregate.js +0 -1
- package/lib/operations/aggregate.js.map +1 -1
- package/lib/operations/bulk_write.js.map +1 -1
- package/lib/operations/collections.js.map +1 -1
- package/lib/operations/command.js +1 -1
- package/lib/operations/command.js.map +1 -1
- package/lib/operations/count.js.map +1 -1
- package/lib/operations/create_collection.js.map +1 -1
- package/lib/operations/delete.js +2 -2
- package/lib/operations/delete.js.map +1 -1
- package/lib/operations/distinct.js.map +1 -1
- package/lib/operations/drop.js.map +1 -1
- package/lib/operations/estimated_document_count.js.map +1 -1
- package/lib/operations/execute_operation.js +109 -111
- package/lib/operations/execute_operation.js.map +1 -1
- package/lib/operations/find.js.map +1 -1
- package/lib/operations/find_and_modify.js +8 -2
- package/lib/operations/find_and_modify.js.map +1 -1
- package/lib/operations/get_more.js.map +1 -1
- package/lib/operations/indexes.js.map +1 -1
- package/lib/operations/insert.js.map +1 -1
- package/lib/operations/is_capped.js.map +1 -1
- package/lib/operations/kill_cursors.js.map +1 -1
- package/lib/operations/list_collections.js.map +1 -1
- package/lib/operations/list_databases.js.map +1 -1
- package/lib/operations/operation.js +5 -5
- package/lib/operations/operation.js.map +1 -1
- package/lib/operations/options_operation.js.map +1 -1
- package/lib/operations/profiling_level.js.map +1 -1
- package/lib/operations/search_indexes/drop.js.map +1 -1
- package/lib/operations/set_profiling_level.js.map +1 -1
- package/lib/operations/stats.js.map +1 -1
- package/lib/operations/update.js +2 -2
- package/lib/operations/update.js.map +1 -1
- package/lib/operations/validate_collection.js.map +1 -1
- package/lib/read_concern.js.map +1 -1
- package/lib/read_preference.js +1 -1
- package/lib/read_preference.js.map +1 -1
- package/lib/sdam/common.js +3 -3
- package/lib/sdam/common.js.map +1 -1
- package/lib/sdam/monitor.js +5 -1
- package/lib/sdam/monitor.js.map +1 -1
- package/lib/sdam/server.js +2 -2
- package/lib/sdam/server.js.map +1 -1
- package/lib/sdam/server_description.js +3 -3
- package/lib/sdam/server_description.js.map +1 -1
- package/lib/sdam/server_selection.js +5 -5
- package/lib/sdam/server_selection.js.map +1 -1
- package/lib/sdam/srv_polling.js +3 -2
- package/lib/sdam/srv_polling.js.map +1 -1
- package/lib/sdam/topology.js +1 -1
- package/lib/sdam/topology.js.map +1 -1
- package/lib/sdam/topology_description.js.map +1 -1
- package/lib/sessions.js +218 -221
- package/lib/sessions.js.map +1 -1
- package/lib/sort.js +3 -2
- package/lib/sort.js.map +1 -1
- package/lib/timeout.js +1 -0
- package/lib/timeout.js.map +1 -1
- package/lib/transactions.js +2 -2
- package/lib/transactions.js.map +1 -1
- package/lib/utils.js +51 -49
- package/lib/utils.js.map +1 -1
- package/lib/write_concern.js +2 -2
- package/lib/write_concern.js.map +1 -1
- package/mongodb.d.ts +143 -146
- package/package.json +28 -27
- package/src/bson.ts +13 -1
- package/src/bulk/common.ts +18 -18
- package/src/change_stream.ts +15 -33
- package/src/client-side-encryption/auto_encrypter.ts +82 -18
- package/src/client-side-encryption/client_encryption.ts +54 -51
- package/src/client-side-encryption/mongocryptd_manager.ts +6 -10
- package/src/client-side-encryption/state_machine.ts +6 -28
- package/src/cmap/auth/gssapi.ts +1 -1
- package/src/cmap/auth/mongodb_aws.ts +2 -2
- package/src/cmap/auth/mongodb_oidc/callback_workflow.ts +2 -2
- package/src/cmap/auth/mongodb_oidc/machine_workflow.ts +2 -2
- package/src/cmap/commands.ts +5 -70
- package/src/cmap/connect.ts +1 -3
- package/src/cmap/connection.ts +4 -3
- package/src/cmap/connection_pool.ts +9 -17
- package/src/cmap/connection_pool_events.ts +2 -34
- package/src/cmap/handshake/client_metadata.ts +1 -1
- package/src/cmap/wire_protocol/constants.ts +2 -2
- package/src/cmap/wire_protocol/on_demand/document.ts +14 -18
- package/src/cmap/wire_protocol/responses.ts +23 -5
- package/src/cmap/wire_protocol/shared.ts +2 -1
- package/src/collection.ts +15 -16
- package/src/connection_string.ts +2 -8
- package/src/constants.ts +0 -1
- package/src/cursor/abstract_cursor.ts +28 -42
- package/src/cursor/aggregation_cursor.ts +5 -7
- package/src/cursor/find_cursor.ts +1 -1
- package/src/deps.ts +1 -8
- package/src/error.ts +14 -33
- package/src/gridfs/download.ts +4 -28
- package/src/gridfs/upload.ts +6 -1
- package/src/index.ts +6 -6
- package/src/mongo_client.ts +3 -25
- package/src/mongo_logger.ts +3 -5
- package/src/mongo_types.ts +68 -69
- package/src/operations/aggregate.ts +1 -2
- package/src/operations/bulk_write.ts +2 -2
- package/src/operations/command.ts +1 -1
- package/src/operations/execute_operation.ts +131 -137
- package/src/operations/find_and_modify.ts +7 -2
- package/src/operations/insert.ts +4 -3
- package/src/operations/operation.ts +10 -7
- package/src/operations/search_indexes/drop.ts +1 -4
- package/src/sdam/monitor.ts +5 -3
- package/src/sdam/server.ts +1 -1
- package/src/sdam/server_description.ts +6 -5
- package/src/sdam/srv_polling.ts +2 -1
- package/src/sessions.ts +277 -291
- package/src/sort.ts +1 -1
- package/src/timeout.ts +1 -0
- package/src/transactions.ts +2 -1
- package/src/utils.ts +4 -9
- package/src/write_concern.ts +2 -2
- package/tsconfig.json +1 -2
- package/lib/beta.d.ts +0 -7900
- package/lib/beta.js +0 -21
- package/lib/beta.js.map +0 -1
- package/lib/operations/client_bulk_write/command_builder.js +0 -198
- package/lib/operations/client_bulk_write/command_builder.js.map +0 -1
- package/lib/operations/client_bulk_write/common.js +0 -3
- package/lib/operations/client_bulk_write/common.js.map +0 -1
- package/lib/resource_management.js +0 -58
- package/lib/resource_management.js.map +0 -1
- package/src/beta.ts +0 -22
- package/src/operations/client_bulk_write/command_builder.ts +0 -283
- package/src/operations/client_bulk_write/common.ts +0 -146
- package/src/resource_management.ts +0 -74
package/src/sessions.ts
CHANGED
|
@@ -27,7 +27,6 @@ import { executeOperation } from './operations/execute_operation';
|
|
|
27
27
|
import { RunAdminCommandOperation } from './operations/run_command';
|
|
28
28
|
import { ReadConcernLevel } from './read_concern';
|
|
29
29
|
import { ReadPreference } from './read_preference';
|
|
30
|
-
import { type AsyncDisposable, configureResourceManagement } from './resource_management';
|
|
31
30
|
import { _advanceClusterTime, type ClusterTime, TopologyType } from './sdam/common';
|
|
32
31
|
import {
|
|
33
32
|
isTransactionCommand,
|
|
@@ -46,7 +45,7 @@ import {
|
|
|
46
45
|
squashError,
|
|
47
46
|
uuidV4
|
|
48
47
|
} from './utils';
|
|
49
|
-
import { WriteConcern
|
|
48
|
+
import { WriteConcern } from './write_concern';
|
|
50
49
|
|
|
51
50
|
const minWireVersionForShardedTransactions = 8;
|
|
52
51
|
|
|
@@ -106,10 +105,7 @@ export interface EndSessionOptions {
|
|
|
106
105
|
* NOTE: not meant to be instantiated directly.
|
|
107
106
|
* @public
|
|
108
107
|
*/
|
|
109
|
-
export class ClientSession
|
|
110
|
-
extends TypedEventEmitter<ClientSessionEvents>
|
|
111
|
-
implements AsyncDisposable
|
|
112
|
-
{
|
|
108
|
+
export class ClientSession extends TypedEventEmitter<ClientSessionEvents> {
|
|
113
109
|
/** @internal */
|
|
114
110
|
client: MongoClient;
|
|
115
111
|
/** @internal */
|
|
@@ -259,10 +255,7 @@ export class ClientSession
|
|
|
259
255
|
}
|
|
260
256
|
|
|
261
257
|
/**
|
|
262
|
-
*
|
|
263
|
-
* the transaction is aborted.
|
|
264
|
-
*
|
|
265
|
-
* Does not end the session on the server.
|
|
258
|
+
* Ends this session on the server
|
|
266
259
|
*
|
|
267
260
|
* @param options - Optional settings. Currently reserved for future use
|
|
268
261
|
*/
|
|
@@ -293,16 +286,6 @@ export class ClientSession
|
|
|
293
286
|
maybeClearPinnedConnection(this, { force: true, ...options });
|
|
294
287
|
}
|
|
295
288
|
}
|
|
296
|
-
/**
|
|
297
|
-
* @beta
|
|
298
|
-
* @experimental
|
|
299
|
-
* An alias for {@link ClientSession.endSession|ClientSession.endSession()}.
|
|
300
|
-
*/
|
|
301
|
-
declare [Symbol.asyncDispose]: () => Promise<void>;
|
|
302
|
-
/** @internal */
|
|
303
|
-
async asyncDispose() {
|
|
304
|
-
await this.endSession({ force: true });
|
|
305
|
-
}
|
|
306
289
|
|
|
307
290
|
/**
|
|
308
291
|
* Advances the operationTime for a ClientSession.
|
|
@@ -443,167 +426,14 @@ export class ClientSession
|
|
|
443
426
|
* Commits the currently active transaction in this session.
|
|
444
427
|
*/
|
|
445
428
|
async commitTransaction(): Promise<void> {
|
|
446
|
-
|
|
447
|
-
throw new MongoTransactionError('No transaction started');
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
if (
|
|
451
|
-
this.transaction.state === TxnState.STARTING_TRANSACTION ||
|
|
452
|
-
this.transaction.state === TxnState.TRANSACTION_COMMITTED_EMPTY
|
|
453
|
-
) {
|
|
454
|
-
// the transaction was never started, we can safely exit here
|
|
455
|
-
this.transaction.transition(TxnState.TRANSACTION_COMMITTED_EMPTY);
|
|
456
|
-
return;
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
if (this.transaction.state === TxnState.TRANSACTION_ABORTED) {
|
|
460
|
-
throw new MongoTransactionError(
|
|
461
|
-
'Cannot call commitTransaction after calling abortTransaction'
|
|
462
|
-
);
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
const command: {
|
|
466
|
-
commitTransaction: 1;
|
|
467
|
-
writeConcern?: WriteConcernSettings;
|
|
468
|
-
recoveryToken?: Document;
|
|
469
|
-
maxTimeMS?: number;
|
|
470
|
-
} = { commitTransaction: 1 };
|
|
471
|
-
|
|
472
|
-
const wc = this.transaction.options.writeConcern ?? this.clientOptions?.writeConcern;
|
|
473
|
-
if (wc != null) {
|
|
474
|
-
WriteConcern.apply(command, { wtimeoutMS: 10000, w: 'majority', ...wc });
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
if (this.transaction.state === TxnState.TRANSACTION_COMMITTED) {
|
|
478
|
-
WriteConcern.apply(command, { wtimeoutMS: 10000, ...wc, w: 'majority' });
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
if (typeof this.transaction.options.maxTimeMS === 'number') {
|
|
482
|
-
command.maxTimeMS = this.transaction.options.maxTimeMS;
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
if (this.transaction.recoveryToken) {
|
|
486
|
-
command.recoveryToken = this.transaction.recoveryToken;
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
const operation = new RunAdminCommandOperation(command, {
|
|
490
|
-
session: this,
|
|
491
|
-
readPreference: ReadPreference.primary,
|
|
492
|
-
bypassPinningCheck: true
|
|
493
|
-
});
|
|
494
|
-
|
|
495
|
-
try {
|
|
496
|
-
await executeOperation(this.client, operation);
|
|
497
|
-
return;
|
|
498
|
-
} catch (firstCommitError) {
|
|
499
|
-
if (firstCommitError instanceof MongoError && isRetryableWriteError(firstCommitError)) {
|
|
500
|
-
// SPEC-1185: apply majority write concern when retrying commitTransaction
|
|
501
|
-
WriteConcern.apply(command, { wtimeoutMS: 10000, ...wc, w: 'majority' });
|
|
502
|
-
// per txns spec, must unpin session in this case
|
|
503
|
-
this.unpin({ force: true });
|
|
504
|
-
|
|
505
|
-
try {
|
|
506
|
-
await executeOperation(this.client, operation);
|
|
507
|
-
return;
|
|
508
|
-
} catch (retryCommitError) {
|
|
509
|
-
// If the retry failed, we process that error instead of the original
|
|
510
|
-
if (shouldAddUnknownTransactionCommitResultLabel(retryCommitError)) {
|
|
511
|
-
retryCommitError.addErrorLabel(MongoErrorLabel.UnknownTransactionCommitResult);
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
if (shouldUnpinAfterCommitError(retryCommitError)) {
|
|
515
|
-
this.unpin({ error: retryCommitError });
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
throw retryCommitError;
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
if (shouldAddUnknownTransactionCommitResultLabel(firstCommitError)) {
|
|
523
|
-
firstCommitError.addErrorLabel(MongoErrorLabel.UnknownTransactionCommitResult);
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
if (shouldUnpinAfterCommitError(firstCommitError)) {
|
|
527
|
-
this.unpin({ error: firstCommitError });
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
throw firstCommitError;
|
|
531
|
-
} finally {
|
|
532
|
-
this.transaction.transition(TxnState.TRANSACTION_COMMITTED);
|
|
533
|
-
}
|
|
429
|
+
return await endTransaction(this, 'commitTransaction');
|
|
534
430
|
}
|
|
535
431
|
|
|
536
432
|
/**
|
|
537
433
|
* Aborts the currently active transaction in this session.
|
|
538
434
|
*/
|
|
539
435
|
async abortTransaction(): Promise<void> {
|
|
540
|
-
|
|
541
|
-
throw new MongoTransactionError('No transaction started');
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
if (this.transaction.state === TxnState.STARTING_TRANSACTION) {
|
|
545
|
-
// the transaction was never started, we can safely exit here
|
|
546
|
-
this.transaction.transition(TxnState.TRANSACTION_ABORTED);
|
|
547
|
-
return;
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
if (this.transaction.state === TxnState.TRANSACTION_ABORTED) {
|
|
551
|
-
throw new MongoTransactionError('Cannot call abortTransaction twice');
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
if (
|
|
555
|
-
this.transaction.state === TxnState.TRANSACTION_COMMITTED ||
|
|
556
|
-
this.transaction.state === TxnState.TRANSACTION_COMMITTED_EMPTY
|
|
557
|
-
) {
|
|
558
|
-
throw new MongoTransactionError(
|
|
559
|
-
'Cannot call abortTransaction after calling commitTransaction'
|
|
560
|
-
);
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
const command: {
|
|
564
|
-
abortTransaction: 1;
|
|
565
|
-
writeConcern?: WriteConcernOptions;
|
|
566
|
-
recoveryToken?: Document;
|
|
567
|
-
} = { abortTransaction: 1 };
|
|
568
|
-
|
|
569
|
-
const wc = this.transaction.options.writeConcern ?? this.clientOptions?.writeConcern;
|
|
570
|
-
if (wc != null) {
|
|
571
|
-
WriteConcern.apply(command, { wtimeoutMS: 10000, w: 'majority', ...wc });
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
if (this.transaction.recoveryToken) {
|
|
575
|
-
command.recoveryToken = this.transaction.recoveryToken;
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
const operation = new RunAdminCommandOperation(command, {
|
|
579
|
-
session: this,
|
|
580
|
-
readPreference: ReadPreference.primary,
|
|
581
|
-
bypassPinningCheck: true
|
|
582
|
-
});
|
|
583
|
-
|
|
584
|
-
try {
|
|
585
|
-
await executeOperation(this.client, operation);
|
|
586
|
-
this.unpin();
|
|
587
|
-
return;
|
|
588
|
-
} catch (firstAbortError) {
|
|
589
|
-
this.unpin();
|
|
590
|
-
|
|
591
|
-
if (firstAbortError instanceof MongoError && isRetryableWriteError(firstAbortError)) {
|
|
592
|
-
try {
|
|
593
|
-
await executeOperation(this.client, operation);
|
|
594
|
-
return;
|
|
595
|
-
} catch {
|
|
596
|
-
// we do not retry the retry
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
// The spec indicates that if the operation times out or fails with a non-retryable error, we should ignore all errors on `abortTransaction`
|
|
601
|
-
} finally {
|
|
602
|
-
this.transaction.transition(TxnState.TRANSACTION_ABORTED);
|
|
603
|
-
if (this.loadBalanced) {
|
|
604
|
-
maybeClearPinnedConnection(this, { force: false });
|
|
605
|
-
}
|
|
606
|
-
}
|
|
436
|
+
return await endTransaction(this, 'abortTransaction');
|
|
607
437
|
}
|
|
608
438
|
|
|
609
439
|
/**
|
|
@@ -649,132 +479,23 @@ export class ClientSession
|
|
|
649
479
|
fn: WithTransactionCallback<T>,
|
|
650
480
|
options?: TransactionOptions
|
|
651
481
|
): Promise<T> {
|
|
652
|
-
const MAX_TIMEOUT = 120000;
|
|
653
482
|
const startTime = now();
|
|
654
|
-
|
|
655
|
-
let committed = false;
|
|
656
|
-
let result: any;
|
|
657
|
-
|
|
658
|
-
while (!committed) {
|
|
659
|
-
this.startTransaction(options); // may throw on error
|
|
660
|
-
|
|
661
|
-
try {
|
|
662
|
-
const promise = fn(this);
|
|
663
|
-
if (!isPromiseLike(promise)) {
|
|
664
|
-
throw new MongoInvalidArgumentError(
|
|
665
|
-
'Function provided to `withTransaction` must return a Promise'
|
|
666
|
-
);
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
result = await promise;
|
|
670
|
-
|
|
671
|
-
if (
|
|
672
|
-
this.transaction.state === TxnState.NO_TRANSACTION ||
|
|
673
|
-
this.transaction.state === TxnState.TRANSACTION_COMMITTED ||
|
|
674
|
-
this.transaction.state === TxnState.TRANSACTION_ABORTED
|
|
675
|
-
) {
|
|
676
|
-
// Assume callback intentionally ended the transaction
|
|
677
|
-
return result;
|
|
678
|
-
}
|
|
679
|
-
} catch (fnError) {
|
|
680
|
-
if (!(fnError instanceof MongoError) || fnError instanceof MongoInvalidArgumentError) {
|
|
681
|
-
await this.abortTransaction();
|
|
682
|
-
throw fnError;
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
if (
|
|
686
|
-
this.transaction.state === TxnState.STARTING_TRANSACTION ||
|
|
687
|
-
this.transaction.state === TxnState.TRANSACTION_IN_PROGRESS
|
|
688
|
-
) {
|
|
689
|
-
await this.abortTransaction();
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
if (
|
|
693
|
-
fnError.hasErrorLabel(MongoErrorLabel.TransientTransactionError) &&
|
|
694
|
-
now() - startTime < MAX_TIMEOUT
|
|
695
|
-
) {
|
|
696
|
-
continue;
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
throw fnError;
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
while (!committed) {
|
|
703
|
-
try {
|
|
704
|
-
/*
|
|
705
|
-
* We will rely on ClientSession.commitTransaction() to
|
|
706
|
-
* apply a majority write concern if commitTransaction is
|
|
707
|
-
* being retried (see: DRIVERS-601)
|
|
708
|
-
*/
|
|
709
|
-
await this.commitTransaction();
|
|
710
|
-
committed = true;
|
|
711
|
-
} catch (commitError) {
|
|
712
|
-
/*
|
|
713
|
-
* Note: a maxTimeMS error will have the MaxTimeMSExpired
|
|
714
|
-
* code (50) and can be reported as a top-level error or
|
|
715
|
-
* inside writeConcernError, ex.
|
|
716
|
-
* { ok:0, code: 50, codeName: 'MaxTimeMSExpired' }
|
|
717
|
-
* { ok:1, writeConcernError: { code: 50, codeName: 'MaxTimeMSExpired' } }
|
|
718
|
-
*/
|
|
719
|
-
if (
|
|
720
|
-
!isMaxTimeMSExpiredError(commitError) &&
|
|
721
|
-
commitError.hasErrorLabel(MongoErrorLabel.UnknownTransactionCommitResult) &&
|
|
722
|
-
now() - startTime < MAX_TIMEOUT
|
|
723
|
-
) {
|
|
724
|
-
continue;
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
if (
|
|
728
|
-
commitError.hasErrorLabel(MongoErrorLabel.TransientTransactionError) &&
|
|
729
|
-
now() - startTime < MAX_TIMEOUT
|
|
730
|
-
) {
|
|
731
|
-
break;
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
throw commitError;
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
return result;
|
|
483
|
+
return await attemptTransaction(this, startTime, fn, options);
|
|
740
484
|
}
|
|
741
485
|
}
|
|
742
486
|
|
|
743
|
-
|
|
744
|
-
|
|
487
|
+
const MAX_WITH_TRANSACTION_TIMEOUT = 120000;
|
|
745
488
|
const NON_DETERMINISTIC_WRITE_CONCERN_ERRORS = new Set([
|
|
746
489
|
'CannotSatisfyWriteConcern',
|
|
747
490
|
'UnknownReplWriteConcern',
|
|
748
491
|
'UnsatisfiableWriteConcern'
|
|
749
492
|
]);
|
|
750
493
|
|
|
751
|
-
function
|
|
752
|
-
|
|
753
|
-
if (
|
|
754
|
-
isRetryableWriteError(commitError) ||
|
|
755
|
-
commitError instanceof MongoWriteConcernError ||
|
|
756
|
-
isMaxTimeMSExpiredError(commitError)
|
|
757
|
-
) {
|
|
758
|
-
if (isUnknownTransactionCommitResult(commitError)) {
|
|
759
|
-
// per txns spec, must unpin session in this case
|
|
760
|
-
return true;
|
|
761
|
-
}
|
|
762
|
-
} else if (commitError.hasErrorLabel(MongoErrorLabel.TransientTransactionError)) {
|
|
763
|
-
return true;
|
|
764
|
-
}
|
|
765
|
-
}
|
|
766
|
-
return false;
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
function shouldAddUnknownTransactionCommitResultLabel(commitError: MongoError) {
|
|
770
|
-
let ok = isRetryableWriteError(commitError);
|
|
771
|
-
ok ||= commitError instanceof MongoWriteConcernError;
|
|
772
|
-
ok ||= isMaxTimeMSExpiredError(commitError);
|
|
773
|
-
ok &&= isUnknownTransactionCommitResult(commitError);
|
|
774
|
-
return ok;
|
|
494
|
+
function hasNotTimedOut(startTime: number, max: number) {
|
|
495
|
+
return calculateDurationInMs(startTime) < max;
|
|
775
496
|
}
|
|
776
497
|
|
|
777
|
-
function isUnknownTransactionCommitResult(err: MongoError)
|
|
498
|
+
function isUnknownTransactionCommitResult(err: MongoError) {
|
|
778
499
|
const isNonDeterministicWriteConcernError =
|
|
779
500
|
err instanceof MongoServerError &&
|
|
780
501
|
err.codeName &&
|
|
@@ -829,17 +550,282 @@ export function maybeClearPinnedConnection(
|
|
|
829
550
|
}
|
|
830
551
|
}
|
|
831
552
|
|
|
832
|
-
function isMaxTimeMSExpiredError(err: MongoError)
|
|
553
|
+
function isMaxTimeMSExpiredError(err: MongoError) {
|
|
833
554
|
if (err == null || !(err instanceof MongoServerError)) {
|
|
834
555
|
return false;
|
|
835
556
|
}
|
|
836
557
|
|
|
837
558
|
return (
|
|
838
559
|
err.code === MONGODB_ERROR_CODES.MaxTimeMSExpired ||
|
|
839
|
-
err.writeConcernError
|
|
560
|
+
(err.writeConcernError && err.writeConcernError.code === MONGODB_ERROR_CODES.MaxTimeMSExpired)
|
|
840
561
|
);
|
|
841
562
|
}
|
|
842
563
|
|
|
564
|
+
async function attemptTransactionCommit<T>(
|
|
565
|
+
session: ClientSession,
|
|
566
|
+
startTime: number,
|
|
567
|
+
fn: WithTransactionCallback<T>,
|
|
568
|
+
result: T,
|
|
569
|
+
options: TransactionOptions
|
|
570
|
+
): Promise<T> {
|
|
571
|
+
try {
|
|
572
|
+
await session.commitTransaction();
|
|
573
|
+
return result;
|
|
574
|
+
} catch (commitErr) {
|
|
575
|
+
if (
|
|
576
|
+
commitErr instanceof MongoError &&
|
|
577
|
+
hasNotTimedOut(startTime, MAX_WITH_TRANSACTION_TIMEOUT) &&
|
|
578
|
+
!isMaxTimeMSExpiredError(commitErr)
|
|
579
|
+
) {
|
|
580
|
+
if (commitErr.hasErrorLabel(MongoErrorLabel.UnknownTransactionCommitResult)) {
|
|
581
|
+
return await attemptTransactionCommit(session, startTime, fn, result, options);
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
if (commitErr.hasErrorLabel(MongoErrorLabel.TransientTransactionError)) {
|
|
585
|
+
return await attemptTransaction(session, startTime, fn, options);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
throw commitErr;
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
const USER_EXPLICIT_TXN_END_STATES = new Set<TxnState>([
|
|
594
|
+
TxnState.NO_TRANSACTION,
|
|
595
|
+
TxnState.TRANSACTION_COMMITTED,
|
|
596
|
+
TxnState.TRANSACTION_ABORTED
|
|
597
|
+
]);
|
|
598
|
+
|
|
599
|
+
function userExplicitlyEndedTransaction(session: ClientSession) {
|
|
600
|
+
return USER_EXPLICIT_TXN_END_STATES.has(session.transaction.state);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
async function attemptTransaction<T>(
|
|
604
|
+
session: ClientSession,
|
|
605
|
+
startTime: number,
|
|
606
|
+
fn: WithTransactionCallback<T>,
|
|
607
|
+
options: TransactionOptions = {}
|
|
608
|
+
): Promise<T> {
|
|
609
|
+
session.startTransaction(options);
|
|
610
|
+
|
|
611
|
+
let promise;
|
|
612
|
+
try {
|
|
613
|
+
promise = fn(session);
|
|
614
|
+
} catch (err) {
|
|
615
|
+
promise = Promise.reject(err);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
if (!isPromiseLike(promise)) {
|
|
619
|
+
try {
|
|
620
|
+
await session.abortTransaction();
|
|
621
|
+
} catch (error) {
|
|
622
|
+
squashError(error);
|
|
623
|
+
}
|
|
624
|
+
throw new MongoInvalidArgumentError(
|
|
625
|
+
'Function provided to `withTransaction` must return a Promise'
|
|
626
|
+
);
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
try {
|
|
630
|
+
const result = await promise;
|
|
631
|
+
if (userExplicitlyEndedTransaction(session)) {
|
|
632
|
+
return result;
|
|
633
|
+
}
|
|
634
|
+
return await attemptTransactionCommit(session, startTime, fn, result, options);
|
|
635
|
+
} catch (err) {
|
|
636
|
+
if (session.inTransaction()) {
|
|
637
|
+
await session.abortTransaction();
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
if (
|
|
641
|
+
err instanceof MongoError &&
|
|
642
|
+
err.hasErrorLabel(MongoErrorLabel.TransientTransactionError) &&
|
|
643
|
+
hasNotTimedOut(startTime, MAX_WITH_TRANSACTION_TIMEOUT)
|
|
644
|
+
) {
|
|
645
|
+
return await attemptTransaction(session, startTime, fn, options);
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
if (isMaxTimeMSExpiredError(err)) {
|
|
649
|
+
err.addErrorLabel(MongoErrorLabel.UnknownTransactionCommitResult);
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
throw err;
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
async function endTransaction(
|
|
657
|
+
session: ClientSession,
|
|
658
|
+
commandName: 'abortTransaction' | 'commitTransaction'
|
|
659
|
+
): Promise<void> {
|
|
660
|
+
// handle any initial problematic cases
|
|
661
|
+
const txnState = session.transaction.state;
|
|
662
|
+
|
|
663
|
+
if (txnState === TxnState.NO_TRANSACTION) {
|
|
664
|
+
throw new MongoTransactionError('No transaction started');
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
if (commandName === 'commitTransaction') {
|
|
668
|
+
if (
|
|
669
|
+
txnState === TxnState.STARTING_TRANSACTION ||
|
|
670
|
+
txnState === TxnState.TRANSACTION_COMMITTED_EMPTY
|
|
671
|
+
) {
|
|
672
|
+
// the transaction was never started, we can safely exit here
|
|
673
|
+
session.transaction.transition(TxnState.TRANSACTION_COMMITTED_EMPTY);
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
if (txnState === TxnState.TRANSACTION_ABORTED) {
|
|
678
|
+
throw new MongoTransactionError(
|
|
679
|
+
'Cannot call commitTransaction after calling abortTransaction'
|
|
680
|
+
);
|
|
681
|
+
}
|
|
682
|
+
} else {
|
|
683
|
+
if (txnState === TxnState.STARTING_TRANSACTION) {
|
|
684
|
+
// the transaction was never started, we can safely exit here
|
|
685
|
+
session.transaction.transition(TxnState.TRANSACTION_ABORTED);
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
if (txnState === TxnState.TRANSACTION_ABORTED) {
|
|
690
|
+
throw new MongoTransactionError('Cannot call abortTransaction twice');
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
if (
|
|
694
|
+
txnState === TxnState.TRANSACTION_COMMITTED ||
|
|
695
|
+
txnState === TxnState.TRANSACTION_COMMITTED_EMPTY
|
|
696
|
+
) {
|
|
697
|
+
throw new MongoTransactionError(
|
|
698
|
+
'Cannot call abortTransaction after calling commitTransaction'
|
|
699
|
+
);
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
// construct and send the command
|
|
704
|
+
const command: Document = { [commandName]: 1 };
|
|
705
|
+
|
|
706
|
+
// apply a writeConcern if specified
|
|
707
|
+
let writeConcern;
|
|
708
|
+
if (session.transaction.options.writeConcern) {
|
|
709
|
+
writeConcern = Object.assign({}, session.transaction.options.writeConcern);
|
|
710
|
+
} else if (session.clientOptions && session.clientOptions.writeConcern) {
|
|
711
|
+
writeConcern = { w: session.clientOptions.writeConcern.w };
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
if (txnState === TxnState.TRANSACTION_COMMITTED) {
|
|
715
|
+
writeConcern = Object.assign({ wtimeoutMS: 10000 }, writeConcern, { w: 'majority' });
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
if (writeConcern) {
|
|
719
|
+
WriteConcern.apply(command, writeConcern);
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
if (commandName === 'commitTransaction' && session.transaction.options.maxTimeMS) {
|
|
723
|
+
Object.assign(command, { maxTimeMS: session.transaction.options.maxTimeMS });
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
if (session.transaction.recoveryToken) {
|
|
727
|
+
command.recoveryToken = session.transaction.recoveryToken;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
try {
|
|
731
|
+
// send the command
|
|
732
|
+
await executeOperation(
|
|
733
|
+
session.client,
|
|
734
|
+
new RunAdminCommandOperation(command, {
|
|
735
|
+
session,
|
|
736
|
+
readPreference: ReadPreference.primary,
|
|
737
|
+
bypassPinningCheck: true
|
|
738
|
+
})
|
|
739
|
+
);
|
|
740
|
+
if (command.abortTransaction) {
|
|
741
|
+
// always unpin on abort regardless of command outcome
|
|
742
|
+
session.unpin();
|
|
743
|
+
}
|
|
744
|
+
if (commandName !== 'commitTransaction') {
|
|
745
|
+
session.transaction.transition(TxnState.TRANSACTION_ABORTED);
|
|
746
|
+
if (session.loadBalanced) {
|
|
747
|
+
maybeClearPinnedConnection(session, { force: false });
|
|
748
|
+
}
|
|
749
|
+
} else {
|
|
750
|
+
session.transaction.transition(TxnState.TRANSACTION_COMMITTED);
|
|
751
|
+
}
|
|
752
|
+
} catch (firstAttemptErr) {
|
|
753
|
+
if (command.abortTransaction) {
|
|
754
|
+
// always unpin on abort regardless of command outcome
|
|
755
|
+
session.unpin();
|
|
756
|
+
}
|
|
757
|
+
if (firstAttemptErr instanceof MongoError && isRetryableWriteError(firstAttemptErr)) {
|
|
758
|
+
// SPEC-1185: apply majority write concern when retrying commitTransaction
|
|
759
|
+
if (command.commitTransaction) {
|
|
760
|
+
// per txns spec, must unpin session in this case
|
|
761
|
+
session.unpin({ force: true });
|
|
762
|
+
|
|
763
|
+
command.writeConcern = Object.assign({ wtimeout: 10000 }, command.writeConcern, {
|
|
764
|
+
w: 'majority'
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
try {
|
|
769
|
+
await executeOperation(
|
|
770
|
+
session.client,
|
|
771
|
+
new RunAdminCommandOperation(command, {
|
|
772
|
+
session,
|
|
773
|
+
readPreference: ReadPreference.primary,
|
|
774
|
+
bypassPinningCheck: true
|
|
775
|
+
})
|
|
776
|
+
);
|
|
777
|
+
if (commandName !== 'commitTransaction') {
|
|
778
|
+
session.transaction.transition(TxnState.TRANSACTION_ABORTED);
|
|
779
|
+
if (session.loadBalanced) {
|
|
780
|
+
maybeClearPinnedConnection(session, { force: false });
|
|
781
|
+
}
|
|
782
|
+
} else {
|
|
783
|
+
session.transaction.transition(TxnState.TRANSACTION_COMMITTED);
|
|
784
|
+
}
|
|
785
|
+
} catch (secondAttemptErr) {
|
|
786
|
+
handleEndTransactionError(session, commandName, secondAttemptErr);
|
|
787
|
+
}
|
|
788
|
+
} else {
|
|
789
|
+
handleEndTransactionError(session, commandName, firstAttemptErr);
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
function handleEndTransactionError(
|
|
795
|
+
session: ClientSession,
|
|
796
|
+
commandName: 'abortTransaction' | 'commitTransaction',
|
|
797
|
+
error: Error
|
|
798
|
+
) {
|
|
799
|
+
if (commandName !== 'commitTransaction') {
|
|
800
|
+
session.transaction.transition(TxnState.TRANSACTION_ABORTED);
|
|
801
|
+
if (session.loadBalanced) {
|
|
802
|
+
maybeClearPinnedConnection(session, { force: false });
|
|
803
|
+
}
|
|
804
|
+
// The spec indicates that if the operation times out or fails with a non-retryable error, we should ignore all errors on `abortTransaction`
|
|
805
|
+
return;
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
session.transaction.transition(TxnState.TRANSACTION_COMMITTED);
|
|
809
|
+
if (error instanceof MongoError) {
|
|
810
|
+
if (
|
|
811
|
+
isRetryableWriteError(error) ||
|
|
812
|
+
error instanceof MongoWriteConcernError ||
|
|
813
|
+
isMaxTimeMSExpiredError(error)
|
|
814
|
+
) {
|
|
815
|
+
if (isUnknownTransactionCommitResult(error)) {
|
|
816
|
+
error.addErrorLabel(MongoErrorLabel.UnknownTransactionCommitResult);
|
|
817
|
+
|
|
818
|
+
// per txns spec, must unpin session in this case
|
|
819
|
+
session.unpin({ error });
|
|
820
|
+
}
|
|
821
|
+
} else if (error.hasErrorLabel(MongoErrorLabel.TransientTransactionError)) {
|
|
822
|
+
session.unpin({ error });
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
throw error;
|
|
827
|
+
}
|
|
828
|
+
|
|
843
829
|
/** @public */
|
|
844
830
|
export type ServerSessionId = { id: Binary };
|
|
845
831
|
|
package/src/sort.ts
CHANGED
package/src/timeout.ts
CHANGED
package/src/transactions.ts
CHANGED
|
@@ -2,7 +2,8 @@ import type { Document } from './bson';
|
|
|
2
2
|
import { MongoRuntimeError, MongoTransactionError } from './error';
|
|
3
3
|
import type { CommandOperationOptions } from './operations/command';
|
|
4
4
|
import { ReadConcern, type ReadConcernLike } from './read_concern';
|
|
5
|
-
import {
|
|
5
|
+
import type { ReadPreferenceLike } from './read_preference';
|
|
6
|
+
import { ReadPreference } from './read_preference';
|
|
6
7
|
import type { Server } from './sdam/server';
|
|
7
8
|
import { WriteConcern } from './write_concern';
|
|
8
9
|
|