Skip to content

Commit 5f95a59

Browse files
CSHARP-2615: Discard ServerSessions involved in network errors
1 parent a19d77c commit 5f95a59

23 files changed

+1359
-14
lines changed

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ private static BsonDocument GenerateSessionId()
3636

3737
// private fields
3838
private readonly BsonDocument _id;
39+
private bool _isDirty;
3940
private DateTime? _lastUsedAt;
4041
private long _transactionNumber;
4142

@@ -50,6 +51,9 @@ public CoreServerSession()
5051
/// <inheritdoc />
5152
public BsonDocument Id => _id;
5253

54+
/// <inheritdoc />
55+
public bool IsDirty => _isDirty;
56+
5357
/// <inheritdoc />
5458
public DateTime? LastUsedAt => _lastUsedAt;
5559

@@ -65,6 +69,12 @@ public void Dispose()
6569
{
6670
}
6771

72+
/// <inheritdoc />
73+
public void MarkDirty()
74+
{
75+
_isDirty = true;
76+
}
77+
6878
/// <inheritdoc />
6979
public void WasUsed()
7080
{

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

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public ICoreServerSession AcquireSession()
4141
for (var i = _pool.Count - 1; i >= 0; i--)
4242
{
4343
var pooledSession = _pool[i];
44-
if (IsAboutToExpire(pooledSession))
44+
if (IsAboutToExpireOrDirty(pooledSession))
4545
{
4646
pooledSession.Dispose();
4747
}
@@ -68,7 +68,7 @@ public void ReleaseSession(ICoreServerSession session)
6868
for (var i = 0; i < _pool.Count; i++)
6969
{
7070
var pooledSession = _pool[i];
71-
if (IsAboutToExpire(pooledSession))
71+
if (IsAboutToExpireOrDirty(pooledSession))
7272
{
7373
pooledSession.Dispose();
7474
removeCount++;
@@ -80,7 +80,7 @@ public void ReleaseSession(ICoreServerSession session)
8080
}
8181
_pool.RemoveRange(0, removeCount);
8282

83-
if (IsAboutToExpire(session))
83+
if (IsAboutToExpireOrDirty(session))
8484
{
8585
session.Dispose();
8686
}
@@ -107,6 +107,11 @@ private bool IsAboutToExpire(ICoreServerSession session)
107107
}
108108
}
109109

110+
private bool IsAboutToExpireOrDirty(ICoreServerSession session)
111+
{
112+
return IsAboutToExpire(session) || session.IsDirty;
113+
}
114+
110115
// nested types
111116
internal sealed class ReleaseOnDisposeCoreServerSession : WrappingCoreServerSession
112117
{

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ public CoreSession(
7979
/// <inheritdoc />
8080
public bool IsCausallyConsistent => _options.IsCausallyConsistent;
8181

82+
/// <inheritdoc />
83+
public bool IsDirty => _serverSession.IsDirty;
84+
8285
/// <inheritdoc />
8386
public bool IsImplicit => _options.IsImplicit;
8487

@@ -347,6 +350,12 @@ public void Dispose()
347350
}
348351
}
349352

353+
/// <inheritdoc />
354+
public void MarkDirty()
355+
{
356+
_serverSession.MarkDirty();
357+
}
358+
350359
/// <inheritdoc />
351360
public void StartTransaction(TransactionOptions transactionOptions = null)
352361
{

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@ public interface ICoreServerSession : IDisposable
3232
/// </value>
3333
BsonDocument Id { get; }
3434

35+
/// <summary>
36+
/// Gets a value indicate whether this session is dirty.
37+
/// </summary>
38+
/// <value>
39+
/// <c>true</c> if the session is dirty.
40+
/// </value>
41+
bool IsDirty { get; }
42+
3543
/// <summary>
3644
/// Gets the time this server session was last used (in UTC).
3745
/// </summary>
@@ -40,13 +48,18 @@ public interface ICoreServerSession : IDisposable
4048
/// </value>
4149
DateTime? LastUsedAt { get; }
4250

51+
// methods
4352
/// <summary>
4453
/// Gets the next transaction number.
4554
/// </summary>
4655
/// <returns>The transaction number.</returns>
4756
long AdvanceTransactionNumber();
4857

49-
// methods
58+
/// <summary>
59+
/// Marks the session as dirty.
60+
/// </summary>
61+
void MarkDirty();
62+
5063
/// <summary>
5164
/// Called by the driver when the session is used (i.e. sent to the server).
5265
/// </summary>

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717
using System.Threading;
1818
using System.Threading.Tasks;
1919
using MongoDB.Bson;
20-
using MongoDB.Driver.Core.Clusters;
21-
using MongoDB.Driver.Core.Servers;
2220

2321
namespace MongoDB.Driver.Core.Bindings
2422
{
@@ -59,6 +57,14 @@ public interface ICoreSession : IDisposable
5957
/// <c>true</c> if the session is causally consistent.
6058
/// </value>
6159
bool IsCausallyConsistent { get; }
60+
61+
/// <summary>
62+
/// Gets a value indicate whether this session is dirty.
63+
/// </summary>
64+
/// <value>
65+
/// <c>true</c> if the session is dirty.
66+
/// </value>
67+
bool IsDirty { get; }
6268

6369
/// <summary>
6470
/// Gets a value indicating whether this instance is implicit session.
@@ -150,6 +156,11 @@ public interface ICoreSession : IDisposable
150156
/// <returns>A Task.</returns>
151157
Task CommitTransactionAsync(CancellationToken cancellationToken = default(CancellationToken));
152158

159+
/// <summary>
160+
/// Marks the session as dirty.
161+
/// </summary>
162+
void MarkDirty();
163+
153164
/// <summary>
154165
/// Starts a transaction.
155166
/// </summary>

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ internal class NoCoreServerSession : ICoreServerSession
3030

3131
public BsonDocument Id => null;
3232

33+
public bool IsDirty => false;
34+
3335
public DateTime? LastUsedAt => null;
3436

3537
public long AdvanceTransactionNumber()
@@ -41,6 +43,10 @@ public void Dispose()
4143
{
4244
}
4345

46+
public void MarkDirty()
47+
{
48+
}
49+
4450
public void WasUsed()
4551
{
4652
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ public static ICoreSessionHandle NewHandle()
6363
/// <inheritdoc />
6464
public bool IsCausallyConsistent => false;
6565

66+
/// <inheritdoc />
67+
public bool IsDirty => false;
68+
6669
/// <inheritdoc />
6770
public bool IsImplicit => true;
6871

@@ -129,6 +132,11 @@ public void Dispose()
129132
{
130133
}
131134

135+
/// <inheritdoc />
136+
public void MarkDirty()
137+
{
138+
}
139+
132140
/// <inheritdoc />
133141
public void StartTransaction(TransactionOptions transactionOptions = null)
134142
{

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@ public BsonDocument Id
4343
}
4444
}
4545

46+
public bool IsDirty
47+
{
48+
get
49+
{
50+
ThrowIfDisposed();
51+
return _wrapped.IsDirty;
52+
}
53+
}
54+
4655
public DateTime? LastUsedAt
4756
{
4857
get
@@ -74,6 +83,12 @@ public void Dispose()
7483
GC.SuppressFinalize(this);
7584
}
7685

86+
public void MarkDirty()
87+
{
88+
ThrowIfDisposed();
89+
_wrapped.MarkDirty();
90+
}
91+
7792
public void WasUsed()
7893
{
7994
ThrowIfDisposed();

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,16 @@ public virtual BsonDocument Id
7575
}
7676
}
7777

78+
/// <inheritdoc />
79+
public virtual bool IsDirty
80+
{
81+
get
82+
{
83+
ThrowIfDisposed();
84+
return _wrapped.IsDirty;
85+
}
86+
}
87+
7888
/// <inheritdoc />
7989
public virtual bool IsCausallyConsistent
8090
{
@@ -213,6 +223,13 @@ public void Dispose()
213223
GC.SuppressFinalize(this);
214224
}
215225

226+
/// <inheritdoc />
227+
public virtual void MarkDirty()
228+
{
229+
ThrowIfDisposed();
230+
_wrapped.MarkDirty();
231+
}
232+
216233
/// <inheritdoc />
217234
public virtual void StartTransaction(TransactionOptions transactionOptions = null)
218235
{

src/MongoDB.Driver.Core/Core/Servers/Server.cs

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ public TResult Command<TResult>(
545545
resultSerializer,
546546
messageEncoderSettings);
547547

548-
return ExecuteProtocol(protocol, cancellationToken);
548+
return ExecuteProtocol(protocol, session, cancellationToken);
549549
}
550550

551551
[Obsolete("Use the newest overload instead.")]
@@ -646,7 +646,7 @@ public Task<TResult> CommandAsync<TResult>(
646646
resultSerializer,
647647
messageEncoderSettings);
648648

649-
return ExecuteProtocolAsync(protocol, cancellationToken);
649+
return ExecuteProtocolAsync(protocol, session, cancellationToken);
650650
}
651651

652652
public void Dispose()
@@ -963,6 +963,20 @@ private TResult ExecuteProtocol<TResult>(IWireProtocol<TResult> protocol, Cancel
963963
}
964964
}
965965

966+
private TResult ExecuteProtocol<TResult>(IWireProtocol<TResult> protocol, ICoreSession session, CancellationToken cancellationToken)
967+
{
968+
try
969+
{
970+
return protocol.Execute(_connection, cancellationToken);
971+
}
972+
catch (Exception ex)
973+
{
974+
MarkSessionDirtyIfNeeded(session, ex);
975+
_server.HandleChannelException(_connection, ex);
976+
throw;
977+
}
978+
}
979+
966980
private async Task ExecuteProtocolAsync(IWireProtocol protocol, CancellationToken cancellationToken)
967981
{
968982
try
@@ -988,6 +1002,20 @@ private async Task<TResult> ExecuteProtocolAsync<TResult>(IWireProtocol<TResult>
9881002
throw;
9891003
}
9901004
}
1005+
1006+
private async Task<TResult> ExecuteProtocolAsync<TResult>(IWireProtocol<TResult> protocol, ICoreSession session, CancellationToken cancellationToken)
1007+
{
1008+
try
1009+
{
1010+
return await protocol.ExecuteAsync(_connection, cancellationToken).ConfigureAwait(false);
1011+
}
1012+
catch (Exception ex)
1013+
{
1014+
MarkSessionDirtyIfNeeded(session, ex);
1015+
_server.HandleChannelException(_connection, ex);
1016+
throw;
1017+
}
1018+
}
9911019

9921020
public IChannelHandle Fork()
9931021
{
@@ -1026,6 +1054,14 @@ private bool GetEffectiveSlaveOk(bool slaveOk)
10261054
return slaveOk;
10271055
}
10281056

1057+
private void MarkSessionDirtyIfNeeded(ICoreSession session, Exception ex)
1058+
{
1059+
if (ex is MongoConnectionException)
1060+
{
1061+
session.MarkDirty();
1062+
}
1063+
}
1064+
10291065
private void ThrowIfDisposed()
10301066
{
10311067
if (_disposed)

0 commit comments

Comments
 (0)