Skip to content

Commit 804f383

Browse files
committed
PHPC-1382: Allow applications to set maxTimeMS for commitTransaction
1 parent 74eb111 commit 804f383

File tree

4 files changed

+67
-14
lines changed

4 files changed

+67
-14
lines changed

src/MongoDB/Session.c

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -247,21 +247,50 @@ static PHP_METHOD(Session, getOperationTime)
247247
} /* }}} */
248248

249249
/* Creates a opts structure from an array optionally containing an RP, RC,
250-
* and/or WC object. Returns NULL if no options were found, or there was an
251-
* invalid option. If there was an invalid option or structure, an exception
252-
* will be thrown too. */
250+
* WC object, and/or maxCommitTimeMS int. Returns NULL if no options were found,
251+
* or there was an invalid option. If there was an invalid option or structure,
252+
* an exception will be thrown too. */
253253
mongoc_transaction_opt_t* php_mongodb_session_parse_transaction_options(zval* options TSRMLS_DC)
254254
{
255255
mongoc_transaction_opt_t* opts = NULL;
256256

257+
if (php_array_existsc(options, "maxCommitTimeMS")) {
258+
int64_t max_commit_time_ms = php_array_fetchc_long(options, "maxCommitTimeMS");
259+
260+
if (max_commit_time_ms < 0) {
261+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected \"maxCommitTimeMS\" option to be >= 0, %" PRId64 " given", max_commit_time_ms);
262+
/* Freeing opts is not needed here, as it can't be set yet. The
263+
* code is here to keep it consistent with the others in case more
264+
* options are added before this one. */
265+
if (opts) {
266+
mongoc_transaction_opts_destroy(opts);
267+
}
268+
return NULL;
269+
}
270+
271+
if (max_commit_time_ms > UINT32_MAX) {
272+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected \"maxCommitTimeMS\" option to be <= %" PRIu32 ", %" PRId64 " given", UINT32_MAX, max_commit_time_ms);
273+
/* Freeing opts is not needed here, as it can't be set yet. The
274+
* code is here to keep it consistent with the others in case more
275+
* options are added before this one. */
276+
if (opts) {
277+
mongoc_transaction_opts_destroy(opts);
278+
}
279+
return NULL;
280+
}
281+
282+
if (!opts) {
283+
opts = mongoc_transaction_opts_new();
284+
}
285+
286+
mongoc_transaction_opts_set_max_commit_time_ms(opts, max_commit_time_ms);
287+
}
288+
257289
if (php_array_existsc(options, "readConcern")) {
258290
zval* read_concern = php_array_fetchc(options, "readConcern");
259291

260292
if (Z_TYPE_P(read_concern) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(read_concern), php_phongo_readconcern_ce TSRMLS_CC)) {
261293
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected \"readConcern\" option to be %s, %s given", ZSTR_VAL(php_phongo_readconcern_ce->name), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(read_concern));
262-
/* Freeing opts is not needed here, as it can't be set yet. The
263-
* code is here to keep it consistent with the others in case more
264-
* options are added before this one. */
265294
if (opts) {
266295
mongoc_transaction_opts_destroy(opts);
267296
}

tests/session/session-startTransaction_error-002.phpt

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@ $manager = new MongoDB\Driver\Manager(URI);
1313
$session = $manager->startSession();
1414

1515
$options = [
16-
[ 'readConcern' => 42 ],
16+
[ 'maxCommitTimeMS' => -1 ],
17+
[ 'readConcern' => 42 ],
1718
[ 'readConcern' => new stdClass ],
1819
[ 'readConcern' => new \MongoDB\Driver\WriteConcern( 2 ) ],
19-
[ 'readPreference' => 42 ],
20+
[ 'readPreference' => 42 ],
2021
[ 'readPreference' => new stdClass ],
2122
[ 'readPreference' => new \MongoDB\Driver\ReadConcern( \MongoDB\Driver\ReadConcern::LOCAL ) ],
22-
[ 'writeConcern' => 42 ],
23+
[ 'writeConcern' => 42 ],
2324
[ 'writeConcern' => new stdClass ],
2425
[ 'writeConcern' => new \MongoDB\Driver\ReadPreference( \MongoDB\Driver\ReadPreference::RP_SECONDARY ) ],
2526

@@ -43,11 +44,17 @@ foreach ($options as $txnOptions) {
4344
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
4445
}
4546

47+
echo raises(function() use ($session) {
48+
$session->startTransaction([ 'maxCommitTimeMS' => new stdClass ]);
49+
}, E_NOTICE), "\n";
50+
4651
?>
4752
===DONE===
4853
<?php exit(0); ?>
4954
--EXPECTF--
5055
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
56+
Expected "maxCommitTimeMS" option to be >= 0, -1 given
57+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
5158
Expected "readConcern" option to be MongoDB\Driver\ReadConcern, int%S given
5259
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
5360
Expected "readConcern" option to be MongoDB\Driver\ReadConcern, stdClass given
@@ -71,4 +78,6 @@ OK: Got MongoDB\Driver\Exception\InvalidArgumentException
7178
Expected "writeConcern" option to be MongoDB\Driver\WriteConcern, MongoDB\Driver\ReadPreference given
7279
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
7380
Expected "writeConcern" option to be MongoDB\Driver\WriteConcern, MongoDB\Driver\ReadPreference given
81+
OK: Got E_NOTICE
82+
Object of class stdClass could not be converted to int
7483
===DONE===

tests/session/session_error-001.phpt

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@ require_once __DIR__ . "/../utils/basic.inc";
77
$manager = new MongoDB\Driver\Manager();
88

99
$options = [
10-
[ 'readConcern' => 42 ],
10+
[ 'maxCommitTimeMS' => -1 ],
11+
[ 'readConcern' => 42 ],
1112
[ 'readConcern' => new stdClass ],
1213
[ 'readConcern' => new \MongoDB\Driver\WriteConcern( 2 ) ],
13-
[ 'readPreference' => 42 ],
14+
[ 'readPreference' => 42 ],
1415
[ 'readPreference' => new stdClass ],
1516
[ 'readPreference' => new \MongoDB\Driver\ReadConcern( \MongoDB\Driver\ReadConcern::LOCAL ) ],
16-
[ 'writeConcern' => 42 ],
17+
[ 'writeConcern' => 42 ],
1718
[ 'writeConcern' => new stdClass ],
1819
[ 'writeConcern' => new \MongoDB\Driver\ReadPreference( \MongoDB\Driver\ReadPreference::RP_SECONDARY ) ],
1920

@@ -36,17 +37,25 @@ $options = [
3637

3738
foreach ($options as $txnOptions) {
3839
echo throws(function() use ($manager, $txnOptions) {
39-
$session = $manager->startSession([
40+
$manager->startSession([
4041
'defaultTransactionOptions' => $txnOptions
4142
]);
4243
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
4344
}
4445

46+
echo raises(function() use ($manager) {
47+
$manager->startSession([
48+
'defaultTransactionOptions' => [ 'maxCommitTimeMS' => new stdClass ]
49+
]);
50+
}, E_NOTICE), "\n";
51+
4552
?>
4653
===DONE===
4754
<?php exit(0); ?>
4855
--EXPECTF--
4956
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
57+
Expected "maxCommitTimeMS" option to be >= 0, -1 given
58+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
5059
Expected "readConcern" option to be MongoDB\Driver\ReadConcern, int%S given
5160
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
5261
Expected "readConcern" option to be MongoDB\Driver\ReadConcern, stdClass given
@@ -74,4 +83,6 @@ OK: Got MongoDB\Driver\Exception\InvalidArgumentException
7483
Expected "defaultTransactionOptions" option to be an array, int%S given
7584
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
7685
Expected "defaultTransactionOptions" option to be an array, stdClass given
86+
OK: Got E_NOTICE
87+
Object of class stdClass could not be converted to int
7788
===DONE===

tests/utils/tools.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,8 @@ function severityToString($type) {
518518
switch($type) {
519519
case E_WARNING:
520520
return "E_WARNING";
521+
case E_NOTICE:
522+
return "E_NOTICE";
521523
default:
522524
return "Some other #_$type";
523525
}
@@ -531,6 +533,8 @@ function raises($function, $type, $infunction = null) {
531533
try {
532534
$function();
533535
} catch(Exception $e) {
536+
$exceptionname = get_class($e);
537+
534538
if ($e instanceof ErrorException && $e->getSeverity() & $type) {
535539
if ($infunction) {
536540
$trace = $e->getTrace();
@@ -551,7 +555,7 @@ function raises($function, $type, $infunction = null) {
551555
return $e->getMessage();
552556
}
553557

554-
echo "FAILED: Expected $exceptionname thrown!\n";
558+
printf("FAILED: Expected %s thrown!\n", ErrorException::class);
555559
restore_error_handler();
556560
}
557561
function throws($function, $exceptionname, $infunction = null) {

0 commit comments

Comments
 (0)