Skip to content

Commit 2d7d5f2

Browse files
authored
CDRIVER-3067/3161 error when attempting sharded transactions on 4.2 or maxWireVersion < 7 (#567) (#568)
1 parent a86f189 commit 2d7d5f2

File tree

2 files changed

+78
-19
lines changed

2 files changed

+78
-19
lines changed

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

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -799,16 +799,42 @@ mongoc_client_session_advance_operation_time (mongoc_client_session_t *session,
799799
EXIT;
800800
}
801801

802-
803802
bool
804803
mongoc_client_session_start_transaction (mongoc_client_session_t *session,
805804
const mongoc_transaction_opt_t *opts,
806805
bson_error_t *error)
807806
{
808-
ENTRY;
807+
int32_t max_wire_version;
808+
mongoc_server_description_t *sd;
809+
bool is_sharded_cluster;
809810

811+
ENTRY;
810812
BSON_ASSERT (session);
811813

814+
sd = mongoc_client_select_server (
815+
session->client, true /* selects primary */, NULL, NULL);
816+
max_wire_version = sd->max_wire_version;
817+
is_sharded_cluster = sd && (sd->type == MONGOC_SERVER_MONGOS);
818+
mongoc_server_description_destroy (sd);
819+
820+
if (is_sharded_cluster) {
821+
bson_set_error (error,
822+
MONGOC_ERROR_TRANSACTION,
823+
MONGOC_ERROR_TRANSACTION_INVALID_STATE,
824+
"Multi-document transactions on sharded clusters are not "
825+
"supported by this version of libmongoc");
826+
RETURN (false);
827+
}
828+
829+
if (max_wire_version < 7 || (max_wire_version < 8 && is_sharded_cluster)) {
830+
bson_set_error (error,
831+
MONGOC_ERROR_TRANSACTION,
832+
MONGOC_ERROR_TRANSACTION_INVALID_STATE,
833+
"Multi-document transactions are not supported by this "
834+
"server version");
835+
RETURN (false);
836+
}
837+
812838
/* use "switch" so that static checkers ensure we handle all states */
813839
switch (session->txn.state) {
814840
case MONGOC_TRANSACTION_STARTING:

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

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ test_transactions_cb (bson_t *scenario)
4545
static void
4646
test_transactions_supported (void *ctx)
4747
{
48-
bool supported;
4948
mongoc_client_t *client;
5049
mongoc_client_session_t *session;
5150
mongoc_database_t *db;
@@ -59,8 +58,6 @@ test_transactions_supported (void *ctx)
5958
return;
6059
}
6160

62-
supported = test_framework_max_wire_version_at_least (7) &&
63-
test_framework_is_replset ();
6461
client = test_framework_client_new ();
6562
mongoc_client_set_error_api (client, 2);
6663
db = mongoc_client_get_database (client, "transaction-tests");
@@ -75,29 +72,24 @@ test_transactions_supported (void *ctx)
7572
session = mongoc_client_start_session (client, NULL, &error);
7673
ASSERT_OR_PRINT (session, error);
7774

78-
/* Transactions Spec says "startTransaction SHOULD report an error if the
79-
* driver can detect that transactions are not supported by the deployment",
80-
* but we take advantage of the wiggle room and don't error here. */
81-
r = mongoc_client_session_start_transaction (session, NULL, &error);
82-
ASSERT_OR_PRINT (r, error);
75+
if ((r = mongoc_client_session_start_transaction (session, NULL, &error))) {
76+
r = mongoc_client_session_append (session, &opts, &error);
77+
ASSERT_OR_PRINT (r, error);
8378

84-
r = mongoc_client_session_append (session, &opts, &error);
85-
ASSERT_OR_PRINT (r, error);
86-
r = mongoc_collection_insert_one (
87-
collection, tmp_bson ("{}"), &opts, NULL, &error);
79+
r = mongoc_collection_insert_one (
80+
collection, tmp_bson ("{}"), &opts, NULL, &error);
8881

89-
if (supported) {
90-
ASSERT_OR_PRINT (r, error);
82+
/* insert should fail if replset has no members */
83+
BSON_ASSERT (r == test_framework_is_replset ());
9184
} else {
92-
BSON_ASSERT (!r);
93-
ASSERT_CMPINT32 (error.domain, ==, MONGOC_ERROR_SERVER);
85+
ASSERT_CMPINT32 (error.domain, ==, MONGOC_ERROR_TRANSACTION);
9486
ASSERT_CONTAINS (error.message, "transaction");
9587
}
9688

9789
bson_destroy (&opts);
9890
mongoc_collection_destroy (collection);
9991

100-
if (!supported) {
92+
if (!r) {
10193
/* suppress "error in abortTransaction" warning from session_destroy */
10294
capture_logs (true);
10395
}
@@ -533,6 +525,38 @@ test_inherit_from_client (void *ctx)
533525
mongoc_client_destroy (client);
534526
}
535527

528+
void
529+
test_transaction_fails_on_unsupported_version_or_sharded_cluster (void *ctx)
530+
{
531+
bson_error_t error;
532+
mongoc_client_session_t *session;
533+
mongoc_client_t *client;
534+
bool r;
535+
536+
client = test_framework_client_new ();
537+
session = mongoc_client_start_session (client, NULL, &error);
538+
ASSERT_OR_PRINT (session, error);
539+
540+
r = mongoc_client_session_start_transaction (session, NULL, &error);
541+
if (test_framework_is_mongos ()) {
542+
BSON_ASSERT (!r);
543+
ASSERT_CONTAINS (error.message,
544+
"Multi-document transactions on sharded clusters are "
545+
"not supported by this version of libmongoc");
546+
} else if (!test_framework_max_wire_version_at_least (7) ||
547+
(test_framework_is_mongos () &&
548+
!test_framework_max_wire_version_at_least (8))) {
549+
BSON_ASSERT (!r);
550+
ASSERT_CONTAINS (error.message,
551+
"Multi-document transactions are not supported by this "
552+
"server version");
553+
} else {
554+
ASSERT_OR_PRINT (r, error);
555+
}
556+
557+
mongoc_client_session_destroy (session);
558+
mongoc_client_destroy (client);
559+
}
536560

537561
void
538562
test_transactions_install (TestSuite *suite)
@@ -582,4 +606,13 @@ test_transactions_install (TestSuite *suite)
582606
NULL,
583607
NULL,
584608
test_framework_skip_if_no_txns);
609+
TestSuite_AddFull (
610+
suite,
611+
"/transactions/"
612+
"transaction_fails_on_unsupported_version_or_sharded_cluster",
613+
test_transaction_fails_on_unsupported_version_or_sharded_cluster,
614+
NULL,
615+
NULL,
616+
test_framework_skip_if_no_sessions,
617+
test_framework_skip_if_no_crypto);
585618
}

0 commit comments

Comments
 (0)