Skip to content

Commit 1d70e1a

Browse files
committed
PHPC-1683: Collect WCE error labels in libmongoc bulk write replies
Also adds additional type and error checking to phongo_exception_append_error_labels.
1 parent 0962b42 commit 1d70e1a

File tree

2 files changed

+59
-7
lines changed

2 files changed

+59
-7
lines changed

php_phongo.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,10 @@ static int phongo_exception_append_error_labels(zval* labels, const bson_iter_t*
200200
bson_iter_t error_labels;
201201
uint32_t label_count = 0;
202202

203-
bson_iter_recurse(iter, &error_labels);
203+
if (!BSON_ITER_HOLDS_ARRAY(iter) || !bson_iter_recurse(iter, &error_labels)) {
204+
return label_count;
205+
}
206+
204207
while (bson_iter_next(&error_labels)) {
205208
if (BSON_ITER_HOLDS_UTF8(&error_labels)) {
206209
const char* error_label;
@@ -217,7 +220,7 @@ static int phongo_exception_append_error_labels(zval* labels, const bson_iter_t*
217220

218221
static void phongo_exception_add_error_labels(const bson_t* reply)
219222
{
220-
bson_iter_t iter;
223+
bson_iter_t iter, child;
221224
zval labels;
222225
uint32_t label_count = 0;
223226

@@ -231,12 +234,20 @@ static void phongo_exception_add_error_labels(const bson_t* reply)
231234
label_count += phongo_exception_append_error_labels(&labels, &iter);
232235
}
233236

234-
if (bson_iter_init_find(&iter, reply, "writeConcernError")) {
235-
bson_iter_t write_concern_error_iter;
237+
if (bson_iter_init_find(&iter, reply, "writeConcernError") && BSON_ITER_HOLDS_DOCUMENT(&iter) &&
238+
bson_iter_recurse(&iter, &child) && bson_iter_find(&child, "errorLabels")) {
239+
label_count += phongo_exception_append_error_labels(&labels, &child);
240+
}
241+
242+
/* mongoc_write_result_t always reports writeConcernErrors in an array, so
243+
* we must iterate this to collect WCE labels for BulkWrite replies. */
244+
if (bson_iter_init_find(&iter, reply, "writeConcernErrors") && BSON_ITER_HOLDS_ARRAY(&iter) && bson_iter_recurse(&iter, &child)) {
245+
bson_iter_t wce;
236246

237-
bson_iter_recurse(&iter, &write_concern_error_iter);
238-
if (bson_iter_find(&write_concern_error_iter, "errorLabels")) {
239-
label_count += phongo_exception_append_error_labels(&labels, &write_concern_error_iter);
247+
while (bson_iter_next(&child)) {
248+
if (BSON_ITER_HOLDS_DOCUMENT(&child) && bson_iter_recurse(&child, &wce) && bson_iter_find(&wce, "errorLabels")) {
249+
label_count += phongo_exception_append_error_labels(&labels, &wce);
250+
}
240251
}
241252
}
242253

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
--TEST--
2+
MongoDB\Driver\Exception\BulkWriteException::hasErrorLabel() with writeConcernError
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
5+
<?php skip_if_not_live(); ?>
6+
<?php skip_if_no_failcommand_failpoint(); ?>
7+
<?php skip_if_not_clean(); ?>
8+
--FILE--
9+
<?php
10+
require_once __DIR__ . "/../utils/basic.inc";
11+
12+
// Disable retryWrites since we want to check for a RetryableWriteError error label
13+
$manager = new MongoDB\Driver\Manager(URI, ['retryWrites' => false]);
14+
15+
// Select a specific server for future operations to avoid mongos switching in sharded clusters
16+
$server = $manager->selectServer(new \MongoDB\Driver\ReadPreference('primary'));
17+
18+
configureTargetedFailPoint($server, 'failCommand', [ 'times' => 1 ], [
19+
'failCommands' => ['insert'],
20+
'writeConcernError' => [
21+
'code' => 91,
22+
'errmsg' => 'Replication is being shut down',
23+
'errorLabels' => ['RetryableWriteError'],
24+
],
25+
]);
26+
27+
$bulk = new MongoDB\Driver\BulkWrite;
28+
$bulk->insert(['x' => 1]);
29+
30+
try {
31+
$server->executeBulkWrite(NS, $bulk);
32+
} catch (MongoDB\Driver\Exception\BulkWriteException $e) {
33+
var_dump($e->hasErrorLabel('RetryableWriteError'));
34+
}
35+
36+
?>
37+
===DONE===
38+
<?php exit(0); ?>
39+
--EXPECT--
40+
bool(true)
41+
===DONE===

0 commit comments

Comments
 (0)