Skip to content

Commit 77209dd

Browse files
committed
PHPC-752: Add maxStalenessMS to ReadPreference class
This adds an options array to the ReadPreference constructor, which accepts a maxStalenessMS option. The option is also exposed via a getter method and in debug output.
1 parent 40a0f52 commit 77209dd

7 files changed

+151
-23
lines changed

php_phongo.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -962,7 +962,7 @@ void php_phongo_read_preference_to_zval(zval *retval, const mongoc_read_prefs_t
962962
const bson_t *tags = mongoc_read_prefs_get_tags(read_prefs);
963963
mongoc_read_mode_t mode = mongoc_read_prefs_get_mode(read_prefs);
964964

965-
array_init_size(retval, 2);
965+
array_init_size(retval, 3);
966966

967967
switch (mode) {
968968
case MONGOC_READ_PRIMARY: ADD_ASSOC_STRING(retval, "mode", "primary"); break;
@@ -987,6 +987,10 @@ void php_phongo_read_preference_to_zval(zval *retval, const mongoc_read_prefs_t
987987
ADD_ASSOC_ZVAL_EX(retval, "tags", state.zchild);
988988
#endif
989989
}
990+
991+
if (mongoc_read_prefs_get_max_staleness_ms(read_prefs) != 0) {
992+
ADD_ASSOC_LONG_EX(retval, "maxStalenessMS", mongoc_read_prefs_get_max_staleness_ms(read_prefs));
993+
}
990994
} /* }}} */
991995

992996
void php_phongo_write_concern_to_zval(zval *retval, const mongoc_write_concern_t *write_concern) /* {{{ */

src/MongoDB/ReadPreference.c

Lines changed: 60 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
#include <ext/standard/info.h>
3535
#include <Zend/zend_interfaces.h>
3636
#include <ext/spl/spl_iterators.h>
37+
/* PHP array helpers */
38+
#include "php_array_api.h"
3739
/* Our Compatability header */
3840
#include "phongo_compat.h"
3941

@@ -46,21 +48,22 @@ PHONGO_API zend_class_entry *php_phongo_readpreference_ce;
4648

4749
zend_object_handlers php_phongo_handler_readpreference;
4850

49-
/* {{{ proto void ReadPreference::__construct(integer $mode[, array $tagSets = array()])
51+
/* {{{ proto void ReadPreference::__construct(integer $mode[, array $tagSets = array()[, array $options = array()]])
5052
Constructs a new ReadPreference */
5153
PHP_METHOD(ReadPreference, __construct)
5254
{
5355
php_phongo_readpreference_t *intern;
5456
zend_error_handling error_handling;
5557
phongo_long mode;
5658
zval *tagSets = NULL;
59+
zval *options = NULL;
5760
SUPPRESS_UNUSED_WARNING(return_value_ptr) SUPPRESS_UNUSED_WARNING(return_value) SUPPRESS_UNUSED_WARNING(return_value_used)
5861

5962

6063
zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling TSRMLS_CC);
6164
intern = Z_READPREFERENCE_OBJ_P(getThis());
6265

63-
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|a!", &mode, &tagSets) == FAILURE) {
66+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|a!a!", &mode, &tagSets, &options) == FAILURE) {
6467
zend_restore_error_handling(&error_handling TSRMLS_CC);
6568
return;
6669
}
@@ -80,28 +83,46 @@ PHP_METHOD(ReadPreference, __construct)
8083
return;
8184
}
8285

83-
switch(ZEND_NUM_ARGS()) {
84-
case 2:
85-
if (tagSets) {
86-
bson_t *tags = bson_new();
86+
if (tagSets) {
87+
bson_t *tags = bson_new();
8788

88-
phongo_zval_to_bson(tagSets, PHONGO_BSON_NONE, (bson_t *)tags, NULL TSRMLS_CC);
89+
phongo_zval_to_bson(tagSets, PHONGO_BSON_NONE, (bson_t *)tags, NULL TSRMLS_CC);
8990

90-
if (!php_phongo_read_preference_tags_are_valid(tags)) {
91-
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "tagSets must be an array of zero or more documents");
92-
bson_destroy(tags);
93-
return;
94-
}
91+
if (!php_phongo_read_preference_tags_are_valid(tags)) {
92+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "tagSets must be an array of zero or more documents");
93+
bson_destroy(tags);
94+
return;
95+
}
96+
97+
if (!bson_empty(tags) && mode == MONGOC_READ_PRIMARY) {
98+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "tagSets may not be used with primary mode");
99+
bson_destroy(tags);
100+
return;
101+
}
102+
103+
mongoc_read_prefs_set_tags(intern->read_preference, tags);
104+
bson_destroy(tags);
105+
}
106+
107+
if (options && php_array_exists(options, "maxStalenessMS")) {
108+
phongo_long maxStalenessMS = php_array_fetchc_long(options, "maxStalenessMS");
95109

96-
if (!bson_empty(tags) && mode == MONGOC_READ_PRIMARY) {
97-
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "tagSets may not be used with primary mode");
98-
bson_destroy(tags);
99-
return;
100-
}
110+
if (maxStalenessMS < 0) {
111+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected maxStalenessMS to be >= 0, %" PHONGO_LONG_FORMAT " given", maxStalenessMS);
112+
return;
113+
}
114+
115+
if (maxStalenessMS > INT32_MAX) {
116+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected maxStalenessMS to be <= %" PRId32 ", %" PHONGO_LONG_FORMAT " given", INT32_MAX, maxStalenessMS);
117+
return;
118+
}
101119

102-
mongoc_read_prefs_set_tags(intern->read_preference, tags);
103-
bson_destroy(tags);
104-
}
120+
if (maxStalenessMS > 0 && mode == MONGOC_READ_PRIMARY) {
121+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "maxStalenessMS may not be used with primary mode");
122+
return;
123+
}
124+
125+
mongoc_read_prefs_set_max_staleness_ms(intern->read_preference, maxStalenessMS);
105126
}
106127

107128
if (!mongoc_read_prefs_is_valid(intern->read_preference)) {
@@ -111,6 +132,23 @@ PHP_METHOD(ReadPreference, __construct)
111132
}
112133
/* }}} */
113134

135+
/* {{{ proto integer ReadPreference::getMaxStalenessMS()
136+
Returns the ReadPreference maxStalenessMS value */
137+
PHP_METHOD(ReadPreference, getMaxStalenessMS)
138+
{
139+
php_phongo_readpreference_t *intern;
140+
SUPPRESS_UNUSED_WARNING(return_value_ptr) SUPPRESS_UNUSED_WARNING(return_value_used)
141+
142+
intern = Z_READPREFERENCE_OBJ_P(getThis());
143+
144+
if (zend_parse_parameters_none() == FAILURE) {
145+
return;
146+
}
147+
148+
RETURN_LONG(mongoc_read_prefs_get_max_staleness_ms(intern->read_preference));
149+
}
150+
/* }}} */
151+
114152
/* {{{ proto integer ReadPreference::getMode()
115153
Returns the ReadPreference mode */
116154
PHP_METHOD(ReadPreference, getMode)
@@ -184,13 +222,15 @@ PHP_METHOD(ReadPreference, bsonSerialize)
184222
ZEND_BEGIN_ARG_INFO_EX(ai_ReadPreference___construct, 0, 0, 1)
185223
ZEND_ARG_INFO(0, mode)
186224
ZEND_ARG_ARRAY_INFO(0, tagSets, 1)
225+
ZEND_ARG_ARRAY_INFO(0, options, 1)
187226
ZEND_END_ARG_INFO()
188227

189228
ZEND_BEGIN_ARG_INFO_EX(ai_ReadPreference_void, 0, 0, 0)
190229
ZEND_END_ARG_INFO()
191230

192231
static zend_function_entry php_phongo_readpreference_me[] = {
193232
PHP_ME(ReadPreference, __construct, ai_ReadPreference___construct, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
233+
PHP_ME(ReadPreference, getMaxStalenessMS, ai_ReadPreference_void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
194234
PHP_ME(ReadPreference, getMode, ai_ReadPreference_void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
195235
PHP_ME(ReadPreference, getTagSets, ai_ReadPreference_void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
196236
PHP_ME(ReadPreference, bsonSerialize, ai_ReadPreference_void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)

tests/readPreference/readpreference-ctor-001.phpt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ MongoDB\Driver\ReadPreference construction
44
<?php
55

66
var_dump(new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_PRIMARY));
7-
var_dump(new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_SECONDARY, array(array("tag" => "one"))));
8-
var_dump(new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_PRIMARY, array()));
7+
var_dump(new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_SECONDARY, [['tag' => 'one']]));
8+
var_dump(new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_PRIMARY, []));
9+
var_dump(new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_SECONDARY, null, ['maxStalenessMS' => 1000]));
910

1011
?>
1112
===DONE===
@@ -31,4 +32,10 @@ object(MongoDB\Driver\ReadPreference)#%d (%d) {
3132
["mode"]=>
3233
string(7) "primary"
3334
}
35+
object(MongoDB\Driver\ReadPreference)#%d (%d) {
36+
["mode"]=>
37+
string(9) "secondary"
38+
["maxStalenessMS"]=>
39+
int(1000)
40+
}
3441
===DONE===

tests/readPreference/readpreference-ctor_error-002.phpt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ echo throws(function() {
1717
new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_SECONDARY, ['invalid']);
1818
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
1919

20+
// Ensure that tagSets is validated before maxStalenessMS option
21+
echo throws(function() {
22+
new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_SECONDARY, ['invalid'], ['maxStalenessMS' => -1]);
23+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
24+
2025
?>
2126
===DONE===
2227
<?php exit(0); ?>
@@ -27,4 +32,6 @@ OK: Got MongoDB\Driver\Exception\InvalidArgumentException
2732
tagSets must be an array of zero or more documents
2833
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
2934
tagSets must be an array of zero or more documents
35+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
36+
tagSets must be an array of zero or more documents
3037
===DONE===
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
MongoDB\Driver\ReadPreference construction (invalid maxStalenessMS)
3+
--FILE--
4+
<?php
5+
6+
require_once __DIR__ . '/../utils/tools.php';
7+
8+
echo throws(function() {
9+
new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_PRIMARY, null, ['maxStalenessMS' => 1000]);
10+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
11+
12+
echo throws(function() {
13+
new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_SECONDARY, null, ['maxStalenessMS' => -1]);
14+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
15+
16+
?>
17+
===DONE===
18+
<?php exit(0); ?>
19+
--EXPECT--
20+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
21+
maxStalenessMS may not be used with primary mode
22+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
23+
Expected maxStalenessMS to be >= 0, -1 given
24+
===DONE===
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
MongoDB\Driver\ReadPreference construction (invalid maxStalenessMS range)
3+
--SKIPIF--
4+
<?php if (8 !== PHP_INT_SIZE) { die('skip Only for 64-bit platform'); } ?>
5+
--FILE--
6+
<?php
7+
8+
require_once __DIR__ . '/../utils/tools.php';
9+
10+
echo throws(function() {
11+
new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_SECONDARY, null, ['maxStalenessMS' => 2147483648]);
12+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
13+
14+
?>
15+
===DONE===
16+
<?php exit(0); ?>
17+
--EXPECT--
18+
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
19+
Expected maxStalenessMS to be <= 2147483647, 2147483648 given
20+
===DONE===
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
MongoDB\Driver\ReadPreference::getMaxStalenessMS()
3+
--FILE--
4+
<?php
5+
6+
require_once __DIR__ . '/../utils/tools.php';
7+
8+
$tests = [
9+
0,
10+
1000,
11+
2147483647,
12+
];
13+
14+
foreach ($tests as $test) {
15+
$rp = new MongoDB\Driver\ReadPreference(MongoDB\Driver\ReadPreference::RP_SECONDARY, null, ['maxStalenessMS' => $test]);
16+
var_dump($rp->getMaxStalenessMS());
17+
}
18+
19+
?>
20+
===DONE===
21+
<?php exit(0); ?>
22+
--EXPECT--
23+
int(0)
24+
int(1000)
25+
int(2147483647)
26+
===DONE===

0 commit comments

Comments
 (0)