diff --git a/AerospikeClient/Async/AsyncClient.cs b/AerospikeClient/Async/AsyncClient.cs
index e1647a5b..ce6e4db9 100644
--- a/AerospikeClient/Async/AsyncClient.cs
+++ b/AerospikeClient/Async/AsyncClient.cs
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2024 Aerospike, Inc.
+ * Copyright 2012-2025 Aerospike, Inc.
*
* Portions may be licensed to Aerospike, Inc. under one or more contributor
* license agreements.
@@ -183,8 +183,7 @@ public void Commit(CommitListener listener, Txn txn)
break;
case Txn.TxnState.ABORTED:
- listener.OnSuccess(CommitStatus.CommitStatusType.ALREADY_ABORTED);
- break;
+ throw new AerospikeException(ResultCode.TXN_ALREADY_ABORTED, "Transaction already aborted");
}
}
@@ -227,8 +226,7 @@ public void Abort(AbortListener listener, Txn txn)
break;
case Txn.TxnState.COMMITTED:
- listener.OnSuccess(AbortStatus.AbortStatusType.ALREADY_COMMITTED);
- break;
+ throw new AerospikeException(ResultCode.TXN_ALREADY_COMMITTED, "Transaction already committed");
case Txn.TxnState.ABORTED:
listener.OnSuccess(AbortStatus.AbortStatusType.ALREADY_ABORTED);
diff --git a/AerospikeClient/Main/AbortStatus.cs b/AerospikeClient/Main/AbortStatus.cs
index 94f2dee2..41bbb4db 100644
--- a/AerospikeClient/Main/AbortStatus.cs
+++ b/AerospikeClient/Main/AbortStatus.cs
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2024 Aerospike, Inc.
+ * Copyright 2012-2025 Aerospike, Inc.
*
* Portions may be licensed to Aerospike, Inc. under one or more contributor
* license agreements.
@@ -25,7 +25,6 @@ public static class AbortStatus
public enum AbortStatusType
{
OK,
- ALREADY_COMMITTED,
ALREADY_ABORTED,
ROLL_BACK_ABANDONED,
CLOSE_ABANDONED
@@ -36,7 +35,6 @@ public static string AbortErrorToString(AbortStatusType status)
return status switch
{
AbortStatusType.OK => "Abort succeeded.",
- AbortStatusType.ALREADY_COMMITTED => "Already committed.",
AbortStatusType.ALREADY_ABORTED => "Already aborted.",
AbortStatusType.ROLL_BACK_ABANDONED => "MRT client roll back abandoned. Server will eventually abort the MRT.",
AbortStatusType.CLOSE_ABANDONED => "MRT has been rolled back, but MRT client close was abandoned. Server will eventually close the MRT.",
diff --git a/AerospikeClient/Main/AerospikeClient.cs b/AerospikeClient/Main/AerospikeClient.cs
index a91de549..678b8201 100644
--- a/AerospikeClient/Main/AerospikeClient.cs
+++ b/AerospikeClient/Main/AerospikeClient.cs
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2024 Aerospike, Inc.
+ * Copyright 2012-2025 Aerospike, Inc.
*
* Portions may be licensed to Aerospike, Inc. under one or more contributor
* license agreements.
@@ -516,7 +516,7 @@ public CommitStatus.CommitStatusType Commit(Txn txn)
return CommitStatus.CommitStatusType.ALREADY_COMMITTED;
case Txn.TxnState.ABORTED:
- return CommitStatus.CommitStatusType.ALREADY_ABORTED;
+ throw new AerospikeException(ResultCode.TXN_ALREADY_ABORTED, "Transaction already aborted");
}
}
@@ -540,8 +540,8 @@ public AbortStatus.AbortStatusType Abort(Txn txn)
return tr.Abort(txnRollPolicyDefault);
case Txn.TxnState.COMMITTED:
- return AbortStatus.AbortStatusType.ALREADY_COMMITTED;
-
+ throw new AerospikeException(ResultCode.TXN_ALREADY_COMMITTED, "Transaction already committed");
+
case Txn.TxnState.ABORTED:
return AbortStatus.AbortStatusType.ALREADY_ABORTED;
}
diff --git a/AerospikeClient/Main/CommitStatus.cs b/AerospikeClient/Main/CommitStatus.cs
index 50c9a7d2..1386b303 100644
--- a/AerospikeClient/Main/CommitStatus.cs
+++ b/AerospikeClient/Main/CommitStatus.cs
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2024 Aerospike, Inc.
+ * Copyright 2012-2025 Aerospike, Inc.
*
* Portions may be licensed to Aerospike, Inc. under one or more contributor
* license agreements.
@@ -28,7 +28,6 @@ public enum CommitStatusType
{
OK,
ALREADY_COMMITTED,
- ALREADY_ABORTED,
ROLL_FORWARD_ABANDONED,
CLOSE_ABANDONED
}
@@ -39,7 +38,6 @@ public static string CommitErrorToString(CommitStatusType status)
{
CommitStatusType.OK => "Commit succeeded.",
CommitStatusType.ALREADY_COMMITTED => "Already committed.",
- CommitStatusType.ALREADY_ABORTED => "Already aborted.",
CommitStatusType.ROLL_FORWARD_ABANDONED => "MRT client roll forward abandoned. Server will eventually commit the MRT.",
CommitStatusType.CLOSE_ABANDONED => "MRT has been rolled forward, but MRT client close was abandoned. Server will eventually close the MRT.",
_ => "Unexpected AbortStatusType."
diff --git a/AerospikeClient/Main/ResultCode.cs b/AerospikeClient/Main/ResultCode.cs
index 9e701fb6..65b6924e 100644
--- a/AerospikeClient/Main/ResultCode.cs
+++ b/AerospikeClient/Main/ResultCode.cs
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2024 Aerospike, Inc.
+ * Copyright 2012-2025 Aerospike, Inc.
*
* Portions may be licensed to Aerospike, Inc. under one or more contributor
* license agreements.
@@ -22,7 +22,19 @@ namespace Aerospike.Client
/// Database operation error codes.
///
public sealed class ResultCode
- {
+ {
+ ///
+ /// Multi-record transaction commit called, but the transaction was already aborted.
+ /// Value: -19
+ ///
+ public const int TXN_ALREADY_ABORTED = -19;
+
+ ///
+ /// Multi-record transaction abort called, but the transaction was already committed.
+ /// Value: -18
+ ///
+ public const int TXN_ALREADY_COMMITTED = -18;
+
///
/// Multi-record transaction failed.
/// Value: -17
@@ -592,7 +604,13 @@ public static bool KeepConnection(int resultCode)
public static string GetResultString(int resultCode)
{
switch (resultCode)
- {
+ {
+ case TXN_ALREADY_ABORTED:
+ return "Multi-record transaction already aborted";
+
+ case TXN_ALREADY_COMMITTED:
+ return "Multi-record transaction already committed";
+
case TXN_FAILED:
return "Multi-record transaction failed";
diff --git a/AerospikeTest/Async/TestAsyncTxn.cs b/AerospikeTest/Async/TestAsyncTxn.cs
index af397f37..3f23fe46 100644
--- a/AerospikeTest/Async/TestAsyncTxn.cs
+++ b/AerospikeTest/Async/TestAsyncTxn.cs
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2018 Aerospike, Inc.
+ * Copyright 2012-2025 Aerospike, Inc.
*
* Portions may be licensed to Aerospike, Inc. under one or more contributor
* license agreements.
@@ -357,7 +357,7 @@ public void AsyncTxnWriteCommitAbort()
new Put(txn, key, "val2"),
new Commit(txn),
new GetExpect(null, key, "val2"),
- new Abort(txn, AbortStatus.AbortStatusType.ALREADY_COMMITTED)
+ new Abort(txn, ResultCode.TXN_ALREADY_COMMITTED)
};
Execute(cmds);
@@ -578,6 +578,7 @@ public class Abort : Runner
{
private readonly Txn txn;
private readonly AbortStatusType status;
+ private readonly int resultCode = 0;
public Abort(Txn txn)
{
@@ -591,9 +592,22 @@ public Abort(Txn txn, AbortStatusType abortStatus)
this.status = abortStatus;
}
+ public Abort(Txn txn, int resultCode)
+ {
+ this.txn = txn;
+ this.resultCode = resultCode;
+ }
+
public void Run(TestAsyncTxn parent, Listener listener)
{
- client.Abort(new AbortHandler(listener, status), txn);
+ try
+ {
+ client.Abort(new AbortHandler(listener, status), txn);
+ }
+ catch (Exception e)
+ {
+ parent.OnError(e, resultCode);
+ }
}
private class AbortHandler : AbortListener
diff --git a/AerospikeTest/Sync/Basic/TestTxn.cs b/AerospikeTest/Sync/Basic/TestTxn.cs
index b5024183..b17733bd 100644
--- a/AerospikeTest/Sync/Basic/TestTxn.cs
+++ b/AerospikeTest/Sync/Basic/TestTxn.cs
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2018 Aerospike, Inc.
+ * Copyright 2012-2025 Aerospike, Inc.
*
* Portions may be licensed to Aerospike, Inc. under one or more contributor
* license agreements.
@@ -498,8 +498,17 @@ public void TxnWriteCommitAbort()
record = client.Get(null, key);
AssertBinEqual(key, record, binName, "val2");
- var abortStatus = client.Abort(txn);
- Assert.AreEqual(AbortStatus.AbortStatusType.ALREADY_COMMITTED, abortStatus);
+ try
+ {
+ var abortStatus = client.Abort(txn);
+ }
+ catch (AerospikeException ae)
+ {
+ if (ae.Result != ResultCode.TXN_ALREADY_COMMITTED)
+ {
+ throw;
+ }
+ }
}
[TestMethod]