1
- import { promisify } from 'util' ;
2
-
3
1
import { type BSONSerializeOptions , type Document , EJSON , resolveBSONOptions } from '../bson' ;
4
2
import type { Collection } from '../collection' ;
5
3
import {
6
4
type AnyError ,
7
5
MongoBatchReExecutionError ,
8
6
MONGODB_ERROR_CODES ,
9
7
MongoInvalidArgumentError ,
8
+ MongoRuntimeError ,
10
9
MongoServerError ,
11
10
MongoWriteConcernError
12
11
} from '../error' ;
@@ -22,7 +21,6 @@ import type { Topology } from '../sdam/topology';
22
21
import type { ClientSession } from '../sessions' ;
23
22
import {
24
23
applyRetryableWrites ,
25
- type Callback ,
26
24
getTopology ,
27
25
hasAtomicOperators ,
28
26
maybeAddIdToDocuments ,
@@ -500,86 +498,46 @@ export function mergeBatchResults(
500
498
}
501
499
}
502
500
503
- function executeCommands (
501
+ async function executeCommands (
504
502
bulkOperation : BulkOperationBase ,
505
- options : BulkWriteOptions ,
506
- callback : Callback < BulkWriteResult >
507
- ) {
503
+ options : BulkWriteOptions
504
+ ) : Promise < BulkWriteResult > {
508
505
if ( bulkOperation . s . batches . length === 0 ) {
509
- return callback (
510
- undefined ,
511
- new BulkWriteResult ( bulkOperation . s . bulkResult , bulkOperation . isOrdered )
512
- ) ;
506
+ return new BulkWriteResult ( bulkOperation . s . bulkResult , bulkOperation . isOrdered ) ;
513
507
}
514
508
515
- const batch = bulkOperation . s . batches . shift ( ) as Batch ;
509
+ for ( const batch of bulkOperation . s . batches ) {
510
+ const finalOptions = resolveOptions ( bulkOperation , {
511
+ ...options ,
512
+ ordered : bulkOperation . isOrdered
513
+ } ) ;
516
514
517
- function resultHandler ( err ?: AnyError , result ?: Document ) {
518
- // Error is a driver related error not a bulk op error, return early
519
- if ( err && 'message' in err && ! ( err instanceof MongoWriteConcernError ) ) {
520
- return callback (
521
- new MongoBulkWriteError (
522
- err ,
523
- new BulkWriteResult ( bulkOperation . s . bulkResult , bulkOperation . isOrdered )
524
- )
525
- ) ;
515
+ if ( finalOptions . bypassDocumentValidation !== true ) {
516
+ delete finalOptions . bypassDocumentValidation ;
526
517
}
527
518
528
- if ( err instanceof MongoWriteConcernError ) {
529
- return handleMongoWriteConcernError (
530
- batch ,
531
- bulkOperation . s . bulkResult ,
532
- bulkOperation . isOrdered ,
533
- err ,
534
- callback
535
- ) ;
519
+ // Is the bypassDocumentValidation options specific
520
+ if ( bulkOperation . s . bypassDocumentValidation === true ) {
521
+ finalOptions . bypassDocumentValidation = true ;
536
522
}
537
523
538
- // Merge the results together
539
- mergeBatchResults ( batch , bulkOperation . s . bulkResult , err , result ) ;
540
- const writeResult = new BulkWriteResult ( bulkOperation . s . bulkResult , bulkOperation . isOrdered ) ;
541
- if ( bulkOperation . handleWriteError ( callback , writeResult ) ) return ;
542
-
543
- // Execute the next command in line
544
- executeCommands ( bulkOperation , options , callback ) ;
545
- }
546
-
547
- const finalOptions = resolveOptions ( bulkOperation , {
548
- ...options ,
549
- ordered : bulkOperation . isOrdered
550
- } ) ;
551
-
552
- if ( finalOptions . bypassDocumentValidation !== true ) {
553
- delete finalOptions . bypassDocumentValidation ;
554
- }
555
-
556
- // Set an operationIf if provided
557
- if ( bulkOperation . operationId ) {
558
- resultHandler . operationId = bulkOperation . operationId ;
559
- }
560
-
561
- // Is the bypassDocumentValidation options specific
562
- if ( bulkOperation . s . bypassDocumentValidation === true ) {
563
- finalOptions . bypassDocumentValidation = true ;
564
- }
565
-
566
- // Is the checkKeys option disabled
567
- if ( bulkOperation . s . checkKeys === false ) {
568
- finalOptions . checkKeys = false ;
569
- }
570
-
571
- if ( finalOptions . retryWrites ) {
572
- if ( isUpdateBatch ( batch ) ) {
573
- finalOptions . retryWrites = finalOptions . retryWrites && ! batch . operations . some ( op => op . multi ) ;
524
+ // Is the checkKeys option disabled
525
+ if ( bulkOperation . s . checkKeys === false ) {
526
+ finalOptions . checkKeys = false ;
574
527
}
575
528
576
- if ( isDeleteBatch ( batch ) ) {
577
- finalOptions . retryWrites =
578
- finalOptions . retryWrites && ! batch . operations . some ( op => op . limit === 0 ) ;
529
+ if ( finalOptions . retryWrites ) {
530
+ if ( isUpdateBatch ( batch ) ) {
531
+ finalOptions . retryWrites =
532
+ finalOptions . retryWrites && ! batch . operations . some ( op => op . multi ) ;
533
+ }
534
+
535
+ if ( isDeleteBatch ( batch ) ) {
536
+ finalOptions . retryWrites =
537
+ finalOptions . retryWrites && ! batch . operations . some ( op => op . limit === 0 ) ;
538
+ }
579
539
}
580
- }
581
540
582
- try {
583
541
const operation = isInsertBatch ( batch )
584
542
? new InsertOperation ( bulkOperation . s . namespace , batch . operations , finalOptions )
585
543
: isUpdateBatch ( batch )
@@ -588,38 +546,61 @@ function executeCommands(
588
546
? new DeleteOperation ( bulkOperation . s . namespace , batch . operations , finalOptions )
589
547
: null ;
590
548
591
- if ( operation != null ) {
592
- executeOperation ( bulkOperation . s . collection . client , operation ) . then (
593
- result => resultHandler ( undefined , result ) ,
594
- error => resultHandler ( error )
595
- ) ;
549
+ if ( operation == null ) throw new MongoRuntimeError ( `Unknown batchType: ${ batch . batchType } ` ) ;
550
+
551
+ let thrownError = null ;
552
+ let result ;
553
+ try {
554
+ result = await executeOperation ( bulkOperation . s . collection . client , operation ) ;
555
+ } catch ( error ) {
556
+ thrownError = error ;
557
+ }
558
+
559
+ if ( thrownError != null ) {
560
+ if ( ! ( thrownError instanceof MongoWriteConcernError ) ) {
561
+ // Error is a driver related error not a bulk op error, return early
562
+ throw new MongoBulkWriteError (
563
+ thrownError ,
564
+ new BulkWriteResult ( bulkOperation . s . bulkResult , bulkOperation . isOrdered )
565
+ ) ;
566
+ }
567
+
568
+ if ( thrownError instanceof MongoWriteConcernError ) {
569
+ handleMongoWriteConcernError (
570
+ batch ,
571
+ bulkOperation . s . bulkResult ,
572
+ bulkOperation . isOrdered ,
573
+ thrownError
574
+ ) ;
575
+ }
596
576
}
597
- } catch ( err ) {
598
- // Force top level error
599
- err . ok = 0 ;
600
- // Merge top level error and return
601
- mergeBatchResults ( batch , bulkOperation . s . bulkResult , err , undefined ) ;
602
- callback ( ) ;
577
+
578
+ mergeBatchResults ( batch , bulkOperation . s . bulkResult , thrownError , result ) ;
579
+ const writeResult = new BulkWriteResult ( bulkOperation . s . bulkResult , bulkOperation . isOrdered ) ;
580
+ bulkOperation . handleWriteError ( writeResult ) ;
603
581
}
582
+
583
+ bulkOperation . s . batches . length = 0 ;
584
+
585
+ const writeResult = new BulkWriteResult ( bulkOperation . s . bulkResult , bulkOperation . isOrdered ) ;
586
+ bulkOperation . handleWriteError ( writeResult ) ;
587
+ return writeResult ;
604
588
}
605
589
606
590
function handleMongoWriteConcernError (
607
591
batch : Batch ,
608
592
bulkResult : BulkResult ,
609
593
isOrdered : boolean ,
610
- err : MongoWriteConcernError ,
611
- callback : Callback < BulkWriteResult >
612
- ) {
594
+ err : MongoWriteConcernError
595
+ ) : never {
613
596
mergeBatchResults ( batch , bulkResult , undefined , err . result ) ;
614
597
615
- callback (
616
- new MongoBulkWriteError (
617
- {
618
- message : err . result . writeConcernError . errmsg ,
619
- code : err . result . writeConcernError . code
620
- } ,
621
- new BulkWriteResult ( bulkResult , isOrdered )
622
- )
598
+ throw new MongoBulkWriteError (
599
+ {
600
+ message : err . result . writeConcernError . errmsg ,
601
+ code : err . result . writeConcernError . code
602
+ } ,
603
+ new BulkWriteResult ( bulkResult , isOrdered )
623
604
) ;
624
605
}
625
606
@@ -875,8 +856,6 @@ export interface BulkWriteOptions extends CommandOperationOptions {
875
856
let ?: Document ;
876
857
}
877
858
878
- const executeCommandsAsync = promisify ( executeCommands ) ;
879
-
880
859
/**
881
860
* TODO(NODE-4063)
882
861
* BulkWrites merge complexity is implemented in executeCommands
@@ -895,15 +874,15 @@ export class BulkWriteShimOperation extends AbstractOperation {
895
874
return 'bulkWrite' as const ;
896
875
}
897
876
898
- execute ( _server : Server , session : ClientSession | undefined ) : Promise < any > {
877
+ async execute ( _server : Server , session : ClientSession | undefined ) : Promise < any > {
899
878
if ( this . options . session == null ) {
900
879
// An implicit session could have been created by 'executeOperation'
901
880
// So if we stick it on finalOptions here, each bulk operation
902
881
// will use this same session, it'll be passed in the same way
903
882
// an explicit session would be
904
883
this . options . session = session ;
905
884
}
906
- return executeCommandsAsync ( this . bulkOperation , this . options ) ;
885
+ return await executeCommands ( this . bulkOperation , this . options ) ;
907
886
}
908
887
}
909
888
@@ -1239,33 +1218,26 @@ export abstract class BulkOperationBase {
1239
1218
* Handles the write error before executing commands
1240
1219
* @internal
1241
1220
*/
1242
- handleWriteError ( callback : Callback < BulkWriteResult > , writeResult : BulkWriteResult ) : boolean {
1221
+ handleWriteError ( writeResult : BulkWriteResult ) : void {
1243
1222
if ( this . s . bulkResult . writeErrors . length > 0 ) {
1244
1223
const msg = this . s . bulkResult . writeErrors [ 0 ] . errmsg
1245
1224
? this . s . bulkResult . writeErrors [ 0 ] . errmsg
1246
1225
: 'write operation failed' ;
1247
1226
1248
- callback (
1249
- new MongoBulkWriteError (
1250
- {
1251
- message : msg ,
1252
- code : this . s . bulkResult . writeErrors [ 0 ] . code ,
1253
- writeErrors : this . s . bulkResult . writeErrors
1254
- } ,
1255
- writeResult
1256
- )
1227
+ throw new MongoBulkWriteError (
1228
+ {
1229
+ message : msg ,
1230
+ code : this . s . bulkResult . writeErrors [ 0 ] . code ,
1231
+ writeErrors : this . s . bulkResult . writeErrors
1232
+ } ,
1233
+ writeResult
1257
1234
) ;
1258
-
1259
- return true ;
1260
1235
}
1261
1236
1262
1237
const writeConcernError = writeResult . getWriteConcernError ( ) ;
1263
1238
if ( writeConcernError ) {
1264
- callback ( new MongoBulkWriteError ( writeConcernError , writeResult ) ) ;
1265
- return true ;
1239
+ throw new MongoBulkWriteError ( writeConcernError , writeResult ) ;
1266
1240
}
1267
-
1268
- return false ;
1269
1241
}
1270
1242
1271
1243
abstract addToOperationsList (
0 commit comments