Skip to content

Commit acc9ea8

Browse files
authored
CDRIVER-4099 Support mongos redirection during retryable operations (#1529)
* Fix position of mock server port number info log message * Add tests for mongos deprioritization during retryable operations * Add support for mongos deprioritization during retryable operations
1 parent 9fa6f2e commit acc9ea8

30 files changed

+1370
-151
lines changed

src/libmongoc/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,7 @@ set (SOURCES ${SOURCES}
566566
${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-cursor-array.c
567567
${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-database.c
568568
${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-error.c
569+
${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-deprioritized-servers.c
569570
${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-flags.c
570571
${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-find-and-modify.c
571572
${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-generation-map.c
@@ -1039,6 +1040,7 @@ set (test-libmongoc-sources
10391040
${PROJECT_SOURCE_DIR}/tests/test-mongoc-read-concern.c
10401041
${PROJECT_SOURCE_DIR}/tests/test-mongoc-read-prefs.c
10411042
${PROJECT_SOURCE_DIR}/tests/test-mongoc-read-write-concern.c
1043+
${PROJECT_SOURCE_DIR}/tests/test-mongoc-retryability-helpers.c
10421044
${PROJECT_SOURCE_DIR}/tests/test-mongoc-retryable-reads.c
10431045
${PROJECT_SOURCE_DIR}/tests/test-mongoc-retryable-writes.c
10441046
${PROJECT_SOURCE_DIR}/tests/test-mongoc-sample-commands.c

src/libmongoc/src/mongoc/mongoc-bulk-operation.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -816,7 +816,7 @@ mongoc_bulk_operation_execute (mongoc_bulk_operation_t *bulk, /* IN */
816816
error);
817817
} else {
818818
server_stream = mongoc_cluster_stream_for_writes (
819-
cluster, bulk->session, reply, error);
819+
cluster, bulk->session, NULL, reply, error);
820820
}
821821

822822
if (!server_stream) {

src/libmongoc/src/mongoc/mongoc-change-stream.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,8 +288,12 @@ _make_cursor (mongoc_change_stream_t *stream)
288288
goto cleanup;
289289
}
290290

291-
server_stream = mongoc_cluster_stream_for_reads (
292-
&stream->client->cluster, stream->read_prefs, cs, &reply, &stream->err);
291+
server_stream = mongoc_cluster_stream_for_reads (&stream->client->cluster,
292+
stream->read_prefs,
293+
cs,
294+
NULL,
295+
&reply,
296+
&stream->err);
293297
if (!server_stream) {
294298
bson_destroy (&stream->err_doc);
295299
bson_copy_to (&reply, &stream->err_doc);

src/libmongoc/src/mongoc/mongoc-client-session.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1104,8 +1104,12 @@ mongoc_client_session_start_transaction (mongoc_client_session_t *session,
11041104
BSON_ASSERT (session);
11051105

11061106
ret = true;
1107-
server_stream = mongoc_cluster_stream_for_writes (
1108-
&session->client->cluster, session, NULL /* reply */, error);
1107+
server_stream =
1108+
mongoc_cluster_stream_for_writes (&session->client->cluster,
1109+
session,
1110+
NULL /* deprioritized servers */,
1111+
NULL /* reply */,
1112+
error);
11091113
if (!server_stream) {
11101114
ret = false;
11111115
GOTO (done);

src/libmongoc/src/mongoc/mongoc-client.c

Lines changed: 52 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1727,15 +1727,26 @@ _mongoc_client_retryable_write_command_with_stream (
17271727
_mongoc_write_error_get_type (reply) == MONGOC_WRITE_ERR_RETRY) {
17281728
bson_error_t ignored_error;
17291729

1730-
/* each write command may be retried at most once */
1730+
// The write command may be retried at most once.
17311731
is_retryable = false;
17321732

1733-
if (retry_server_stream) {
1734-
mongoc_server_stream_cleanup (retry_server_stream);
1735-
}
1733+
{
1734+
mongoc_deprioritized_servers_t *const ds =
1735+
mongoc_deprioritized_servers_new ();
17361736

1737-
retry_server_stream = mongoc_cluster_stream_for_writes (
1738-
&client->cluster, parts->assembled.session, NULL, &ignored_error);
1737+
mongoc_deprioritized_servers_add_if_sharded (
1738+
ds, server_stream->topology_type, server_stream->sd);
1739+
1740+
BSON_ASSERT (!retry_server_stream);
1741+
retry_server_stream =
1742+
mongoc_cluster_stream_for_writes (&client->cluster,
1743+
parts->assembled.session,
1744+
ds,
1745+
NULL,
1746+
&ignored_error);
1747+
1748+
mongoc_deprioritized_servers_destroy (ds);
1749+
}
17391750

17401751
if (retry_server_stream) {
17411752
parts->assembled.server_stream = retry_server_stream;
@@ -1820,16 +1831,29 @@ _mongoc_client_retryable_read_command_with_stream (
18201831
/* each read command may be retried at most once */
18211832
is_retryable = false;
18221833

1823-
if (retry_server_stream) {
1824-
mongoc_server_stream_cleanup (retry_server_stream);
1825-
}
1834+
{
1835+
mongoc_deprioritized_servers_t *const ds =
1836+
mongoc_deprioritized_servers_new ();
18261837

1827-
retry_server_stream =
1828-
mongoc_cluster_stream_for_reads (&client->cluster,
1829-
parts->read_prefs,
1830-
parts->assembled.session,
1831-
NULL,
1832-
&ignored_error);
1838+
if (retry_server_stream) {
1839+
mongoc_deprioritized_servers_add_if_sharded (
1840+
ds, retry_server_stream->topology_type, retry_server_stream->sd);
1841+
mongoc_server_stream_cleanup (retry_server_stream);
1842+
} else {
1843+
mongoc_deprioritized_servers_add_if_sharded (
1844+
ds, server_stream->topology_type, server_stream->sd);
1845+
}
1846+
1847+
retry_server_stream =
1848+
mongoc_cluster_stream_for_reads (&client->cluster,
1849+
parts->read_prefs,
1850+
parts->assembled.session,
1851+
ds,
1852+
NULL,
1853+
&ignored_error);
1854+
1855+
mongoc_deprioritized_servers_destroy (ds);
1856+
}
18331857

18341858
if (retry_server_stream) {
18351859
parts->assembled.server_stream = retry_server_stream;
@@ -1918,8 +1942,8 @@ mongoc_client_command_simple (mongoc_client_t *client,
19181942
* configuration. The generic command method SHOULD allow an optional read
19191943
* preference argument."
19201944
*/
1921-
server_stream =
1922-
mongoc_cluster_stream_for_reads (cluster, read_prefs, NULL, reply, error);
1945+
server_stream = mongoc_cluster_stream_for_reads (
1946+
cluster, read_prefs, NULL, NULL, reply, error);
19231947

19241948
if (server_stream) {
19251949
ret = _mongoc_client_command_with_stream (
@@ -2074,10 +2098,10 @@ _mongoc_client_command_with_opts (mongoc_client_t *client,
20742098
}
20752099
} else if (parts.is_write_command) {
20762100
server_stream =
2077-
mongoc_cluster_stream_for_writes (cluster, cs, reply_ptr, error);
2101+
mongoc_cluster_stream_for_writes (cluster, cs, NULL, reply_ptr, error);
20782102
} else {
2079-
server_stream =
2080-
mongoc_cluster_stream_for_reads (cluster, prefs, cs, reply_ptr, error);
2103+
server_stream = mongoc_cluster_stream_for_reads (
2104+
cluster, prefs, cs, NULL, reply_ptr, error);
20812105
}
20822106

20832107
if (!server_stream) {
@@ -2622,6 +2646,7 @@ mongoc_client_kill_cursor (mongoc_client_t *client, int64_t cursor_id)
26222646
MONGOC_SS_WRITE,
26232647
read_prefs,
26242648
NULL /* chosen read mode */,
2649+
NULL /* deprioritized servers */,
26252650
topology->local_threshold_msec);
26262651

26272652
if (selected_server) {
@@ -3060,8 +3085,13 @@ _mongoc_client_end_sessions (mongoc_client_t *client)
30603085

30613086
while (!mongoc_server_session_pool_is_empty (t->session_pool)) {
30623087
prefs = mongoc_read_prefs_new (MONGOC_READ_PRIMARY_PREFERRED);
3063-
server_id = mongoc_topology_select_server_id (
3064-
t, MONGOC_SS_READ, prefs, NULL /* chosen read mode */, &error);
3088+
server_id =
3089+
mongoc_topology_select_server_id (t,
3090+
MONGOC_SS_READ,
3091+
prefs,
3092+
NULL /* chosen read mode */,
3093+
NULL /* deprioritized servers */,
3094+
&error);
30653095

30663096
mongoc_read_prefs_destroy (prefs);
30673097
if (!server_id) {

src/libmongoc/src/mongoc/mongoc-cluster-private.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "mongoc-scram-private.h"
3939
#include "mongoc-cmd-private.h"
4040
#include "mongoc-crypto-private.h"
41+
#include "mongoc-deprioritized-servers-private.h"
4142

4243
BSON_BEGIN_DECLS
4344

@@ -121,6 +122,7 @@ mongoc_server_stream_t *
121122
mongoc_cluster_stream_for_reads (mongoc_cluster_t *cluster,
122123
const mongoc_read_prefs_t *read_prefs,
123124
mongoc_client_session_t *cs,
125+
const mongoc_deprioritized_servers_t *ds,
124126
bson_t *reply,
125127
bson_error_t *error);
126128

@@ -138,6 +140,7 @@ mongoc_cluster_stream_for_reads (mongoc_cluster_t *cluster,
138140
mongoc_server_stream_t *
139141
mongoc_cluster_stream_for_writes (mongoc_cluster_t *cluster,
140142
mongoc_client_session_t *cs,
143+
const mongoc_deprioritized_servers_t *ds,
141144
bson_t *reply,
142145
bson_error_t *error);
143146

src/libmongoc/src/mongoc/mongoc-cluster.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2794,6 +2794,7 @@ _mongoc_cluster_select_server_id (mongoc_client_session_t *cs,
27942794
mongoc_ss_optype_t optype,
27952795
const mongoc_read_prefs_t *read_prefs,
27962796
bool *must_use_primary,
2797+
const mongoc_deprioritized_servers_t *ds,
27972798
bson_error_t *error)
27982799
{
27992800
BSON_ASSERT (cs || true);
@@ -2808,14 +2809,14 @@ _mongoc_cluster_select_server_id (mongoc_client_session_t *cs,
28082809
server_id = cs->server_id;
28092810
if (!server_id) {
28102811
server_id = mongoc_topology_select_server_id (
2811-
topology, optype, read_prefs, must_use_primary, error);
2812+
topology, optype, read_prefs, must_use_primary, ds, error);
28122813
if (server_id) {
28132814
_mongoc_client_session_pin (cs, server_id);
28142815
}
28152816
}
28162817
} else {
28172818
server_id = mongoc_topology_select_server_id (
2818-
topology, optype, read_prefs, must_use_primary, error);
2819+
topology, optype, read_prefs, must_use_primary, ds, error);
28192820
/* Transactions Spec: Additionally, any non-transaction operation using a
28202821
* pinned ClientSession MUST unpin the session and the operation MUST
28212822
* perform normal server selection. */
@@ -2851,6 +2852,7 @@ _mongoc_cluster_stream_for_optype (mongoc_cluster_t *cluster,
28512852
const mongoc_read_prefs_t *read_prefs,
28522853
mongoc_client_session_t *cs,
28532854
bool is_retryable,
2855+
const mongoc_deprioritized_servers_t *ds,
28542856
bson_t *reply,
28552857
bson_error_t *error)
28562858
{
@@ -2870,7 +2872,7 @@ _mongoc_cluster_stream_for_optype (mongoc_cluster_t *cluster,
28702872
BSON_ASSERT (cluster);
28712873

28722874
server_id = _mongoc_cluster_select_server_id (
2873-
cs, topology, optype, read_prefs, &must_use_primary, error);
2875+
cs, topology, optype, read_prefs, &must_use_primary, ds, error);
28742876

28752877
if (!server_id) {
28762878
if (reply) {
@@ -2883,7 +2885,7 @@ _mongoc_cluster_stream_for_optype (mongoc_cluster_t *cluster,
28832885
if (!mongoc_cluster_check_interval (cluster, server_id)) {
28842886
/* Server Selection Spec: try once more */
28852887
server_id = _mongoc_cluster_select_server_id (
2886-
cs, topology, optype, read_prefs, &must_use_primary, error);
2888+
cs, topology, optype, read_prefs, &must_use_primary, ds, error);
28872889

28882890
if (!server_id) {
28892891
if (reply) {
@@ -2967,6 +2969,7 @@ mongoc_server_stream_t *
29672969
mongoc_cluster_stream_for_reads (mongoc_cluster_t *cluster,
29682970
const mongoc_read_prefs_t *read_prefs,
29692971
mongoc_client_session_t *cs,
2972+
const mongoc_deprioritized_servers_t *ds,
29702973
bson_t *reply,
29712974
bson_error_t *error)
29722975
{
@@ -2979,21 +2982,28 @@ mongoc_cluster_stream_for_reads (mongoc_cluster_t *cluster,
29792982
const bool is_retryable = mongoc_uri_get_option_as_bool (
29802983
cluster->uri, MONGOC_URI_RETRYREADS, MONGOC_DEFAULT_RETRYREADS);
29812984

2982-
return _mongoc_cluster_stream_for_optype (
2983-
cluster, MONGOC_SS_READ, prefs_override, cs, is_retryable, reply, error);
2985+
return _mongoc_cluster_stream_for_optype (cluster,
2986+
MONGOC_SS_READ,
2987+
prefs_override,
2988+
cs,
2989+
is_retryable,
2990+
ds,
2991+
reply,
2992+
error);
29842993
}
29852994

29862995
mongoc_server_stream_t *
29872996
mongoc_cluster_stream_for_writes (mongoc_cluster_t *cluster,
29882997
mongoc_client_session_t *cs,
2998+
const mongoc_deprioritized_servers_t *ds,
29892999
bson_t *reply,
29903000
bson_error_t *error)
29913001
{
29923002
const bool is_retryable = mongoc_uri_get_option_as_bool (
29933003
cluster->uri, MONGOC_URI_RETRYWRITES, MONGOC_DEFAULT_RETRYWRITES);
29943004

29953005
return _mongoc_cluster_stream_for_optype (
2996-
cluster, MONGOC_SS_WRITE, NULL, cs, is_retryable, reply, error);
3006+
cluster, MONGOC_SS_WRITE, NULL, cs, is_retryable, ds, reply, error);
29973007
}
29983008

29993009
mongoc_server_stream_t *
@@ -3015,6 +3025,7 @@ mongoc_cluster_stream_for_aggr_with_write (
30153025
prefs_override,
30163026
cs,
30173027
is_retryable,
3028+
NULL,
30183029
reply,
30193030
error);
30203031
}

src/libmongoc/src/mongoc/mongoc-collection.c

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ _mongoc_collection_write_command_execute (
5959
ENTRY;
6060

6161
server_stream = mongoc_cluster_stream_for_writes (
62-
&collection->client->cluster, cs, NULL, &result->error);
62+
&collection->client->cluster, cs, NULL, NULL, &result->error);
6363

6464
if (!server_stream) {
6565
/* result->error has been filled out */
@@ -97,6 +97,7 @@ _mongoc_collection_write_command_execute_idl (
9797
server_stream =
9898
mongoc_cluster_stream_for_writes (&collection->client->cluster,
9999
crud->client_session,
100+
NULL,
100101
&reply,
101102
&result->error);
102103

@@ -815,7 +816,7 @@ mongoc_collection_estimated_document_count (
815816
BSON_ASSERT_PARAM (coll);
816817

817818
server_stream = mongoc_cluster_stream_for_reads (
818-
&coll->client->cluster, read_prefs, NULL, reply, error);
819+
&coll->client->cluster, read_prefs, NULL, NULL, reply, error);
819820

820821
if (opts && bson_has_field (opts, "sessionId")) {
821822
bson_set_error (error,
@@ -1625,7 +1626,7 @@ mongoc_collection_create_index_with_opts (mongoc_collection_t *collection,
16251626
bson_append_array_builder_end (&cmd, ar);
16261627

16271628
server_stream = mongoc_cluster_stream_for_writes (
1628-
&collection->client->cluster, parsed.client_session, reply, error);
1629+
&collection->client->cluster, parsed.client_session, NULL, reply, error);
16291630

16301631
if (!server_stream) {
16311632
reply_initialized = true;
@@ -2245,6 +2246,7 @@ _mongoc_collection_update_or_replace (mongoc_collection_t *collection,
22452246
server_stream =
22462247
mongoc_cluster_stream_for_writes (&collection->client->cluster,
22472248
update_opts->crud.client_session,
2249+
NULL,
22482250
reply,
22492251
error);
22502252

@@ -3396,7 +3398,7 @@ mongoc_collection_find_and_modify_with_opts (
33963398
}
33973399

33983400
server_stream = mongoc_cluster_stream_for_writes (
3399-
cluster, appended_opts.client_session, &ss_reply, error);
3401+
cluster, appended_opts.client_session, NULL, &ss_reply, error);
34003402

34013403
if (!server_stream) {
34023404
bson_concat (reply_ptr, &ss_reply);
@@ -3566,8 +3568,23 @@ mongoc_collection_find_and_modify_with_opts (
35663568

35673569
/* each write command may be retried at most once */
35683570
is_retryable = false;
3569-
retry_server_stream = mongoc_cluster_stream_for_writes (
3570-
cluster, parts.assembled.session, NULL /* reply */, &ignored_error);
3571+
3572+
{
3573+
mongoc_deprioritized_servers_t *const ds =
3574+
mongoc_deprioritized_servers_new ();
3575+
3576+
mongoc_deprioritized_servers_add_if_sharded (
3577+
ds, server_stream->topology_type, server_stream->sd);
3578+
3579+
retry_server_stream =
3580+
mongoc_cluster_stream_for_writes (cluster,
3581+
parts.assembled.session,
3582+
ds,
3583+
NULL /* reply */,
3584+
&ignored_error);
3585+
3586+
mongoc_deprioritized_servers_destroy (ds);
3587+
}
35713588

35723589
if (retry_server_stream) {
35733590
parts.assembled.server_stream = retry_server_stream;
@@ -3782,6 +3799,7 @@ mongoc_collection_create_indexes_with_opts (mongoc_collection_t *collection,
37823799
server_stream =
37833800
mongoc_cluster_stream_for_writes (&collection->client->cluster,
37843801
NULL /* mongoc_client_session_t */,
3802+
NULL /* deprioritized servers */,
37853803
reply_ptr,
37863804
error);
37873805
if (server_stream->sd->max_wire_version < WIRE_VERSION_4_4) {

0 commit comments

Comments
 (0)