11import { type Document } from 'bson' ;
22
33import { ClientBulkWriteCursor } from '../../cursor/client_bulk_write_cursor' ;
4- import { MongoClientBulkWriteExecutionError } from '../../error' ;
4+ import { MongoClientBulkWriteExecutionError , MongoWriteConcernError } from '../../error' ;
55import { type MongoClient } from '../../mongo_client' ;
66import { WriteConcern } from '../../write_concern' ;
77import { executeOperation } from '../execute_operation' ;
@@ -10,7 +10,8 @@ import { type ClientBulkWriteCommand, ClientBulkWriteCommandBuilder } from './co
1010import {
1111 type AnyClientBulkWriteModel ,
1212 type ClientBulkWriteOptions ,
13- type ClientBulkWriteResult
13+ type ClientBulkWriteResult ,
14+ MongoClientBulkWriteError
1415} from './common' ;
1516import { ClientBulkWriteResultsMerger } from './results_merger' ;
1617
@@ -34,9 +35,13 @@ export class ClientBulkWriteExecutor {
3435 operations : AnyClientBulkWriteModel [ ] ,
3536 options ?: ClientBulkWriteOptions
3637 ) {
38+ if ( operations . length === 0 ) {
39+ throw new MongoClientBulkWriteExecutionError ( 'No client bulk write models were provided.' ) ;
40+ }
41+
3742 this . client = client ;
3843 this . operations = operations ;
39- this . options = { ...options } ;
44+ this . options = { ordered : true , ...options } ;
4045
4146 // If no write concern was provided, we inherit one from the client.
4247 if ( ! this . options . writeConcern ) {
@@ -96,12 +101,46 @@ async function executeAcknowledged(
96101 let currentBatchOffset = 0 ;
97102 for ( const command of commands ) {
98103 const cursor = new ClientBulkWriteCursor ( client , command , options ) ;
99- const docs = await cursor . toArray ( ) ;
104+ let docs = [ ] ;
105+ let writeConcernErrorResult ;
106+ try {
107+ docs = await cursor . toArray ( ) ;
108+ } catch ( error ) {
109+ // Write concern errors are recorded in the writeConcernErrors field on MongoClientBulkWriteError.
110+ // When a write concern error is encountered, it should not terminate execution of the bulk write
111+ // for either ordered or unordered bulk writes. However, drivers MUST throw an exception at the end
112+ // of execution if any write concern errors were observed.
113+ if ( error instanceof MongoWriteConcernError ) {
114+ const result = error . result ;
115+ writeConcernErrorResult = {
116+ insertedCount : result . nInserted ,
117+ upsertedCount : result . nUpserted ,
118+ matchedCount : result . nMatched ,
119+ modifiedCount : result . nModified ,
120+ deletedCount : result . nDeleted ,
121+ writeConcernError : result . writeConcernError
122+ } ;
123+ docs = result . cursor . firstBatch ;
124+ } else {
125+ throw error ;
126+ }
127+ }
128+ // Note if we have a write concern error there will be no cursor response present.
129+ const response = writeConcernErrorResult ?? cursor . response ;
100130 const operations = command . ops . documents ;
101- resultsMerger . merge ( currentBatchOffset , operations , cursor . response , docs ) ;
131+ resultsMerger . merge ( currentBatchOffset , operations , response , docs ) ;
102132 // Set the new batch index so we can back back to the index in the original models.
103133 currentBatchOffset += operations . length ;
104134 }
135+
136+ if ( resultsMerger . writeConcernErrors . length > 0 ) {
137+ const error = new MongoClientBulkWriteError ( {
138+ message : 'Mongo client bulk write encountered write concern errors during execution.'
139+ } ) ;
140+ error . writeConcernErrors = resultsMerger . writeConcernErrors ;
141+ error . partialResult = resultsMerger . result ;
142+ throw error ;
143+ }
105144 return resultsMerger . result ;
106145}
107146
0 commit comments