Skip to content

Commit c3f85ae

Browse files
committed
POC Exposing SnapshotTime
1 parent d03569a commit c3f85ae

File tree

8 files changed

+144
-3
lines changed

8 files changed

+144
-3
lines changed

src/MongoDB.Driver/ClientSessionHandle.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ public IServerSession ServerSession
8989
}
9090
}
9191

92+
public BsonTimestamp SnapshotTime => _coreSession.SnapshotTime;
93+
9294
/// <inheritdoc />
9395
public ICoreSessionHandle WrappedCoreSession => _coreSession;
9496

src/MongoDB.Driver/ClientSessionOptions.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
*/
1515

1616
using System;
17+
using MongoDB.Bson;
1718
using MongoDB.Driver.Core.Bindings;
1819

1920
namespace MongoDB.Driver
@@ -46,6 +47,11 @@ public class ClientSessionOptions
4647
/// </value>
4748
public bool Snapshot { get; set;}
4849

50+
/// <summary>
51+
/// //TODO
52+
/// </summary>
53+
public BsonTimestamp SnapshotTime { get; set; }
54+
4955
// internal methods
5056
internal CoreSessionOptions ToCore(bool isImplicit = false)
5157
{
@@ -55,7 +61,8 @@ internal CoreSessionOptions ToCore(bool isImplicit = false)
5561
isCausallyConsistent: isCausallyConsistent,
5662
isImplicit: isImplicit,
5763
isSnapshot: Snapshot,
58-
defaultTransactionOptions: DefaultTransactionOptions);
64+
defaultTransactionOptions: DefaultTransactionOptions,
65+
snapshotTime: SnapshotTime);
5966
}
6067
}
6168
}

src/MongoDB.Driver/Core/Bindings/CoreSession.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ private CoreSession(
7171
{
7272
_cluster = Ensure.IsNotNull(cluster, nameof(cluster));
7373
_options = Ensure.IsNotNull(options, nameof(options));
74+
_snapshotTime = options.SnapshotTime;
7475
}
7576

7677
// public properties

src/MongoDB.Driver/Core/Bindings/CoreSessionOptions.cs

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

16+
using MongoDB.Bson;
17+
1618
namespace MongoDB.Driver.Core.Bindings
1719
{
20+
//TODO Why is this class public?
1821
/// <summary>
1922
/// Core session options.
2023
/// </summary>
@@ -25,6 +28,7 @@ public class CoreSessionOptions
2528
private readonly bool _isCausallyConsistent;
2629
private readonly bool _isImplicit;
2730
private readonly bool _isSnapshot;
31+
private readonly BsonTimestamp _snapshotTime;
2832

2933
// constructors
3034
/// <summary>
@@ -34,16 +38,19 @@ public class CoreSessionOptions
3438
/// <param name="isImplicit">if set to <c>true</c> this session is an implicit session.</param>
3539
/// <param name="isSnapshot">if set to <c>true</c> this session is a snapshot session.</param>
3640
/// <param name="defaultTransactionOptions">The default transaction options.</param>
41+
/// <param name="snapshotTime">//TODO</param>
3742
public CoreSessionOptions(
3843
bool isCausallyConsistent = false,
3944
bool isImplicit = false,
4045
TransactionOptions defaultTransactionOptions = null,
41-
bool isSnapshot = false)
46+
bool isSnapshot = false,
47+
BsonTimestamp snapshotTime = null)
4248
{
4349
_isCausallyConsistent = isCausallyConsistent;
4450
_isImplicit = isImplicit;
4551
_isSnapshot = isSnapshot;
4652
_defaultTransactionOptions = defaultTransactionOptions;
53+
_snapshotTime = snapshotTime;
4754
}
4855

4956
// public properties
@@ -78,5 +85,10 @@ public CoreSessionOptions(
7885
/// <c>true</c> if this session is a snapshot session; otherwise, <c>false</c>.
7986
/// </value>
8087
public bool IsSnapshot => _isSnapshot;
88+
89+
/// <summary>
90+
/// //TODO
91+
/// </summary>
92+
public BsonTimestamp SnapshotTime => _snapshotTime;
8193
}
8294
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public static BsonDocument GetReadConcernForSnapshotSession(ICoreSession session
4040
Feature.SnapshotReads.ThrowIfNotSupported(connectionDescription.MaxWireVersion);
4141

4242
var readConcernDocument = ReadConcern.Snapshot.ToBsonDocument();
43-
if (session.SnapshotTime != null)
43+
if (session.SnapshotTime != null) // For the first read within a snapshot session, SnapshotTime will be null
4444
{
4545
readConcernDocument.Add("atClusterTime", session.SnapshotTime);
4646
}

src/MongoDB.Driver/IClientSession.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ public interface IClientSession : IDisposable
8383
/// </value>
8484
IServerSession ServerSession { get; }
8585

86+
/// <summary>
87+
/// //TODO
88+
/// </summary>
89+
BsonTimestamp SnapshotTime { get; }
90+
8691
/// <summary>
8792
/// Gets the wrapped core session (intended for internal use only).
8893
/// </summary>

src/MongoDB.Driver/MongoClient.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,8 @@ private IClientSessionHandle StartSession(ClientSessionOptions options)
627627
throw new NotSupportedException("Combining both causal consistency and snapshot options is not supported.");
628628
}
629629

630+
//TODO Throw an exception if SnapshotTime is set and Snapshot is not true.
631+
630632
options ??= new ClientSessionOptions();
631633
if (_settings.Timeout.HasValue && options.DefaultTransactionOptions?.Timeout == null)
632634
{
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/* Copyright 2010-present MongoDB Inc.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
using System.Collections.Generic;
17+
using MongoDB.Bson;
18+
using MongoDB.Bson.Serialization.Attributes;
19+
using Xunit;
20+
21+
namespace MongoDB.Driver.Tests;
22+
23+
public class AtClusterTimeTests
24+
{
25+
[Fact]
26+
public void AtClusterTime_should_work()
27+
{
28+
const string collectionName = "atClusterTimeTests";
29+
const string databaseName = "testDb";
30+
31+
using var client = DriverTestConfiguration.Client;
32+
var database = client.GetDatabase(databaseName);
33+
database.DropCollection(collectionName);
34+
var collection = database.GetCollection<TestObject>(collectionName);
35+
36+
var obj1 = new TestObject { Name = "obj1" };
37+
collection.InsertOne(obj1);
38+
39+
BsonTimestamp clusterTime1;
40+
41+
var filterDefinition = Builders<TestObject>.Filter.Empty;
42+
var sortDefinition = Builders<TestObject>.Sort.Ascending(o => o.Name);
43+
44+
var sessionOptions1 = new ClientSessionOptions
45+
{
46+
Snapshot = true
47+
};
48+
49+
using (var session1 = client.StartSession(sessionOptions1))
50+
{
51+
var results = collection.Find(session1, filterDefinition).Sort(sortDefinition).ToList();
52+
AssertOneObj(results);
53+
54+
clusterTime1 = session1.SnapshotTime;
55+
Assert.NotEqual(null, clusterTime1);
56+
}
57+
58+
var obj2 = new TestObject { Name = "obj2" };
59+
collection.InsertOne(obj2);
60+
61+
var sessionOptions2 = new ClientSessionOptions
62+
{
63+
Snapshot = true,
64+
SnapshotTime = clusterTime1
65+
};
66+
67+
//Snapshot read session at clusterTime1 should not see obj2
68+
using (var session2 = client.StartSession(sessionOptions2))
69+
{
70+
var results = collection.Find(session2, filterDefinition).Sort(sortDefinition).ToList();
71+
AssertOneObj(results);
72+
73+
var clusterTime2 = session2.SnapshotTime;
74+
Assert.Equal(clusterTime2, clusterTime1);
75+
}
76+
77+
var sessionOptions3 = new ClientSessionOptions
78+
{
79+
Snapshot = true,
80+
};
81+
82+
//Snapshot read session without cluster time should see obj2
83+
using (var session3 = client.StartSession(sessionOptions3))
84+
{
85+
var results = collection.Find(session3, filterDefinition).Sort(sortDefinition).ToList();
86+
AssertTwoObjs(results);
87+
88+
var clusterTime3 = session3.WrappedCoreSession.SnapshotTime;
89+
Assert.NotEqual(clusterTime3, clusterTime1);
90+
}
91+
92+
void AssertOneObj(List<TestObject> objs)
93+
{
94+
Assert.Equal(1, objs.Count);
95+
Assert.Equal("obj1", objs[0].Name);
96+
}
97+
98+
void AssertTwoObjs(List<TestObject> objs)
99+
{
100+
Assert.Equal(2, objs.Count);
101+
Assert.Equal("obj1", objs[0].Name);
102+
Assert.Equal("obj2", objs[1].Name);
103+
}
104+
}
105+
106+
private class TestObject
107+
{
108+
[BsonId]
109+
public ObjectId Id { get; set; }
110+
public string Name { get; set; }
111+
}
112+
}

0 commit comments

Comments
 (0)