Skip to content

Commit 974ed50

Browse files
feat: an error happened in the transaction, allow one empty rollback (#190)
1 parent 544c6cd commit 974ed50

File tree

6 files changed

+62
-24
lines changed

6 files changed

+62
-24
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
- If an error happened in the transaction, allow one empty rollback
2+
13
## v0.7.0
24
- Parsed @param then prepared for use with $ prefix (@p -> $p)
35
- Fully integrated with Dapper

src/Ydb.Sdk/src/Ado/YdbCommand.cs

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ protected override DbTransaction? DbTransaction
122122
{
123123
if (value is null or YdbTransaction)
124124
{
125-
_ydbTransaction = (YdbTransaction?)value;
125+
Transaction = (YdbTransaction?)value;
126126
}
127127
else
128128
{
@@ -132,21 +132,7 @@ protected override DbTransaction? DbTransaction
132132
}
133133
}
134134

135-
public new YdbTransaction? Transaction
136-
{
137-
get
138-
{
139-
if (_ydbTransaction?.Completed ?? false)
140-
{
141-
_ydbTransaction = null;
142-
}
143-
144-
return _ydbTransaction;
145-
}
146-
set => _ydbTransaction = value;
147-
}
148-
149-
private YdbTransaction? _ydbTransaction;
135+
public new YdbTransaction? Transaction { get; set; }
150136

151137
public override bool DesignTimeVisible { get; set; }
152138

src/Ydb.Sdk/src/Ado/YdbDataReader.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,7 @@ private void OnFailReadStream()
519519
ReaderState = State.Closed;
520520
if (_ydbTransaction != null)
521521
{
522-
_ydbTransaction.Completed = true;
522+
_ydbTransaction.Failed = true;
523523
}
524524
}
525525

src/Ydb.Sdk/src/Ado/YdbTransaction.cs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,26 @@ public sealed class YdbTransaction : DbTransaction
99
{
1010
private readonly TxMode _txMode;
1111

12+
private bool _failed;
13+
1214
internal string? TxId { get; set; }
13-
internal bool Completed { get; set; }
15+
internal bool Completed { get; private set; }
16+
17+
internal bool Failed
18+
{
19+
private get => _failed;
20+
set
21+
{
22+
_failed = value;
23+
Completed = true;
24+
}
25+
}
1426

15-
internal TransactionControl TransactionControl => TxId == null
16-
? new TransactionControl { BeginTx = _txMode.TransactionSettings() }
17-
: new TransactionControl { TxId = TxId };
27+
internal TransactionControl? TransactionControl => Completed
28+
? null
29+
: TxId == null
30+
? new TransactionControl { BeginTx = _txMode.TransactionSettings() }
31+
: new TransactionControl { TxId = TxId };
1832

1933
internal YdbTransaction(YdbConnection ydbConnection, TxMode txMode)
2034
{
@@ -41,6 +55,13 @@ public override void Rollback()
4155
// TODO propagate cancellation token
4256
public override async Task RollbackAsync(CancellationToken cancellationToken = new())
4357
{
58+
if (Failed)
59+
{
60+
Failed = false;
61+
62+
return;
63+
}
64+
4465
await FinishTransaction(txId => DbConnection.Session.RollbackTransaction(txId));
4566
}
4667

src/Ydb.Sdk/tests/Ado/YdbExceptionTests.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public async Task IsTransient_WhenSchemaError_ReturnFalse()
2121
}
2222

2323
[Fact]
24-
public async Task IsTransient_WhenAborted_ReturnTrue()
24+
public async Task IsTransient_WhenAborted_ReturnTrueAndMakeEmptyRollback()
2525
{
2626
var bankTable = $"Bank_{Utils.Net}";
2727
await using var ydbConnection = new YdbConnection();
@@ -57,5 +57,13 @@ public async Task IsTransient_WhenAborted_ReturnTrue()
5757
{
5858
CommandText = $"DROP TABLE {bankTable}"
5959
}.ExecuteNonQueryAsync();
60+
Assert.Equal("This YdbTransaction has completed; it is no longer usable",
61+
Assert.Throws<InvalidOperationException>(() => ydbCommand.Transaction.Commit()).Message);
62+
63+
await ydbCommand.Transaction!.RollbackAsync();
64+
Assert.Equal("This YdbTransaction has completed; it is no longer usable",
65+
Assert.Throws<InvalidOperationException>(() => ydbCommand.Transaction!.Commit()).Message);
66+
Assert.Equal("This YdbTransaction has completed; it is no longer usable",
67+
Assert.Throws<InvalidOperationException>(() => ydbCommand.Transaction!.Rollback()).Message);
6068
}
6169
}

src/Ydb.Sdk/tests/Ado/YdbTransactionTests.cs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public void Commit_WhenEmptyYdbCommand_DoNothing()
9797
}
9898

9999
[Fact]
100-
public void Commit_WhenDoubleCommit_ThrowException()
100+
public void CommitAndRollback_WhenDoubleCommit_ThrowException()
101101
{
102102
using var connection = new YdbConnection();
103103
connection.Open();
@@ -165,7 +165,7 @@ public void CommitAndRollback_WhenConnectionIsClosed_ThrowException()
165165
}
166166

167167
[Fact]
168-
public void Commit_WhenConnectionIsClosedAndTxDoesNotStarted_ThrowException()
168+
public void CommitAndRollback_WhenConnectionIsClosedAndTxDoesNotStarted_ThrowException()
169169
{
170170
using var connection = new YdbConnection();
171171
connection.Open();
@@ -179,6 +179,27 @@ public void Commit_WhenConnectionIsClosedAndTxDoesNotStarted_ThrowException()
179179
Assert.Throws<InvalidOperationException>(() => ydbTransaction.Rollback()).Message);
180180
}
181181

182+
[Fact]
183+
public void CommitAndRollback_WhenTransactionIsFailed_ThrowException()
184+
{
185+
using var connection = new YdbConnection();
186+
connection.Open();
187+
188+
var ydbCommand = connection.CreateCommand();
189+
ydbCommand.Transaction = connection.BeginTransaction();
190+
ydbCommand.Transaction.Failed = true;
191+
ydbCommand.Transaction.TxId = "no_tx";
192+
193+
Assert.Equal("This YdbTransaction has completed; it is no longer usable",
194+
Assert.Throws<InvalidOperationException>(() => ydbCommand.Transaction.Commit()).Message);
195+
196+
ydbCommand.Transaction.Rollback(); // Make completed
197+
Assert.Equal("This YdbTransaction has completed; it is no longer usable",
198+
Assert.Throws<InvalidOperationException>(() => ydbCommand.Transaction.Commit()).Message);
199+
Assert.Equal("This YdbTransaction has completed; it is no longer usable",
200+
Assert.Throws<InvalidOperationException>(() => ydbCommand.Transaction.Rollback()).Message);
201+
}
202+
182203
public async Task InitializeAsync()
183204
{
184205
await using var connection = new YdbConnection();

0 commit comments

Comments
 (0)