Skip to content

Commit b96d39a

Browse files
committed
Support sessions in loadbalanced mode
Sessions never expire Sessions are always supported
1 parent 5c39ca1 commit b96d39a

File tree

4 files changed

+146
-27
lines changed

4 files changed

+146
-27
lines changed

src/libmongoc/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -960,6 +960,7 @@ set (test-libmongoc-sources
960960
${PROJECT_SOURCE_DIR}/tests/test-mongoc-interrupt.c
961961
${PROJECT_SOURCE_DIR}/tests/test-mongoc-linux-distro-scanner.c
962962
${PROJECT_SOURCE_DIR}/tests/test-mongoc-list.c
963+
${PROJECT_SOURCE_DIR}/tests/test-mongoc-loadbalanced.c
963964
${PROJECT_SOURCE_DIR}/tests/test-mongoc-log.c
964965
${PROJECT_SOURCE_DIR}/tests/test-mongoc-long-namespace.c
965966
${PROJECT_SOURCE_DIR}/tests/test-mongoc-matcher.c

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

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1438,45 +1438,53 @@ _mongoc_topology_pop_server_session (mongoc_topology_t *topology,
14381438
int64_t timeout;
14391439
mongoc_server_session_t *ss = NULL;
14401440
mongoc_topology_description_t *td;
1441+
bool loadbalanced;
14411442

14421443
ENTRY;
14431444

14441445
bson_mutex_lock (&topology->mutex);
14451446

14461447
td = &topology->description;
14471448
timeout = td->session_timeout_minutes;
1449+
loadbalanced = td->type == MONGOC_TOPOLOGY_LOADBALANCED;
14481450

1449-
if (timeout == MONGOC_NO_SESSIONS) {
1450-
/* if needed, connect and check for session timeout again */
1451-
if (!mongoc_topology_description_has_data_node (td)) {
1452-
bson_mutex_unlock (&topology->mutex);
1453-
if (!mongoc_topology_select_server_id (
1454-
topology, MONGOC_SS_READ, NULL, error)) {
1455-
RETURN (NULL);
1456-
}
1451+
/* When the topology type is LoadBalanced, sessions are always supported. */
1452+
if (!loadbalanced) {
1453+
if (timeout == MONGOC_NO_SESSIONS) {
1454+
/* if needed, connect and check for session timeout again */
1455+
if (!mongoc_topology_description_has_data_node (td)) {
1456+
bson_mutex_unlock (&topology->mutex);
1457+
if (!mongoc_topology_select_server_id (
1458+
topology, MONGOC_SS_READ, NULL, error)) {
1459+
RETURN (NULL);
1460+
}
14571461

1458-
bson_mutex_lock (&topology->mutex);
1459-
timeout = td->session_timeout_minutes;
1460-
}
1462+
bson_mutex_lock (&topology->mutex);
1463+
timeout = td->session_timeout_minutes;
1464+
}
14611465

1462-
if (timeout == MONGOC_NO_SESSIONS) {
1463-
bson_mutex_unlock (&topology->mutex);
1464-
bson_set_error (error,
1465-
MONGOC_ERROR_CLIENT,
1466-
MONGOC_ERROR_CLIENT_SESSION_FAILURE,
1467-
"Server does not support sessions");
1468-
RETURN (NULL);
1466+
if (timeout == MONGOC_NO_SESSIONS) {
1467+
bson_mutex_unlock (&topology->mutex);
1468+
bson_set_error (error,
1469+
MONGOC_ERROR_CLIENT,
1470+
MONGOC_ERROR_CLIENT_SESSION_FAILURE,
1471+
"Server does not support sessions");
1472+
RETURN (NULL);
1473+
}
14691474
}
14701475
}
14711476

14721477
while (topology->session_pool) {
14731478
ss = topology->session_pool;
14741479
CDL_DELETE (topology->session_pool, ss);
1475-
if (_mongoc_server_session_timed_out (ss, timeout)) {
1476-
_mongoc_server_session_destroy (ss);
1477-
ss = NULL;
1478-
} else {
1479-
break;
1480+
/* Sessions do not expire when the topology type is load balanced. */
1481+
if (!loadbalanced) {
1482+
if (_mongoc_server_session_timed_out (ss, timeout)) {
1483+
_mongoc_server_session_destroy (ss);
1484+
ss = NULL;
1485+
} else {
1486+
break;
1487+
}
14801488
}
14811489
}
14821490

@@ -1505,17 +1513,20 @@ _mongoc_topology_push_server_session (mongoc_topology_t *topology,
15051513
{
15061514
int64_t timeout;
15071515
mongoc_server_session_t *ss;
1516+
bool loadbalanced;
15081517

15091518
ENTRY;
15101519

15111520
bson_mutex_lock (&topology->mutex);
15121521

15131522
timeout = topology->description.session_timeout_minutes;
1523+
loadbalanced = topology->description.type == MONGOC_TOPOLOGY_LOADBALANCED;
15141524

15151525
/* start at back of queue and reap timed-out sessions */
15161526
while (topology->session_pool && topology->session_pool->prev) {
15171527
ss = topology->session_pool->prev;
1518-
if (_mongoc_server_session_timed_out (ss, timeout)) {
1528+
/* Sessions do not expire when the topology type is load balanced. */
1529+
if (!loadbalanced && _mongoc_server_session_timed_out (ss, timeout)) {
15191530
BSON_ASSERT (ss->next); /* silences clang scan-build */
15201531
CDL_DELETE (topology->session_pool, ss);
15211532
_mongoc_server_session_destroy (ss);
@@ -1526,8 +1537,10 @@ _mongoc_topology_push_server_session (mongoc_topology_t *topology,
15261537
}
15271538

15281539
/* If session is expiring or "dirty" (a network error occurred on it), do not
1529-
* return it to the pool. */
1530-
if (_mongoc_server_session_timed_out (server_session, timeout) ||
1540+
* return it to the pool. Sessions do not expire when the topology type is
1541+
* load balanced. */
1542+
if ((!loadbalanced &&
1543+
_mongoc_server_session_timed_out (server_session, timeout)) ||
15311544
server_session->dirty) {
15321545
_mongoc_server_session_destroy (server_session);
15331546
} else {

src/libmongoc/tests/test-libmongoc.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,8 @@ extern void
272272
test_bson_util_install (TestSuite *suite);
273273
extern void
274274
test_result_install (TestSuite *suite);
275+
extern void
276+
test_loadbalanced_install (TestSuite *suite);
275277

276278
typedef struct {
277279
mongoc_log_level_t level;
@@ -1851,7 +1853,8 @@ mongoc_client_pool_t *
18511853
test_framework_new_default_client_pool ()
18521854
{
18531855
mongoc_uri_t *test_uri = test_framework_get_uri ();
1854-
mongoc_client_pool_t *pool = test_framework_client_pool_new_from_uri (test_uri, NULL);
1856+
mongoc_client_pool_t *pool =
1857+
test_framework_client_pool_new_from_uri (test_uri, NULL);
18551858

18561859
BSON_ASSERT (pool);
18571860
test_framework_set_pool_ssl_opts (pool);
@@ -2905,6 +2908,7 @@ main (int argc, char *argv[])
29052908
test_bson_match_install (&suite);
29062909
test_bson_util_install (&suite);
29072910
test_result_install (&suite);
2911+
test_loadbalanced_install (&suite);
29082912

29092913
ret = TestSuite_Run (&suite);
29102914

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Copyright 2020-present MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "mongoc/mongoc.h"
18+
#include "mongoc/mongoc-client-session-private.h"
19+
#include "test-conveniences.h"
20+
#include "test-libmongoc.h"
21+
#include "TestSuite.h"
22+
23+
static char *loadbalanced_uri (void) {
24+
return test_framework_getenv ("SINGLE_MONGOS_LB_URI");
25+
}
26+
27+
static void
28+
test_loadbalanced_sessions_supported (void *unused)
29+
{
30+
mongoc_client_t *client;
31+
mongoc_client_session_t *session;
32+
char *uristr = loadbalanced_uri ();
33+
bson_error_t error;
34+
35+
client = mongoc_client_new (uristr);
36+
session = mongoc_client_start_session (client, NULL /* opts */, &error);
37+
ASSERT_OR_PRINT (session, error);
38+
39+
mongoc_client_session_destroy (session);
40+
bson_free (uristr);
41+
mongoc_client_destroy (client);
42+
}
43+
44+
static void
45+
test_loadbalanced_sessions_do_not_expire (void *unused)
46+
{
47+
mongoc_client_t *client;
48+
mongoc_client_session_t *session;
49+
char *uristr = loadbalanced_uri ();
50+
bson_error_t error;
51+
bson_t *lsid1;
52+
bson_t *lsid2;
53+
54+
client = mongoc_client_new (uristr);
55+
session = mongoc_client_start_session (client, NULL /* opts */, &error);
56+
ASSERT_OR_PRINT (session, error);
57+
58+
lsid1 = bson_copy (&session->server_session->lsid);
59+
session->server_session->last_used_usec = 1;
60+
mongoc_client_session_destroy (session);
61+
62+
session = mongoc_client_start_session (client, NULL /* opts */, &error);
63+
ASSERT_OR_PRINT (session, error);
64+
lsid2 = bson_copy (&session->server_session->lsid);
65+
mongoc_client_session_destroy (session);
66+
67+
if (!bson_equal (lsid1, lsid2)) {
68+
test_error ("Session not reused: %s != %s", tmp_json (lsid1), tmp_json (lsid2));
69+
}
70+
71+
bson_destroy (lsid1);
72+
bson_destroy (lsid2);
73+
bson_free (uristr);
74+
mongoc_client_destroy (client);
75+
}
76+
77+
static int
78+
skip_if_not_loadbalanced (void)
79+
{
80+
char *val = loadbalanced_uri ();
81+
if (!val) {
82+
return 0;
83+
}
84+
bson_free (val);
85+
return 1;
86+
}
87+
88+
void
89+
test_loadbalanced_install (TestSuite *suite)
90+
{
91+
TestSuite_AddFull (suite, "/loadbalanced/sessions/supported",
92+
test_loadbalanced_sessions_supported,
93+
NULL /* ctx */,
94+
NULL /* dtor */,
95+
skip_if_not_loadbalanced);
96+
TestSuite_AddFull (suite, "/loadbalanced/sessions/do_not_expire",
97+
test_loadbalanced_sessions_do_not_expire,
98+
NULL /* ctx */,
99+
NULL /* dtor */,
100+
skip_if_not_loadbalanced);
101+
}

0 commit comments

Comments
 (0)