Skip to content

Commit ebfedb6

Browse files
author
Oleksandr Poliakov
committed
CSHARP-3552: CSOT: Transactions
1 parent 60ebc8c commit ebfedb6

27 files changed

+837
-332
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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;
17+
using MongoDB.Driver.Core.Misc;
18+
19+
namespace MongoDB.Driver
20+
{
21+
// TODO: CSOT: Make it public when CSOT will be ready for GA
22+
internal sealed class AbortTransactionOptions
23+
{
24+
public AbortTransactionOptions()
25+
{}
26+
27+
public AbortTransactionOptions(TimeSpan? timeout)
28+
{
29+
Timeout = Ensure.IsNullOrValidTimeout(timeout, nameof(timeout));
30+
}
31+
32+
public TimeSpan? Timeout { get; }
33+
}
34+
}

src/MongoDB.Driver/ClientSessionHandle.cs

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2017-present MongoDB Inc.
1+
/* Copyright 2010-present MongoDB Inc.
22
*
33
* Licensed under the Apache License, Version 2.0 (the "License");
44
* you may not use this file except in compliance with the License.
@@ -94,16 +94,20 @@ public IServerSession ServerSession
9494

9595
// public methods
9696
/// <inheritdoc />
97-
public void AbortTransaction(CancellationToken cancellationToken = default(CancellationToken))
98-
{
99-
_coreSession.AbortTransaction(cancellationToken);
100-
}
97+
public void AbortTransaction(CancellationToken cancellationToken = default)
98+
=> _coreSession.AbortTransaction(cancellationToken);
99+
100+
// TODO: CSOT: Make it public when CSOT will be ready for GA
101+
internal void AbortTransaction(AbortTransactionOptions options, CancellationToken cancellationToken = default)
102+
=> _coreSession.AbortTransaction(options, cancellationToken);
101103

102104
/// <inheritdoc />
103-
public Task AbortTransactionAsync(CancellationToken cancellationToken = default(CancellationToken))
104-
{
105-
return _coreSession.AbortTransactionAsync(cancellationToken);
106-
}
105+
public Task AbortTransactionAsync(CancellationToken cancellationToken = default)
106+
=> _coreSession.AbortTransactionAsync(cancellationToken);
107+
108+
// TODO: CSOT: Make it public when CSOT will be ready for GA
109+
internal Task AbortTransactionAsync(AbortTransactionOptions options, CancellationToken cancellationToken = default)
110+
=> _coreSession.AbortTransactionAsync(options, cancellationToken);
107111

108112
/// <inheritdoc />
109113
public void AdvanceClusterTime(BsonDocument newClusterTime)
@@ -118,16 +122,20 @@ public void AdvanceOperationTime(BsonTimestamp newOperationTime)
118122
}
119123

120124
/// <inheritdoc />
121-
public void CommitTransaction(CancellationToken cancellationToken = default(CancellationToken))
122-
{
123-
_coreSession.CommitTransaction(cancellationToken);
124-
}
125+
public void CommitTransaction(CancellationToken cancellationToken = default)
126+
=> _coreSession.CommitTransaction(cancellationToken);
127+
128+
// TODO: CSOT: Make it public when CSOT will be ready for GA
129+
internal void CommitTransaction(CommitTransactionOptions options, CancellationToken cancellationToken = default)
130+
=> _coreSession.CommitTransaction(options, cancellationToken);
125131

126132
/// <inheritdoc />
127-
public Task CommitTransactionAsync(CancellationToken cancellationToken = default(CancellationToken))
128-
{
129-
return _coreSession.CommitTransactionAsync(cancellationToken);
130-
}
133+
public Task CommitTransactionAsync(CancellationToken cancellationToken = default)
134+
=> _coreSession.CommitTransactionAsync(cancellationToken);
135+
136+
// TODO: CSOT: Make it public when CSOT will be ready for GA
137+
internal Task CommitTransactionAsync(CommitTransactionOptions options, CancellationToken cancellationToken = default)
138+
=> _coreSession.CommitTransactionAsync(options, cancellationToken);
131139

132140
/// <inheritdoc />
133141
public void Dispose()
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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;
17+
using MongoDB.Driver.Core.Misc;
18+
19+
namespace MongoDB.Driver
20+
{
21+
// TODO: CSOT: Make it public when CSOT will be ready for GA
22+
internal sealed class CommitTransactionOptions
23+
{
24+
public CommitTransactionOptions()
25+
{}
26+
27+
public CommitTransactionOptions(TimeSpan? timeout)
28+
{
29+
Timeout = Ensure.IsNullOrValidTimeout(timeout, nameof(timeout));
30+
}
31+
32+
public TimeSpan? Timeout { get; }
33+
}
34+
35+
}
36+

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

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2018-present MongoDB Inc.
1+
/* Copyright 2010-present MongoDB Inc.
22
*
33
* Licensed under the Apache License, Version 2.0 (the "License");
44
* you may not use this file except in compliance with the License.
@@ -141,12 +141,15 @@ public bool IsInTransaction
141141

142142
// public methods
143143
/// <inheritdoc />
144-
public void AbortTransaction(CancellationToken cancellationToken = default(CancellationToken))
144+
public void AbortTransaction(CancellationToken cancellationToken = default)
145+
=> AbortTransaction(null, cancellationToken);
146+
147+
// TODO: CSOT: Make it public when CSOT will be ready for GA
148+
internal void AbortTransaction(AbortTransactionOptions options, CancellationToken cancellationToken = default)
145149
{
146150
EnsureAbortTransactionCanBeCalled(nameof(AbortTransaction));
147151

148-
// TODO: CSOT implement proper way to obtain the operationContext
149-
var operationContext = new OperationContext(null, cancellationToken);
152+
using var operationContext = new OperationContext(GetTimeout(options?.Timeout), cancellationToken);
150153
try
151154
{
152155
if (_currentTransaction.IsEmpty)
@@ -192,12 +195,15 @@ public bool IsInTransaction
192195
}
193196

194197
/// <inheritdoc />
195-
public async Task AbortTransactionAsync(CancellationToken cancellationToken = default(CancellationToken))
198+
public Task AbortTransactionAsync(CancellationToken cancellationToken = default)
199+
=> AbortTransactionAsync(null, cancellationToken);
200+
201+
// TODO: CSOT: Make it public when CSOT will be ready for GA
202+
internal async Task AbortTransactionAsync(AbortTransactionOptions options, CancellationToken cancellationToken = default)
196203
{
197204
EnsureAbortTransactionCanBeCalled(nameof(AbortTransaction));
198205

199-
// TODO: CSOT implement proper way to obtain the operationContext
200-
var operationContext = new OperationContext(null, cancellationToken);
206+
using var operationContext = new OperationContext(GetTimeout(options?.Timeout), cancellationToken);
201207
try
202208
{
203209
if (_currentTransaction.IsEmpty)
@@ -292,12 +298,15 @@ public long AdvanceTransactionNumber()
292298
}
293299

294300
/// <inheritdoc />
295-
public void CommitTransaction(CancellationToken cancellationToken = default(CancellationToken))
301+
public void CommitTransaction(CancellationToken cancellationToken = default)
302+
=> CommitTransaction(null, cancellationToken);
303+
304+
// TODO: CSOT: Make it public when CSOT will be ready for GA
305+
internal void CommitTransaction(CommitTransactionOptions options, CancellationToken cancellationToken = default)
296306
{
297307
EnsureCommitTransactionCanBeCalled(nameof(CommitTransaction));
298308

299-
// TODO: CSOT implement proper way to obtain the operationContext
300-
var operationContext = new OperationContext(null, cancellationToken);
309+
using var operationContext = new OperationContext(GetTimeout(options?.Timeout), cancellationToken);
301310
try
302311
{
303312
_isCommitTransactionInProgress = true;
@@ -329,12 +338,15 @@ public long AdvanceTransactionNumber()
329338
}
330339

331340
/// <inheritdoc />
332-
public async Task CommitTransactionAsync(CancellationToken cancellationToken = default(CancellationToken))
341+
public Task CommitTransactionAsync(CancellationToken cancellationToken = default)
342+
=> CommitTransactionAsync(null, cancellationToken);
343+
344+
// TODO: CSOT: Make it public when CSOT will be ready for GA
345+
internal async Task CommitTransactionAsync(CommitTransactionOptions options, CancellationToken cancellationToken = default(CancellationToken))
333346
{
334347
EnsureCommitTransactionCanBeCalled(nameof(CommitTransaction));
335348

336-
// TODO: CSOT implement proper way to obtain the operationContext
337-
var operationContext = new OperationContext(null, cancellationToken);
349+
using var operationContext = new OperationContext(GetTimeout(options?.Timeout), cancellationToken);
338350
try
339351
{
340352
_isCommitTransactionInProgress = true;
@@ -563,6 +575,9 @@ private async Task<TResult> ExecuteEndTransactionOnPrimaryAsync<TResult>(Operati
563575
}
564576
}
565577

578+
private TimeSpan? GetTimeout(TimeSpan? timeout)
579+
=> timeout ?? _options.DefaultTransactionOptions?.Timeout;
580+
566581
private TransactionOptions GetEffectiveTransactionOptions(TransactionOptions transactionOptions)
567582
{
568583
var readConcern = transactionOptions?.ReadConcern ?? _options.DefaultTransactionOptions?.ReadConcern ?? ReadConcern.Default;

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2018-present MongoDB Inc.
1+
/* Copyright 2010-present MongoDB Inc.
22
*
33
* Licensed under the Apache License, Version 2.0 (the "License");
44
* you may not use this file except in compliance with the License.
@@ -56,6 +56,8 @@ public CoreTransaction(long transactionNumber, TransactionOptions transactionOpt
5656
/// </value>
5757
public bool IsEmpty => _isEmpty;
5858

59+
internal OperationContext OperationContext { get; set; }
60+
5961
/// <summary>
6062
/// Gets the transaction state.
6163
/// </summary>
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
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;
17+
using System.Threading;
18+
using System.Threading.Tasks;
19+
20+
namespace MongoDB.Driver.Core.Bindings
21+
{
22+
// TODO: CSOT: Make it public when CSOT will be ready for GA
23+
internal static class ICoreSessionExtensions
24+
{
25+
// TODO: CSOT: Merge this extension methods in ICoreSession interface on major release
26+
/// <summary>
27+
/// Aborts the transaction.
28+
/// </summary>
29+
/// <param name="session">The session.</param>
30+
/// <param name="options">Abort transaction options.</param>
31+
/// <param name="cancellationToken">The cancellation token.</param>
32+
public static void AbortTransaction(this ICoreSession session, AbortTransactionOptions options, CancellationToken cancellationToken = default)
33+
{
34+
if (options == null || session.Options.DefaultTransactionOptions?.Timeout == options.Timeout)
35+
{
36+
session.AbortTransaction(cancellationToken);
37+
return;
38+
}
39+
40+
if (session is CoreSession coreSession)
41+
{
42+
coreSession.AbortTransaction(options, cancellationToken);
43+
return;
44+
}
45+
46+
if (session is WrappingCoreSession wrappingCoreSession)
47+
{
48+
wrappingCoreSession.AbortTransaction(options, cancellationToken);
49+
return;
50+
}
51+
52+
throw new InvalidOperationException("Cannot apply options on non CoreSession.");
53+
}
54+
55+
/// <summary>
56+
/// Aborts the transaction.
57+
/// </summary>
58+
/// <param name="session">The session.</param>
59+
/// <param name="options">Abort transaction options.</param>
60+
/// <param name="cancellationToken">The cancellation token.</param>
61+
public static Task AbortTransactionAsync(this ICoreSession session, AbortTransactionOptions options, CancellationToken cancellationToken = default)
62+
{
63+
if (options == null || session.Options.DefaultTransactionOptions?.Timeout == options.Timeout)
64+
{
65+
return session.AbortTransactionAsync(cancellationToken);
66+
}
67+
68+
if (session is CoreSession coreSession)
69+
{
70+
return coreSession.AbortTransactionAsync(options, cancellationToken);
71+
}
72+
73+
if (session is WrappingCoreSession wrappingCoreSession)
74+
{
75+
return wrappingCoreSession.AbortTransactionAsync(options, cancellationToken);
76+
}
77+
78+
throw new InvalidOperationException("Cannot apply options on non CoreSession.");
79+
}
80+
81+
/// <summary>
82+
/// Commits the transaction.
83+
/// </summary>
84+
/// <param name="session">The session.</param>
85+
/// <param name="options">Commit transaction options.</param>
86+
/// <param name="cancellationToken">The cancellation token.</param>
87+
public static void CommitTransaction(this ICoreSession session, CommitTransactionOptions options, CancellationToken cancellationToken = default)
88+
{
89+
if (options == null || session.Options.DefaultTransactionOptions?.Timeout == options.Timeout)
90+
{
91+
session.CommitTransaction(cancellationToken);
92+
return;
93+
}
94+
95+
if (session is CoreSession coreSession)
96+
{
97+
coreSession.CommitTransaction(options, cancellationToken);
98+
return;
99+
}
100+
101+
if (session is WrappingCoreSession wrappingCoreSession)
102+
{
103+
wrappingCoreSession.CommitTransaction(options, cancellationToken);
104+
return;
105+
}
106+
107+
throw new InvalidOperationException("Cannot apply options on non CoreSession.");
108+
}
109+
110+
/// <summary>
111+
/// Commits the transaction.
112+
/// </summary>
113+
/// <param name="session">The session.</param>
114+
/// <param name="options">Commit transaction options.</param>
115+
/// <param name="cancellationToken">The cancellation token.</param>
116+
public static Task CommitTransactionAsync(this ICoreSession session, CommitTransactionOptions options, CancellationToken cancellationToken = default)
117+
{
118+
if (options == null || session.Options.DefaultTransactionOptions?.Timeout == options.Timeout)
119+
{
120+
return session.CommitTransactionAsync(cancellationToken);
121+
}
122+
123+
if (session is CoreSession coreSession)
124+
{
125+
return coreSession.CommitTransactionAsync(options, cancellationToken);
126+
}
127+
128+
if (session is WrappingCoreSession wrappingCoreSession)
129+
{
130+
return wrappingCoreSession.CommitTransactionAsync(options, cancellationToken);
131+
}
132+
133+
throw new InvalidOperationException("Cannot apply options on non CoreSession.");
134+
}
135+
}
136+
}
137+

0 commit comments

Comments
 (0)