Skip to content

Commit b947f6e

Browse files
committed
CSHARP-3722: Raise client error for snapshot sessions on <5.0 servers
1 parent 7bf2a71 commit b947f6e

File tree

9 files changed

+353
-21
lines changed

9 files changed

+353
-21
lines changed

src/MongoDB.Driver.Core/Core/Misc/Feature.cs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ public class Feature
9696
private static readonly Feature __serverReturnsResumableChangeStreamErrorLabel = new Feature("ServerReturnsResumableChangeStreamErrorLabel", new SemanticVersion(4, 3, 0));
9797
private static readonly Feature __serverReturnsRetryableWriteErrorLabel = new Feature("ServerReturnsRetryableWriteErrorLabel", new SemanticVersion(4, 3, 0));
9898
private static readonly Feature __shardedTransactions = new Feature("ShardedTransactions", new SemanticVersion(4, 1, 6));
99+
private static readonly Feature __snapshotReads = new Feature("SnapshotReads", new SemanticVersion(5, 0, 0, ""), notSupportedMessage: "Snapshot reads require MongoDB 5.0 or later");
99100
private static readonly Feature __speculativeAuthentication = new Feature("SpeculativeAuthentication", new SemanticVersion(4, 4, 0, "rc0"));
100101
private static readonly Feature __streamingIsMaster = new Feature("StreamingIsMaster", new SemanticVersion(4, 4, 0, ""));
101102
private static readonly Feature __tailableCursor = new Feature("TailableCursor", new SemanticVersion(3, 2, 0));
@@ -470,6 +471,11 @@ public class Feature
470471
/// </summary>
471472
public static Feature ShardedTransactions => __shardedTransactions;
472473

474+
/// <summary>
475+
/// Gets the snapshot reads feature.
476+
/// </summary>
477+
public static Feature SnapshotReads => __snapshotReads;
478+
473479
/// <summary>
474480
/// Gets the speculative authentication feature.
475481
/// </summary>
@@ -514,19 +520,25 @@ public class Feature
514520
private readonly string _name;
515521
private readonly SemanticVersion _firstSupportedVersion;
516522
private readonly SemanticVersion _supportRemovedVersion;
523+
private readonly string _notSupportedMessage;
517524

518525

519526
/// <summary>
520-
/// Initializes a new instance of the <see cref="Feature"/> class.
527+
/// Initializes a new instance of the <see cref="Feature" /> class.
521528
/// </summary>
522529
/// <param name="name">The name of the feature.</param>
523530
/// <param name="firstSupportedVersion">The first server version that supports the feature.</param>
524-
/// /// <param name="supportRemovedVersion">The server version that stops support the feature.</param>
525-
public Feature(string name, SemanticVersion firstSupportedVersion, SemanticVersion supportRemovedVersion = null)
531+
/// <param name="supportRemovedVersion">The server version that stops support the feature.</param>
532+
/// <param name="notSupportedMessage">The not supported error message.</param>
533+
public Feature(string name,
534+
SemanticVersion firstSupportedVersion,
535+
SemanticVersion supportRemovedVersion = null,
536+
string notSupportedMessage = null)
526537
{
527538
_name = name;
528539
_firstSupportedVersion = firstSupportedVersion;
529540
_supportRemovedVersion = supportRemovedVersion;
541+
_notSupportedMessage = notSupportedMessage;
530542
}
531543

532544
/// <summary>
@@ -544,6 +556,11 @@ public Feature(string name, SemanticVersion firstSupportedVersion, SemanticVersi
544556
/// </summary>
545557
public SemanticVersion LastNotSupportedVersion => VersionBefore(_firstSupportedVersion);
546558

559+
/// <summary>
560+
/// Gets the error message to be used by the feature support checks.
561+
/// </summary>
562+
public string NotSupportedMessage => _notSupportedMessage;
563+
547564
/// <summary>
548565
/// Determines whether a feature is supported by a version of the server.
549566
/// </summary>
@@ -574,7 +591,8 @@ public void ThrowIfNotSupported(SemanticVersion serverVersion)
574591
{
575592
if (!IsSupported(serverVersion))
576593
{
577-
throw new NotSupportedException($"Server version {serverVersion} does not support the {_name} feature.");
594+
var errorMessage = _notSupportedMessage ?? $"Server version {serverVersion} does not support the {_name} feature.";
595+
throw new NotSupportedException(errorMessage);
578596
}
579597
}
580598

src/MongoDB.Driver.Core/Core/Operations/ReadConcernHelper.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
using MongoDB.Bson;
1717
using MongoDB.Driver.Core.Bindings;
1818
using MongoDB.Driver.Core.Connections;
19+
using MongoDB.Driver.Core.Misc;
1920

2021
namespace MongoDB.Driver.Core.Operations
2122
{
@@ -40,6 +41,8 @@ private static BsonDocument ToBsonDocument(ICoreSession session, ConnectionDescr
4041
// snapshot
4142
if (sessionsAreSupported && session.IsSnapshot)
4243
{
44+
Feature.SnapshotReads.ThrowIfNotSupported(connectionDescription.ServerVersion);
45+
4346
var readConcernDocument = ReadConcern.Snapshot.ToBsonDocument();
4447
if (session.SnapshotTime != null)
4548
{

src/MongoDB.Driver/MongoClient.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,7 @@ private IClientSessionHandle StartSession(ClientSessionOptions options, bool are
641641

642642
if (options != null && options.Snapshot && options.CausalConsistency == true)
643643
{
644-
throw new MongoClientException("Combining both causal consistency and snapshot options is not supported.");
644+
throw new NotSupportedException("Combining both causal consistency and snapshot options is not supported.");
645645
}
646646

647647
options = options ?? new ClientSessionOptions();

tests/MongoDB.Driver.Tests/Specifications/sessions/SessionsProseTests.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
* limitations under the License.
1414
*/
1515

16+
using System;
1617
using FluentAssertions;
1718
using MongoDB.Driver.Core.Misc;
1819
using MongoDB.Driver.Core.TestHelpers.XunitExtensions;
@@ -37,7 +38,7 @@ public void Snapshot_and_causal_consistent_session_is_not_allowed()
3738
var mongoClient = DriverTestConfiguration.Client;
3839

3940
var exception = Record.Exception(() => mongoClient.StartSession(sessionOptions));
40-
exception.Should().BeOfType<MongoClientException>();
41+
exception.Should().BeOfType<NotSupportedException>();
4142
}
4243
}
4344
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
{
2+
"description": "snapshot-sessions-not-supported-client-error",
3+
"schemaVersion": "1.0",
4+
"runOnRequirements": [
5+
{
6+
"minServerVersion": "3.6",
7+
"maxServerVersion": "4.4.99"
8+
}
9+
],
10+
"createEntities": [
11+
{
12+
"client": {
13+
"id": "client0",
14+
"observeEvents": [
15+
"commandStartedEvent",
16+
"commandFailedEvent"
17+
]
18+
}
19+
},
20+
{
21+
"database": {
22+
"id": "database0",
23+
"client": "client0",
24+
"databaseName": "database0"
25+
}
26+
},
27+
{
28+
"collection": {
29+
"id": "collection0",
30+
"database": "database0",
31+
"collectionName": "collection0"
32+
}
33+
},
34+
{
35+
"session": {
36+
"id": "session0",
37+
"client": "client0",
38+
"sessionOptions": {
39+
"snapshot": true
40+
}
41+
}
42+
}
43+
],
44+
"initialData": [
45+
{
46+
"collectionName": "collection0",
47+
"databaseName": "database0",
48+
"documents": [
49+
{
50+
"_id": 1,
51+
"x": 11
52+
}
53+
]
54+
}
55+
],
56+
"tests": [
57+
{
58+
"description": "Client error on find with snapshot",
59+
"operations": [
60+
{
61+
"name": "find",
62+
"object": "collection0",
63+
"arguments": {
64+
"session": "session0",
65+
"filter": {}
66+
},
67+
"expectError": {
68+
"isClientError": true,
69+
"errorContains": "Snapshot reads require MongoDB 5.0 or later"
70+
}
71+
}
72+
],
73+
"expectEvents": []
74+
},
75+
{
76+
"description": "Client error on aggregate with snapshot",
77+
"operations": [
78+
{
79+
"name": "aggregate",
80+
"object": "collection0",
81+
"arguments": {
82+
"session": "session0",
83+
"pipeline": []
84+
},
85+
"expectError": {
86+
"isClientError": true,
87+
"errorContains": "Snapshot reads require MongoDB 5.0 or later"
88+
}
89+
}
90+
],
91+
"expectEvents": []
92+
},
93+
{
94+
"description": "Client error on distinct with snapshot",
95+
"operations": [
96+
{
97+
"name": "distinct",
98+
"object": "collection0",
99+
"arguments": {
100+
"fieldName": "x",
101+
"filter": {},
102+
"session": "session0"
103+
},
104+
"expectError": {
105+
"isClientError": true,
106+
"errorContains": "Snapshot reads require MongoDB 5.0 or later"
107+
}
108+
}
109+
],
110+
"expectEvents": []
111+
}
112+
]
113+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
description: snapshot-sessions-not-supported-client-error
2+
3+
schemaVersion: "1.0"
4+
5+
runOnRequirements:
6+
- minServerVersion: "3.6"
7+
maxServerVersion: "4.4.99"
8+
9+
createEntities:
10+
- client:
11+
id: &client0 client0
12+
observeEvents: [ commandStartedEvent, commandFailedEvent ]
13+
- database:
14+
id: &database0Name database0
15+
client: *client0
16+
databaseName: *database0Name
17+
- collection:
18+
id: &collection0Name collection0
19+
database: *database0Name
20+
collectionName: *collection0Name
21+
- session:
22+
id: session0
23+
client: client0
24+
sessionOptions:
25+
snapshot: true
26+
27+
initialData:
28+
- collectionName: *collection0Name
29+
databaseName: *database0Name
30+
documents:
31+
- { _id: 1, x: 11 }
32+
33+
tests:
34+
- description: Client error on find with snapshot
35+
operations:
36+
- name: find
37+
object: collection0
38+
arguments:
39+
session: session0
40+
filter: {}
41+
expectError:
42+
isClientError: true
43+
errorContains: Snapshot reads require MongoDB 5.0 or later
44+
expectEvents: []
45+
46+
- description: Client error on aggregate with snapshot
47+
operations:
48+
- name: aggregate
49+
object: collection0
50+
arguments:
51+
session: session0
52+
pipeline: []
53+
expectError:
54+
isClientError: true
55+
errorContains: Snapshot reads require MongoDB 5.0 or later
56+
expectEvents: []
57+
58+
- description: Client error on distinct with snapshot
59+
operations:
60+
- name: distinct
61+
object: collection0
62+
arguments:
63+
fieldName: x
64+
filter: {}
65+
session: session0
66+
expectError:
67+
isClientError: true
68+
errorContains: Snapshot reads require MongoDB 5.0 or later
69+
expectEvents: []

0 commit comments

Comments
 (0)