Skip to content

Commit 145ac6d

Browse files
committed
PHPC-2493: Revise error handling for mongoc_bulkwrite_execute
1 parent df6512e commit 145ac6d

File tree

1 file changed

+33
-12
lines changed

1 file changed

+33
-12
lines changed

src/phongo_execute.c

+33-12
Original file line numberDiff line numberDiff line change
@@ -368,21 +368,42 @@ bool phongo_execute_bulkwritecommand(zval* manager, php_phongo_bulkwritecommand_
368368

369369
bwcr = phongo_bulkwritecommandresult_init(return_value, &bw_ret, manager);
370370

371+
/* Error handling for mongoc_bulkwrite_execute differs significantly from
372+
* mongoc_bulk_operation_execute.
373+
*
374+
* - There may or may not be a top-level error. Top-level errors include
375+
* both logical errors (invalid arguments) and runtime errors (e.g. server
376+
* selection failure). A bulk write fails due to write or write concern
377+
* errors will typically not have a top-level error.
378+
*
379+
* - There may or may not be an error reply document. This document could be
380+
* the response of a failed bulkWrite command, but it may also originate
381+
* from libmongoc (e.g. server selection, appending a session, iterating
382+
* BSON). This function only uses it to extrapolate error labels and it is
383+
* otherwise accessible to the user through BulkWriteCommandResult.
384+
*
385+
* - InvalidArgumentException may be thrown directly for a basic top-level
386+
* error (assuming BulkWriteCommandResult would also be irrelevant).
387+
* Otherwise, BulkWriteCommandException is thrown with an attached
388+
* BulkWriteCommandResult that collects any error reply, write errors, and
389+
* write concern errors, along with a possible partial write result.
390+
*/
371391
if (bw_ret.exc) {
372392
success = false;
373393
bson_error_t error = { 0 };
394+
const bson_t *error_reply = mongoc_bulkwriteexception_errorreply(bw_ret.exc);
374395

375-
// Check if there is a top-level error
396+
// Consult any top-level error to throw the first exception
376397
if (mongoc_bulkwriteexception_error(bw_ret.exc, &error)) {
377-
phongo_throw_exception_from_bson_error_t_and_reply(&error, mongoc_bulkwriteexception_errorreply(bw_ret.exc));
398+
phongo_throw_exception_from_bson_error_t_and_reply(&error, error_reply);
378399
}
379400

380401
/* Unlike mongoc_bulk_operation_execute, mongoc_bulkwrite_execute may
381-
* report COMMAND_INVALID_ARG alongside a partial result (CDRIVER-5842).
382-
* If there is no result, we can throw InvalidArgumentException without
383-
* proxying it behind a BulkWriteException. */
384-
if (!bw_ret.res && error.domain == MONGOC_ERROR_COMMAND && error.code == MONGOC_ERROR_COMMAND_INVALID_ARG) {
385-
// TODO: Do we care about other mongoc_bulkwriteexception_t fields?
402+
* report MONGOC_ERROR_COMMAND_INVALID_ARG alongside a partial result
403+
* (CDRIVER-5842). Throw InvalidArgumentException directly iff there is
404+
* neither a partial write result nor an error reply (we can assume
405+
* there are no write or write concern errors for this case). */
406+
if (EG(exception) && EG(exception)->ce == php_phongo_invalidargumentexception_ce && !bw_ret.res && !error_reply) {
386407
goto cleanup;
387408
}
388409

@@ -393,14 +414,14 @@ bool phongo_execute_bulkwritecommand(zval* manager, php_phongo_bulkwritecommand_
393414
zend_throw_exception(php_phongo_bulkwritecommandexception_ce, message, 0);
394415
efree(message);
395416
} else {
396-
// TODO: Determine appropriate message w/o top-level error
397417
zend_throw_exception(php_phongo_bulkwritecommandexception_ce, "Bulk write failed", 0);
398418
}
399419

400-
/* Ensure error labels are added to the final BulkWriteCommandException. If a
401-
* previous exception was also thrown, error labels will already have
402-
* been added by phongo_throw_exception_from_bson_error_t_and_reply. */
403-
phongo_exception_add_error_labels(mongoc_bulkwriteexception_errorreply(bw_ret.exc));
420+
/* Ensure error labels are added to the final BulkWriteCommandException.
421+
* If RuntimeException was previously thrown, labels may also have been
422+
* added to it by phongo_throw_exception_from_bson_error_t_and_reply. */
423+
phongo_exception_add_error_labels(error_reply);
424+
404425
phongo_add_exception_prop(ZEND_STRL("bulkWriteCommandResult"), return_value);
405426
}
406427

0 commit comments

Comments
 (0)