This is an automated email from the ASF dual-hosted git repository.

isapego 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 ab8a6b82839 IGNITE-25488 C++ Client: Add transaction timeouts (#6352)
ab8a6b82839 is described below

commit ab8a6b82839e6d1d30329aec38fb32945aa075e9
Author: Ed Rakhmankulov <[email protected]>
AuthorDate: Tue Aug 5 16:25:48 2025 +0300

    IGNITE-25488 C++ Client: Add transaction timeouts (#6352)
---
 .../client/detail/transaction/transactions_impl.h  | 10 ++--
 .../client/transaction/transaction_options.h       | 63 ++++++++++++++++++++++
 .../cpp/ignite/client/transaction/transactions.cpp |  6 ++-
 .../cpp/ignite/client/transaction/transactions.h   | 21 +++++++-
 .../cpp/tests/client-test/transactions_test.cpp    | 52 ++++++++++++++++++
 5 files changed, 146 insertions(+), 6 deletions(-)

diff --git 
a/modules/platforms/cpp/ignite/client/detail/transaction/transactions_impl.h 
b/modules/platforms/cpp/ignite/client/detail/transaction/transactions_impl.h
index ea052b51976..a58ac2520a7 100644
--- a/modules/platforms/cpp/ignite/client/detail/transaction/transactions_impl.h
+++ b/modules/platforms/cpp/ignite/client/detail/transaction/transactions_impl.h
@@ -19,6 +19,7 @@
 
 #include "ignite/client/detail/cluster_connection.h"
 #include "ignite/client/detail/transaction/transaction_impl.h"
+#include "ignite/client/transaction/transaction_options.h"
 
 #include "ignite/common/detail/config.h"
 #include "ignite/common/ignite_result.h"
@@ -53,11 +54,12 @@ public:
      * Starts a new transaction asynchronously.
      *
      * @param callback Callback to be called with a new transaction or error 
upon completion of asynchronous operation.
+     * @param tx_opts Transaction options.
      */
-    IGNITE_API void begin_async(ignite_callback<transaction> callback) {
-        auto writer_func = [this](protocol::writer &writer, auto) {
-            writer.write_bool(false); // readOnly.
-            writer.write(std::int64_t(0)); // timeoutMillis.
+    IGNITE_API void begin_async(transaction_options tx_opts, 
ignite_callback<transaction> callback) {
+        auto writer_func = [this, &tx_opts](protocol::writer &writer, auto) {
+            writer.write_bool(tx_opts.is_read_only());
+            writer.write(tx_opts.get_timeout_millis());
             writer.write(m_connection->get_observable_timestamp());
         };
 
diff --git 
a/modules/platforms/cpp/ignite/client/transaction/transaction_options.h 
b/modules/platforms/cpp/ignite/client/transaction/transaction_options.h
new file mode 100644
index 00000000000..436576beb3e
--- /dev/null
+++ b/modules/platforms/cpp/ignite/client/transaction/transaction_options.h
@@ -0,0 +1,63 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+/**
+ * Transaction options.
+ */
+class transaction_options {
+public:
+    /**
+     * Transaction timeout.
+     *
+     * @return Transaction timeout in milliseconds.
+     */
+    [[nodiscard]] std::int64_t get_timeout_millis() const { return 
m_timeout_millis; }
+
+    /**
+     * Sets new value for transaction timeout.
+     *
+     * @param timeout_millis Transaction timeout in milliseconds.
+     * @return Reference to this for chaining.
+     */
+    transaction_options & set_timeout_millis(std::int64_t timeout_millis) {
+        m_timeout_millis = timeout_millis;
+        return *this;
+    }
+
+    /**
+     * Transaction allow only read operations.
+     *
+     * @return True if only read operation are allowed false otherwise.
+     */
+    [[nodiscard]] bool is_read_only() const { return m_read_only; }
+
+    /**
+     * Change transaction to be read-only or read-write.
+     *
+     * @param read_only True if transaction should read-only, false if 
read-write.
+     * @return Reference to this for chaining.
+     */
+    transaction_options & set_read_only(bool read_only) {
+        m_read_only = read_only;
+        return *this;
+    }
+private:
+    std::int64_t m_timeout_millis = 0;
+    bool m_read_only = false;
+};
diff --git a/modules/platforms/cpp/ignite/client/transaction/transactions.cpp 
b/modules/platforms/cpp/ignite/client/transaction/transactions.cpp
index 2253eff7c4e..eb71d029a99 100644
--- a/modules/platforms/cpp/ignite/client/transaction/transactions.cpp
+++ b/modules/platforms/cpp/ignite/client/transaction/transactions.cpp
@@ -20,8 +20,12 @@
 
 namespace ignite {
 
+void transactions::begin_async(transaction_options tx_opts, 
ignite_callback<transaction> callback) {
+    m_impl->begin_async(tx_opts, std::move(callback));
+}
+
 void transactions::begin_async(ignite_callback<transaction> callback) {
-    m_impl->begin_async(std::move(callback));
+    m_impl->begin_async({}, std::move(callback));
 }
 
 } // namespace ignite
diff --git a/modules/platforms/cpp/ignite/client/transaction/transactions.h 
b/modules/platforms/cpp/ignite/client/transaction/transactions.h
index 4ff5993f727..e418ea1cc84 100644
--- a/modules/platforms/cpp/ignite/client/transaction/transactions.h
+++ b/modules/platforms/cpp/ignite/client/transaction/transactions.h
@@ -18,6 +18,7 @@
 #pragma once
 
 #include "ignite/client/transaction/transaction.h"
+#include "ignite/client/transaction/transaction_options.h"
 
 #include "ignite/common/detail/config.h"
 #include "ignite/common/ignite_result.h"
@@ -40,15 +41,33 @@ public:
     // Delete
     transactions() = delete;
 
+    /**
+     * Starts a new transaction.
+     *
+     * @param tx_opts Transaction options.
+     * @return A new transaction.
+     */
+    IGNITE_API transaction begin(transaction_options tx_opts) {
+        return sync<transaction>([this, &tx_opts](auto callback) { 
begin_async(tx_opts, std::move(callback)); });
+    }
+
     /**
      * Starts a new transaction.
      *
      * @return A new transaction.
      */
     IGNITE_API transaction begin() {
-        return sync<transaction>([this](auto callback) { 
begin_async(std::move(callback)); });
+        return begin({});
     }
 
+    /**
+     * Starts a new transaction asynchronously.
+     *
+     * @param tx_opts Transaction options.
+     * @param callback Callback to be called with a new transaction or error 
upon completion of asynchronous operation.
+     */
+    IGNITE_API void begin_async(transaction_options tx_opts, 
ignite_callback<transaction> callback);
+
     /**
      * Starts a new transaction asynchronously.
      *
diff --git a/modules/platforms/cpp/tests/client-test/transactions_test.cpp 
b/modules/platforms/cpp/tests/client-test/transactions_test.cpp
index 7c38a716898..c7fe62153bd 100644
--- a/modules/platforms/cpp/tests/client-test/transactions_test.cpp
+++ b/modules/platforms/cpp/tests/client-test/transactions_test.cpp
@@ -434,3 +434,55 @@ TEST_F(transactions_test, record_view_remove_all_exact) {
     auto values2 = record_view.remove_all(nullptr, {value0});
     ASSERT_TRUE(values2.empty());
 }
+
+TEST_F(transactions_test, tx_successful_when_timeout_does_not_exceed) {
+    auto record_view = 
m_client.get_tables().get_table(TABLE_1)->get_record_binary_view();
+
+    int64_t key = 42;
+    std::string val = "Lorem ipsum";
+
+    auto tx_opts = 
transaction_options().set_timeout_millis(10'000L).set_read_only(false);
+    auto tx = m_client.get_transactions().begin(tx_opts);
+
+    record_view.insert(&tx, get_tuple(key, val));
+
+    tx.commit();
+
+    auto value = record_view.get(nullptr, get_tuple(42));
+
+    ASSERT_TRUE(value.has_value());
+    EXPECT_EQ(key, value->get<int64_t>(KEY_COLUMN));
+    EXPECT_EQ(val, value->get<std::string>(VAL_COLUMN));
+}
+
+
+TEST_F(transactions_test, tx_failed_when_timeout_exceeds) {
+    auto record_view = 
m_client.get_tables().get_table(TABLE_1)->get_record_binary_view();
+
+    auto timeout_ms = 1'000L;
+
+    int64_t key = 42;
+    std::string val = "Lorem ipsum";
+    auto tx_opts = transaction_options()
+        .set_timeout_millis(timeout_ms)
+        .set_read_only(false);
+
+    auto tx = m_client.get_transactions().begin(tx_opts);
+
+    record_view.insert(&tx, get_tuple(key, val));
+
+    std::this_thread::sleep_for(std::chrono::milliseconds{timeout_ms * 2});
+
+    EXPECT_THROW(
+        {
+            try {
+                // TODO change to check tx.commit when IGNITE-24233 is 
implemented
+                // tx.commit();
+                auto rec = record_view.get(&tx, get_tuple(key));
+            } catch (const ignite_error& e) {
+                EXPECT_EQ(e.get_status_code(), 
error::code::TX_ALREADY_FINISHED_WITH_TIMEOUT);
+                throw;
+            }
+        },
+        ignite_error);
+}

Reply via email to