This is an automated email from the ASF dual-hosted git repository.
ptupitsyn pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new 40f6d16a79 IGNITE-18892 Implement ClientTransaction.isReadonly and
readTimestamp (#1715)
40f6d16a79 is described below
commit 40f6d16a79e22a71f1837a54b333ff0f727e72d5
Author: Pavel Tupitsyn <[email protected]>
AuthorDate: Tue Feb 28 11:32:22 2023 +0300
IGNITE-18892 Implement ClientTransaction.isReadonly and readTimestamp
(#1715)
---
.../java/org/apache/ignite/tx/Transaction.java | 3 ++-
.../requests/tx/ClientTransactionBeginRequest.java | 15 ++++++++++++---
.../internal/client/tx/ClientTransaction.java | 18 +++++++++++++-----
.../internal/client/tx/ClientTransactions.java | 20 ++++++++++++++++++--
.../RepeatedFinishClientTransactionTest.java | 8 ++++----
.../app/client/ItThinClientTransactionsTest.java | 22 ++++++++++++++++++++++
6 files changed, 71 insertions(+), 15 deletions(-)
diff --git a/modules/api/src/main/java/org/apache/ignite/tx/Transaction.java
b/modules/api/src/main/java/org/apache/ignite/tx/Transaction.java
index 0070413267..5d647c436b 100644
--- a/modules/api/src/main/java/org/apache/ignite/tx/Transaction.java
+++ b/modules/api/src/main/java/org/apache/ignite/tx/Transaction.java
@@ -19,6 +19,7 @@ package org.apache.ignite.tx;
import java.util.concurrent.CompletableFuture;
import org.apache.ignite.internal.hlc.HybridTimestamp;
+import org.jetbrains.annotations.Nullable;
/**
* The transaction.
@@ -68,5 +69,5 @@ public interface Transaction {
*
* @return Read timestamp for the given transaction if it is a read-only
one or {code null} otherwise.
*/
- HybridTimestamp readTimestamp();
+ @Nullable HybridTimestamp readTimestamp();
}
diff --git
a/modules/client-handler/src/main/java/org/apache/ignite/client/handler/requests/tx/ClientTransactionBeginRequest.java
b/modules/client-handler/src/main/java/org/apache/ignite/client/handler/requests/tx/ClientTransactionBeginRequest.java
index 15e6890022..a3476835ab 100644
---
a/modules/client-handler/src/main/java/org/apache/ignite/client/handler/requests/tx/ClientTransactionBeginRequest.java
+++
b/modules/client-handler/src/main/java/org/apache/ignite/client/handler/requests/tx/ClientTransactionBeginRequest.java
@@ -51,12 +51,21 @@ public class ClientTransactionBeginRequest {
options = new TransactionOptions().readOnly(true);
}
- return transactions.beginAsync(options).thenAccept(t -> {
+ return transactions.beginAsync(options).thenAccept(tx -> {
try {
- long resourceId = resources.put(new ClientResource(t,
t::rollbackAsync));
+ long resourceId = resources.put(new ClientResource(tx,
tx::rollbackAsync));
out.packLong(resourceId);
+
+ var readTs = tx.readTimestamp();
+
+ if (readTs != null) {
+ out.packLong(readTs.getPhysical());
+ out.packInt(readTs.getLogical());
+ } else {
+ out.packNil();
+ }
} catch (IgniteInternalCheckedException e) {
- t.rollback();
+ tx.rollback();
throw new IgniteInternalException(e.getMessage(), e);
}
});
diff --git
a/modules/client/src/main/java/org/apache/ignite/internal/client/tx/ClientTransaction.java
b/modules/client/src/main/java/org/apache/ignite/internal/client/tx/ClientTransaction.java
index 9448579b7b..dd8c4ec4d3 100644
---
a/modules/client/src/main/java/org/apache/ignite/internal/client/tx/ClientTransaction.java
+++
b/modules/client/src/main/java/org/apache/ignite/internal/client/tx/ClientTransaction.java
@@ -29,6 +29,7 @@ import org.apache.ignite.lang.IgniteException;
import org.apache.ignite.tx.Transaction;
import org.apache.ignite.tx.TransactionException;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
/**
* Client transaction.
@@ -43,15 +44,24 @@ public class ClientTransaction implements Transaction {
/** The future used on repeated commit/rollback. */
private final AtomicReference<CompletableFuture<Void>> finishFut = new
AtomicReference<>();
+ /** Read-only flag. */
+ private final boolean isReadOnly;
+
+ /** Read timestamp. */
+ @Nullable
+ private final HybridTimestamp readTs;
+
/**
* Constructor.
*
* @param ch Channel that the transaction belongs to.
* @param id Transaction id.
*/
- public ClientTransaction(ClientChannel ch, long id) {
+ public ClientTransaction(ClientChannel ch, long id, boolean isReadOnly,
@Nullable HybridTimestamp readTs) {
this.ch = ch;
this.id = id;
+ this.isReadOnly = isReadOnly;
+ this.readTs = readTs;
}
/**
@@ -115,15 +125,13 @@ public class ClientTransaction implements Transaction {
/** {@inheritDoc} */
@Override
public boolean isReadOnly() {
- // TODO: IGNITE-17929 Add read-only support to ClientTransactions
- return false;
+ return isReadOnly;
}
/** {@inheritDoc} */
@Override
public HybridTimestamp readTimestamp() {
- // TODO: IGNITE-17929 Add read-only support to ClientTransactions
- throw new UnsupportedOperationException("Not implemented yet.");
+ return readTs;
}
/**
diff --git
a/modules/client/src/main/java/org/apache/ignite/internal/client/tx/ClientTransactions.java
b/modules/client/src/main/java/org/apache/ignite/internal/client/tx/ClientTransactions.java
index e905d18beb..e77e4bba26 100644
---
a/modules/client/src/main/java/org/apache/ignite/internal/client/tx/ClientTransactions.java
+++
b/modules/client/src/main/java/org/apache/ignite/internal/client/tx/ClientTransactions.java
@@ -20,11 +20,15 @@ package org.apache.ignite.internal.client.tx;
import static org.apache.ignite.internal.client.ClientUtils.sync;
import java.util.concurrent.CompletableFuture;
+import org.apache.ignite.internal.client.PayloadInputChannel;
import org.apache.ignite.internal.client.ReliableChannel;
+import org.apache.ignite.internal.client.proto.ClientMessageUnpacker;
import org.apache.ignite.internal.client.proto.ClientOp;
+import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.tx.IgniteTransactions;
import org.apache.ignite.tx.Transaction;
import org.apache.ignite.tx.TransactionOptions;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
@@ -57,9 +61,21 @@ public class ClientTransactions implements
IgniteTransactions {
throw new UnsupportedOperationException("Timeouts are not
supported yet");
}
+ boolean readOnly = options != null && options.readOnly();
+
return ch.serviceAsync(
ClientOp.TX_BEGIN,
- w -> w.out().packBoolean(options != null &&
options.readOnly()),
- r -> new ClientTransaction(r.clientChannel(),
r.in().unpackLong()));
+ w -> w.out().packBoolean(readOnly),
+ r -> readTx(r, readOnly));
+ }
+
+ @NotNull
+ private static ClientTransaction readTx(PayloadInputChannel r, boolean
isReadOnly) {
+ ClientMessageUnpacker in = r.in();
+
+ long id = in.unpackLong();
+ HybridTimestamp readTs = in.tryUnpackNil() ? null : new
HybridTimestamp(in.unpackLong(), in.unpackInt());
+
+ return new ClientTransaction(r.clientChannel(), id, isReadOnly,
readTs);
}
}
diff --git
a/modules/client/src/test/java/org/apache/ignite/internal/client/RepeatedFinishClientTransactionTest.java
b/modules/client/src/test/java/org/apache/ignite/internal/client/RepeatedFinishClientTransactionTest.java
index 7ffdf1010a..6115cd0885 100644
---
a/modules/client/src/test/java/org/apache/ignite/internal/client/RepeatedFinishClientTransactionTest.java
+++
b/modules/client/src/test/java/org/apache/ignite/internal/client/RepeatedFinishClientTransactionTest.java
@@ -47,7 +47,7 @@ public class RepeatedFinishClientTransactionTest {
TestClientChannel clientChannel = new
TestClientChannel(txFinishStartedLatch, secondFinishLatch);
- ClientTransaction tx = new ClientTransaction(clientChannel, 1);
+ ClientTransaction tx = new ClientTransaction(clientChannel, 1, false,
null);
CompletableFuture<Object> fut = new CompletableFuture<>();
@@ -85,7 +85,7 @@ public class RepeatedFinishClientTransactionTest {
TestClientChannel clientChannel = new
TestClientChannel(txFinishStartedLatch, secondFinishLatch);
- ClientTransaction tx = new ClientTransaction(clientChannel, 1);
+ ClientTransaction tx = new ClientTransaction(clientChannel, 1, false,
null);
CompletableFuture<Object> fut = new CompletableFuture<>();
@@ -122,7 +122,7 @@ public class RepeatedFinishClientTransactionTest {
when(clientChannel.serviceAsync(anyInt(), any(),
any())).thenReturn(failedFuture(new Exception("Expected exception.")));
- ClientTransaction tx = new ClientTransaction(clientChannel, 1);
+ ClientTransaction tx = new ClientTransaction(clientChannel, 1, false,
null);
CompletableFuture<Object> fut = new CompletableFuture<>();
@@ -148,7 +148,7 @@ public class RepeatedFinishClientTransactionTest {
when(clientChannel.serviceAsync(anyInt(), any(),
any())).thenReturn(failedFuture(new Exception("Expected exception.")));
- ClientTransaction tx = new ClientTransaction(clientChannel, 1);
+ ClientTransaction tx = new ClientTransaction(clientChannel, 1, false,
null);
CompletableFuture<Object> fut = new CompletableFuture<>();
diff --git
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/client/ItThinClientTransactionsTest.java
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/client/ItThinClientTransactionsTest.java
index e38a31ae4d..dd2b77777b 100644
---
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/client/ItThinClientTransactionsTest.java
+++
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/client/ItThinClientTransactionsTest.java
@@ -22,6 +22,8 @@ import static org.hamcrest.Matchers.containsString;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -326,6 +328,26 @@ public class ItThinClientTransactionsTest extends
ItAbstractThinClientTest {
}
}
+ @Test
+ void testReadOnlyTxHasReadTimestamp() {
+ Transaction tx = client().transactions().begin(new
TransactionOptions().readOnly(true));
+
+ assertTrue(tx.isReadOnly());
+ assertNotNull(tx.readTimestamp());
+
+ tx.rollback();
+ }
+
+ @Test
+ void testReadWriteTxHasNoReadTimestamp() {
+ Transaction tx = client().transactions().begin();
+
+ assertFalse(tx.isReadOnly());
+ assertNull(tx.readTimestamp());
+
+ tx.rollback();
+ }
+
private KeyValueView<Integer, String> kvView() {
return table().keyValueView(Mapper.of(Integer.class),
Mapper.of(String.class));
}