Skip to content

Commit c23b3bf

Browse files
committed
bypass topology description updates; bypass cooldown
1 parent 5898470 commit c23b3bf

File tree

4 files changed

+124
-17
lines changed

4 files changed

+124
-17
lines changed

src/libmongoc/src/mongoc/mongoc-topology-description.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,6 +1146,11 @@ mongoc_topology_description_invalidate_server (
11461146
{
11471147
BSON_ASSERT (error);
11481148

1149+
if (topology->type == MONGOC_TOPOLOGY_LOAD_BALANCED) {
1150+
/* Load balancers must never be marked unknown. */
1151+
return;
1152+
}
1153+
11491154
/* send NULL hello reply */
11501155
mongoc_topology_description_handle_hello (
11511156
topology, id, NULL, MONGOC_RTT_UNSET, error);

src/libmongoc/src/mongoc/mongoc-topology-scanner.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,6 +1136,10 @@ mongoc_topology_scanner_start (mongoc_topology_scanner_t *ts,
11361136
skip =
11371137
obey_cooldown && mongoc_topology_scanner_node_in_cooldown (node, now);
11381138

1139+
if (skip) {
1140+
MONGOC_DEBUG ("skipping node: %s due to cooldown", node->host.host_and_port);
1141+
}
1142+
11391143
if (!skip) {
11401144
mongoc_topology_scanner_node_setup (node, &node->last_error);
11411145
}

src/libmongoc/src/mongoc/mongoc-topology.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,9 @@ mongoc_topology_new (const mongoc_uri_t *uri, bool single_threaded)
431431
if (mongoc_uri_get_option_as_bool (
432432
topology->uri, MONGOC_URI_LOADBALANCED, false)) {
433433
init_type = MONGOC_TOPOLOGY_LOAD_BALANCED;
434+
if (topology->single_threaded) {
435+
_mongoc_topology_bypass_cooldown (topology);
436+
}
434437
} else if (service && !has_directconnection) {
435438
init_type = MONGOC_TOPOLOGY_UNKNOWN;
436439
} else if (has_directconnection) {
@@ -1011,7 +1014,20 @@ _mongoc_topology_select_server_id_loadbalanced (mongoc_topology_t *topology,
10111014
}
10121015

10131016
if (!node->stream) {
1014-
_mongoc_server_selection_error ("Topology scanner in invalid state; cannot find load balancer", &scanner_error, error);
1017+
/* Use the error domain / code returned in mongoc-cluster when fetching a stream fails. */
1018+
if (scanner_error.code) {
1019+
bson_set_error (error,
1020+
MONGOC_ERROR_STREAM,
1021+
MONGOC_ERROR_STREAM_NOT_ESTABLISHED,
1022+
"Could not establish stream for node %s: %s",
1023+
node->host.host_and_port, scanner_error.message);
1024+
} else {
1025+
bson_set_error (error,
1026+
MONGOC_ERROR_STREAM,
1027+
MONGOC_ERROR_STREAM_NOT_ESTABLISHED,
1028+
"Could not establish stream for node %s",
1029+
node->host.host_and_port);
1030+
}
10151031
return 0;
10161032
}
10171033

@@ -1357,8 +1373,6 @@ mongoc_topology_invalidate_server (mongoc_topology_t *topology,
13571373
{
13581374
BSON_ASSERT (error);
13591375

1360-
// LBTODO: do not update in load balanced mode.
1361-
13621376
bson_mutex_lock (&topology->mutex);
13631377
mongoc_topology_description_invalidate_server (
13641378
&topology->description, id, error);

src/libmongoc/tests/test-mongoc-loadbalanced.c

Lines changed: 98 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,9 @@ topology_closed (const mongoc_apm_topology_closed_t *event)
8888
context->topology_closed_events++;
8989
}
9090

91-
static mongoc_apm_callbacks_t * make_callbacks (void) {
91+
static mongoc_apm_callbacks_t *
92+
make_callbacks (void)
93+
{
9294
mongoc_apm_callbacks_t *cbs;
9395

9496
cbs = mongoc_apm_callbacks_new ();
@@ -101,7 +103,9 @@ static mongoc_apm_callbacks_t * make_callbacks (void) {
101103
return cbs;
102104
}
103105

104-
static stats_t * set_client_callbacks (mongoc_client_t *client) {
106+
static stats_t *
107+
set_client_callbacks (mongoc_client_t *client)
108+
{
105109
mongoc_apm_callbacks_t *cbs;
106110
stats_t *stats;
107111

@@ -112,7 +116,9 @@ static stats_t * set_client_callbacks (mongoc_client_t *client) {
112116
return stats;
113117
}
114118

115-
static stats_t * set_client_pool_callbacks (mongoc_client_pool_t *pool) {
119+
static stats_t *
120+
set_client_pool_callbacks (mongoc_client_pool_t *pool)
121+
{
116122
mongoc_apm_callbacks_t *cbs;
117123
stats_t *stats;
118124

@@ -123,7 +129,9 @@ static stats_t * set_client_pool_callbacks (mongoc_client_pool_t *pool) {
123129
return stats;
124130
}
125131

126-
static void free_and_assert_stats (stats_t *stats) {
132+
static void
133+
free_and_assert_stats (stats_t *stats)
134+
{
127135
ASSERT_CMPINT (stats->topology_opening_events, ==, 1);
128136
ASSERT_CMPINT (stats->topology_changed_events, ==, 2);
129137
ASSERT_CMPINT (stats->server_opening_events, ==, 1);
@@ -267,7 +275,8 @@ test_loadbalanced_connect_single (void *unused)
267275
&error);
268276
ASSERT_OR_PRINT (ok, error);
269277

270-
/* Ensure the server description is unchanged and remains as type LoadBalancer. */
278+
/* Ensure the server description is unchanged and remains as type
279+
* LoadBalancer. */
271280
monitor_sd = mongoc_client_select_server (
272281
client, true /* for writes */, NULL /* read prefs */, &error);
273282
ASSERT_OR_PRINT (monitor_sd, error);
@@ -298,14 +307,15 @@ test_loadbalanced_connect_pooled (void *unused)
298307
client = mongoc_client_pool_pop (pool);
299308

300309
ok = mongoc_client_command_simple (client,
301-
"admin",
302-
tmp_bson ("{'ping': 1}"),
303-
NULL /* read prefs */,
304-
NULL /* reply */,
305-
&error);
310+
"admin",
311+
tmp_bson ("{'ping': 1}"),
312+
NULL /* read prefs */,
313+
NULL /* reply */,
314+
&error);
306315
ASSERT_OR_PRINT (ok, error);
307316

308-
/* Ensure the server description is unchanged and remains as type LoadBalancer. */
317+
/* Ensure the server description is unchanged and remains as type
318+
* LoadBalancer. */
309319
monitor_sd = mongoc_client_select_server (
310320
client, true /* for writes */, NULL /* read prefs */, &error);
311321
ASSERT_OR_PRINT (monitor_sd, error);
@@ -316,7 +326,7 @@ test_loadbalanced_connect_pooled (void *unused)
316326
mongoc_uri_destroy (uri);
317327
mongoc_client_pool_push (pool, client);
318328
mongoc_client_pool_destroy (pool);
319-
free_and_assert_stats (stats);
329+
free_and_assert_stats (stats);
320330
}
321331

322332
/* Ensure that server selection on single threaded clients establishes a
@@ -349,10 +359,76 @@ test_loadbalanced_server_selection_establishes_connection_single (void *unused)
349359
mongoc_client_destroy (client);
350360
}
351361

352-
/* Test that the 5 second cooldown does not apply when establishing a new connection to the load balancer after a network error. */
362+
/* Test that the 5 second cooldown does not apply when establishing a new
363+
* connection to the load balancer after a network error. */
353364
static void
354-
test_loadbalanced_network_error_bypasses_cooldown_single (void *unused) {
365+
test_loadbalanced_cooldown_is_bypassed_single (void *unused)
366+
{
367+
mongoc_client_t *client;
368+
char *uristr = loadbalanced_uri ();
369+
bson_error_t error;
370+
bool ok;
371+
stats_t *stats;
372+
mongoc_server_description_t *monitor_sd;
373+
374+
client = mongoc_client_new (uristr);
375+
stats = set_client_callbacks (client);
376+
377+
ok = mongoc_client_command_simple (
378+
client,
379+
"admin",
380+
tmp_bson ("{'configureFailPoint': 'failCommand', 'mode': { 'times': 2 }, "
381+
"'data': {'closeConnection': true, 'failCommands': ['ping', "
382+
"'isMaster']}}"),
383+
NULL /* read prefs */,
384+
NULL /* reply */,
385+
&error);
386+
ASSERT_OR_PRINT (ok, error);
387+
388+
ok = mongoc_client_command_simple (client,
389+
"admin",
390+
tmp_bson ("{'ping': 1}"),
391+
NULL /* read prefs */,
392+
NULL /* reply */,
393+
&error);
394+
ASSERT_ERROR_CONTAINS (
395+
error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_SOCKET, "socket error");
355396

397+
/* The next attempted command should attempt to scan, and fail when
398+
* performing the handshake with the isMaster command. */
399+
ok = mongoc_client_command_simple (client,
400+
"admin",
401+
tmp_bson ("{'ping': 1}"),
402+
NULL /* read prefs */,
403+
NULL /* reply */,
404+
&error);
405+
ASSERT_ERROR_CONTAINS (error,
406+
MONGOC_ERROR_STREAM,
407+
MONGOC_ERROR_STREAM_NOT_ESTABLISHED,
408+
"Could not establish stream");
409+
410+
/* Failing to "scan" would normally cause the node to be in cooldown. But in
411+
* load balancer mode this is bypassed. The subsequent connect attempt should
412+
* succeed. */
413+
ok = mongoc_client_command_simple (client,
414+
"admin",
415+
tmp_bson ("{'ping': 1}"),
416+
NULL /* read prefs */,
417+
NULL /* reply */,
418+
&error);
419+
ASSERT_OR_PRINT (ok, error);
420+
421+
/* Ensure the server description is unchanged and remains as type
422+
* LoadBalancer. */
423+
monitor_sd = mongoc_client_select_server (
424+
client, true /* for writes */, NULL /* read prefs */, &error);
425+
ASSERT_OR_PRINT (monitor_sd, error);
426+
ASSERT_CMPSTR ("LoadBalancer", mongoc_server_description_type (monitor_sd));
427+
428+
mongoc_server_description_destroy (monitor_sd);
429+
bson_free (uristr);
430+
mongoc_client_destroy (client);
431+
free_and_assert_stats (stats);
356432
}
357433

358434
static int
@@ -409,4 +485,12 @@ test_loadbalanced_install (TestSuite *suite)
409485
NULL /* ctx */,
410486
NULL /* dtor */,
411487
skip_if_not_loadbalanced);
488+
489+
TestSuite_AddFull (suite,
490+
"/loadbalanced/cooldown_is_bypassed/single",
491+
test_loadbalanced_cooldown_is_bypassed_single,
492+
NULL /* dtor */,
493+
NULL /* ctx */,
494+
skip_if_not_loadbalanced,
495+
test_framework_skip_if_no_failpoint);
412496
}

0 commit comments

Comments
 (0)