Skip to content

Commit ad157ae

Browse files
author
Oleksandr Poliakov
committed
CSHARP-3552: CSOT: Transactions
1 parent a93f29e commit ad157ae

25 files changed

+769
-315
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: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
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 not CoreSession coreSession)
41+
{
42+
throw new InvalidOperationException("Cannot apply options on non CoreSession.");
43+
}
44+
45+
coreSession.AbortTransaction(options, cancellationToken);
46+
}
47+
48+
/// <summary>
49+
/// Aborts the transaction.
50+
/// </summary>
51+
/// <param name="session">The session.</param>
52+
/// <param name="options">Abort transaction options.</param>
53+
/// <param name="cancellationToken">The cancellation token.</param>
54+
public static Task AbortTransactionAsync(this ICoreSession session, AbortTransactionOptions options, CancellationToken cancellationToken = default)
55+
{
56+
if (options == null || session.Options.DefaultTransactionOptions?.Timeout == options.Timeout)
57+
{
58+
return session.AbortTransactionAsync(cancellationToken);
59+
}
60+
61+
if (session is not CoreSession coreSession)
62+
{
63+
throw new InvalidOperationException("Cannot apply options on non CoreSession.");
64+
}
65+
66+
return coreSession.AbortTransactionAsync(options, cancellationToken);
67+
}
68+
69+
/// <summary>
70+
/// Commits the transaction.
71+
/// </summary>
72+
/// <param name="session">The session.</param>
73+
/// <param name="options">Commit transaction options.</param>
74+
/// <param name="cancellationToken">The cancellation token.</param>
75+
public static void CommitTransaction(this ICoreSession session, CommitTransactionOptions options, CancellationToken cancellationToken = default)
76+
{
77+
if (options == null || session.Options.DefaultTransactionOptions?.Timeout == options.Timeout)
78+
{
79+
session.CommitTransaction(cancellationToken);
80+
return;
81+
}
82+
83+
if (session is not CoreSession coreSession)
84+
{
85+
throw new InvalidOperationException("Cannot apply options on non CoreSession.");
86+
}
87+
88+
coreSession.CommitTransaction(options, cancellationToken);
89+
}
90+
91+
/// <summary>
92+
/// Commits the transaction.
93+
/// </summary>
94+
/// <param name="session">The session.</param>
95+
/// <param name="options">Commit transaction options.</param>
96+
/// <param name="cancellationToken">The cancellation token.</param>
97+
public static Task CommitTransactionAsync(this ICoreSession session, CommitTransactionOptions options, CancellationToken cancellationToken = default)
98+
{
99+
if (options == null || session.Options.DefaultTransactionOptions?.Timeout == options.Timeout)
100+
{
101+
return session.CommitTransactionAsync(cancellationToken);
102+
}
103+
104+
if (session is not CoreSession coreSession)
105+
{
106+
throw new InvalidOperationException("Cannot apply options on non CoreSession.");
107+
}
108+
109+
return coreSession.CommitTransactionAsync(options, cancellationToken);
110+
}
111+
}
112+
}
113+

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2013-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.
@@ -20,5 +20,7 @@ namespace MongoDB.Driver.Core.Misc
2020
internal interface IClock
2121
{
2222
DateTime UtcNow { get; }
23+
24+
IWatch StartWatch();
2325
}
2426
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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+
18+
namespace MongoDB.Driver.Core.Misc
19+
{
20+
internal interface IWatch
21+
{
22+
TimeSpan Elapsed { get; }
23+
}
24+
}

0 commit comments

Comments
 (0)