Skip to content

Commit 5c8550a

Browse files
committed
Add the isolation level option
1 parent 18ca608 commit 5c8550a

File tree

1 file changed

+32
-11
lines changed

1 file changed

+32
-11
lines changed

apis/Google.Cloud.Spanner.Data/Google.Cloud.Spanner.Data/SpannerTransactionCreationOptions.cs

+32-11
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
using Google.Api.Gax;
1616
using Google.Cloud.Spanner.V1;
17+
using System;
1718
using static Google.Cloud.Spanner.V1.TransactionOptions.Types;
1819

1920
namespace Google.Cloud.Spanner.Data;
@@ -28,19 +29,19 @@ public sealed class SpannerTransactionCreationOptions
2829
/// Options that will result in a read-write transaction.
2930
/// </summary>
3031
public static SpannerTransactionCreationOptions ReadWrite { get; } = new SpannerTransactionCreationOptions(
31-
timestampBound: null, transactionId: null, isDetached: false, isSingleUse: false, isPartitionedDml: false, excludeFromChangeStreams: false);
32+
timestampBound: null, transactionId: null, isDetached: false, isSingleUse: false, isPartitionedDml: false, excludeFromChangeStreams: false, isolationLevel: IsolationLevel.Unspecified);
3233

3334
/// <summary>
3435
/// Options that will result in a read-write transaction suitable for executing partioned DML.
3536
/// </summary>
3637
public static SpannerTransactionCreationOptions PartitionedDml { get; } = new SpannerTransactionCreationOptions(
37-
timestampBound: null, transactionId: null, isDetached: false, isSingleUse: false, isPartitionedDml: true, excludeFromChangeStreams: false);
38+
timestampBound: null, transactionId: null, isDetached: false, isSingleUse: false, isPartitionedDml: true, excludeFromChangeStreams: false, isolationLevel: IsolationLevel.Unspecified);
3839

3940
/// <summary>
4041
/// Options that will result in a read-only transaction bound by <see cref="TimestampBound.Strong"/>.
4142
/// </summary>
4243
public static SpannerTransactionCreationOptions ReadOnly { get; } = new SpannerTransactionCreationOptions(
43-
TimestampBound.Strong, transactionId: null, isDetached: false, isSingleUse: false, isPartitionedDml: false, excludeFromChangeStreams: false);
44+
TimestampBound.Strong, transactionId: null, isDetached: false, isSingleUse: false, isPartitionedDml: false, excludeFromChangeStreams: false, isolationLevel: IsolationLevel.Unspecified);
4445

4546
/// <summary>
4647
/// Timestamp bound settings for the transaction. May be null.
@@ -92,6 +93,13 @@ public sealed class SpannerTransactionCreationOptions
9293
/// </summary>
9394
public bool IsPartitionedDml { get; }
9495

96+
/// <summary>
97+
/// Set the isolation level for the transaction. This is only meant for read-write transactions.
98+
/// <see cref="TransactionOptions.Types.IsolationLevel"/> to reference the possible configuration values.
99+
/// When this is set to other than ISOLATION_LEVEL_UNSPECIFIED the transaction will be read-write.
100+
/// </summary>
101+
public IsolationLevel IsolationLevel { get; }
102+
95103
/// <summary>
96104
/// Whether changes executed within this transaction are recorded in change streams or not.
97105
/// This will always be false for read-only transactions.
@@ -105,7 +113,7 @@ public sealed class SpannerTransactionCreationOptions
105113
/// </remarks>
106114
public bool ExcludeFromChangeStreams { get; }
107115

108-
private SpannerTransactionCreationOptions(TimestampBound timestampBound, TransactionId transactionId, bool isDetached, bool isSingleUse, bool isPartitionedDml, bool excludeFromChangeStreams)
116+
private SpannerTransactionCreationOptions(TimestampBound timestampBound, TransactionId transactionId, bool isDetached, bool isSingleUse, bool isPartitionedDml, bool excludeFromChangeStreams, IsolationLevel isolationLevel)
109117
{
110118
GaxPreconditions.CheckArgument(
111119
timestampBound is null || transactionId is null,
@@ -137,6 +145,11 @@ private SpannerTransactionCreationOptions(TimestampBound timestampBound, Transac
137145
nameof(excludeFromChangeStreams),
138146
"Only read-write and partioned DML transactions can be marked for change stream exclusion.");
139147
ExcludeFromChangeStreams = excludeFromChangeStreams;
148+
GaxPreconditions.CheckArgument(
149+
isolationLevel != IsolationLevel.Unspecified && TimestampBound == TimestampBound.Strong,
150+
nameof(isolationLevel),
151+
$"{nameof(isolationLevel)} cannot be set on a Read-only transaction"
152+
);
140153
}
141154

142155
/// <summary>
@@ -155,7 +168,8 @@ timestampBound is null
155168
isDetached: false,
156169
isSingleUse: timestampBound?.Mode == TimestampBoundMode.MinReadTimestamp || timestampBound?.Mode == TimestampBoundMode.MaxStaleness,
157170
isPartitionedDml: false,
158-
excludeFromChangeStreams: false);
171+
excludeFromChangeStreams: false,
172+
isolationLevel: IsolationLevel.Unspecified);
159173

160174
/// <summary>
161175
/// Creates transaction options with the given <paramref name="transactionId"/>.
@@ -170,15 +184,16 @@ public static SpannerTransactionCreationOptions FromReadOnlyTransactionId(Transa
170184
isDetached: true,
171185
isSingleUse: false,
172186
isPartitionedDml: false,
173-
excludeFromChangeStreams: false);
187+
excludeFromChangeStreams: false,
188+
isolationLevel: IsolationLevel.Unspecified);
174189

175190
/// <summary>
176191
/// Options used to acquire the transaction's underlying session.
177192
/// </summary>
178193
internal TransactionOptions GetTransactionOptions()
179194
{
180-
var options = IsPartitionedDml ? new TransactionOptions { PartitionedDml = new PartitionedDml() } :
181-
TransactionMode == TransactionMode.ReadWrite ? new TransactionOptions { ReadWrite = new ReadWrite() } :
195+
var options = IsPartitionedDml ? new TransactionOptions { PartitionedDml = new PartitionedDml(), IsolationLevel = IsolationLevel.Unspecified } :
196+
TransactionMode == TransactionMode.ReadWrite ? new TransactionOptions { ReadWrite = new ReadWrite(), IsolationLevel = IsolationLevel } :
182197
TimestampBound?.ToTransactionOptions();
183198
if (options is not null)
184199
{
@@ -192,7 +207,7 @@ internal TransactionOptions GetTransactionOptions()
192207
/// If <see cref="TransactionId"/> is set, <see cref="IsDetached"/> cannot be false.
193208
/// </summary>
194209
public SpannerTransactionCreationOptions WithIsDetached(bool isDetached) =>
195-
isDetached == IsDetached ? this : new SpannerTransactionCreationOptions(TimestampBound, TransactionId, isDetached, IsSingleUse, IsPartitionedDml, ExcludeFromChangeStreams);
210+
isDetached == IsDetached ? this : new SpannerTransactionCreationOptions(TimestampBound, TransactionId, isDetached, IsSingleUse, IsPartitionedDml, ExcludeFromChangeStreams, IsolationLevel);
196211

197212
/// <summary>
198213
/// Returns a new instance identical to this one except for the value of <see cref="IsSingleUse"/>.
@@ -201,12 +216,18 @@ public SpannerTransactionCreationOptions WithIsDetached(bool isDetached) =>
201216
/// <see cref="IsSingleUse"/> cannot be false.
202217
/// </summary>
203218
public SpannerTransactionCreationOptions WithIsSingleUse(bool isSingleUse) =>
204-
isSingleUse == IsSingleUse ? this : new SpannerTransactionCreationOptions(TimestampBound, TransactionId, IsDetached, isSingleUse, IsPartitionedDml, ExcludeFromChangeStreams);
219+
isSingleUse == IsSingleUse ? this : new SpannerTransactionCreationOptions(TimestampBound, TransactionId, IsDetached, isSingleUse, IsPartitionedDml, ExcludeFromChangeStreams, IsolationLevel);
205220

206221
/// <summary>
207222
/// Returns a new instance identical to this one except for the value of <see cref="ExcludeFromChangeStreams"/>.
208223
/// <see cref="ExcludeFromChangeStreams"/> can only be true for read-write transactions.
209224
/// </summary>
210225
public SpannerTransactionCreationOptions WithExcludeFromChangeStreams(bool excludeFromChangeStreams) =>
211-
excludeFromChangeStreams == ExcludeFromChangeStreams ? this : new SpannerTransactionCreationOptions(TimestampBound, TransactionId, IsDetached, IsSingleUse, IsPartitionedDml, excludeFromChangeStreams);
226+
excludeFromChangeStreams == ExcludeFromChangeStreams ? this : new SpannerTransactionCreationOptions(TimestampBound, TransactionId, IsDetached, IsSingleUse, IsPartitionedDml, excludeFromChangeStreams, IsolationLevel);
227+
228+
/// <summary>
229+
/// Returns a new instance identical to this one except for the value of <see cref="IsolationLevel"/>
230+
/// </summary>
231+
public SpannerTransactionCreationOptions WithIsolationLevel(IsolationLevel isolationLevel) =>
232+
isolationLevel == IsolationLevel ? this : new SpannerTransactionCreationOptions(TimestampBound, TransactionId, IsDetached, IsSingleUse, IsPartitionedDml, ExcludeFromChangeStreams, isolationLevel);
212233
}

0 commit comments

Comments
 (0)