userver: userver/ydb/transaction.hpp Source File
Loading...
Searching...
No Matches
transaction.hpp
1#pragma once
2
3#include <functional>
4#include <string>
5
6#include <ydb-cpp-sdk/client/query/client.h>
7#include <ydb-cpp-sdk/client/table/table.h>
8
9#include <userver/engine/deadline.hpp>
10#include <userver/tracing/span.hpp>
11#include <userver/utils/function_ref.hpp>
12#include <userver/utils/trx_tracker.hpp>
13
14#include <userver/ydb/builder.hpp>
15#include <userver/ydb/exceptions.hpp>
16#include <userver/ydb/impl/stats_scope.hpp>
17#include <userver/ydb/query.hpp>
18#include <userver/ydb/response.hpp>
19#include <userver/ydb/settings.hpp>
20
21USERVER_NAMESPACE_BEGIN
22
23namespace ydb {
24
25class TxActor;
26
27/// Action to take after the retry function completes.
28enum class TxAction {
29 kCommit,
30 kRollback,
31};
32
33/// Signature for the function passed to TableClient::RetryTx.
34using RetryTxFunction = utils::function_ref<TxAction(TxActor&)>;
35
36/// @brief Transaction actor for use with TableClient::RetryTx.
37///
38/// Provides only query execution within a transaction. Commit and rollback
39/// are controlled by returning TxAction from the retry function.
40/// https://ydb.tech/docs/en/concepts/transactions
41class TxActor {
42public:
43 TxActor(const TxActor&) = delete;
44 TxActor& operator=(const TxActor&) = delete;
45 TxActor(TxActor&&) noexcept = delete;
46 TxActor& operator=(TxActor&&) = delete;
47
48 /// Execute a single data query as a part of the transaction. Query parameters
49 /// are passed in `Args` as "string key - value" pairs:
50 ///
51 /// @code
52 /// tx.Execute(query, "name1", value1, "name2", value2, ...);
53 /// @endcode
54 ///
55 /// Use ydb::PreparedArgsBuilder for storing a generic buffer of query params
56 /// if needed.
57 ///
58 /// @{
59 template <typename... Args>
60 ExecuteResponse Execute(const Query& query, Args&&... args);
61
62 template <typename... Args>
63 ExecuteResponse Execute(ExecuteSettings settings, const Query& query, Args&&... args);
64
65 ExecuteResponse Execute(ExecuteSettings settings, const Query& query, PreparedArgsBuilder&& builder);
66 /// @}
67
68 PreparedArgsBuilder GetBuilder() const;
69
70private:
71 friend class TableClient;
72
73 TxActor(
74 TableClient& table_client,
75 NYdb::NQuery::TSession& session,
76 NYdb::NQuery::TTxSettings&& tx_settings,
77 engine::Deadline deadline,
78 std::uint32_t attempt
79 ) noexcept;
80
81 NYdb::NQuery::TTransaction BeginTx(NYdb::NQuery::TSession& session, NYdb::NQuery::TTxSettings&& tx_settings);
82
83 template <TxAction Action>
84 void FinishTx(const RequestSettings& settings);
85
86 TableClient& table_client_;
87 engine::Deadline deadline_;
88 std::uint32_t attempt_;
89
90 NYdb::NQuery::TTransaction ydb_tx_;
91};
92
93template <typename... Args>
94ExecuteResponse TxActor::Execute(const Query& query, Args&&... args) {
95 auto builder = GetBuilder();
96 builder.AddParams(std::forward<Args>(args)...);
97 return Execute(ExecuteSettings{}, query, std::move(builder));
98}
99
100template <typename... Args>
101ExecuteResponse TxActor::Execute(ExecuteSettings settings, const Query& query, Args&&... args) {
102 auto builder = GetBuilder();
103 builder.AddParams(std::forward<Args>(args)...);
104 return Execute(std::move(settings), query, std::move(builder));
105}
106
107/// @brief YDB Transaction
108///
109/// @deprecated Use TableClient::RetryTx instead of manually managing
110/// transactions with Begin/Commit/Rollback.
111///
112/// https://ydb.tech/docs/en/concepts/transactions
113class Transaction final {
114public:
115 Transaction(Transaction&&) noexcept = default;
116 Transaction(const Transaction&) = delete;
117 Transaction& operator=(Transaction&&) = delete;
118 Transaction& operator=(const Transaction&) = delete;
119 ~Transaction();
120
121 /// Execute a single data query as a part of the transaction. Query parameters
122 /// are passed in `Args` as "string key - value" pairs:
123 ///
124 /// @code
125 /// client.ExecuteDataQuery(query, "name1", value1, "name2", value2, ...);
126 /// @endcode
127 ///
128 /// Use ydb::PreparedArgsBuilder for storing a generic buffer of query params
129 /// if needed.
130 ///
131 /// @{
132 template <typename... Args>
133 ExecuteResponse Execute(const Query& query, Args&&... args);
134
135 template <typename... Args>
136 ExecuteResponse Execute(OperationSettings settings, const Query& query, Args&&... args);
137
138 ExecuteResponse Execute(OperationSettings settings, const Query& query, PreparedArgsBuilder&& builder);
139
140 ExecuteResponse Execute(
141 QuerySettings query_settings,
142 OperationSettings settings,
143 const Query& query,
144 PreparedArgsBuilder&& builder
145 );
146 /// @}
147
148 /// Commit the transaction. The options that are missing in `settings` are
149 /// taken from the static config or driver defaults. `settings` can be
150 /// overridden by dynamic config's options for `Commit` "query".
151 void Commit(OperationSettings settings = {});
152
153 /// Rollback the transaction. The operation settings are taken from `Begin`
154 /// settings.
155 void Rollback();
156
157 PreparedArgsBuilder GetBuilder() const;
158
159 /// @cond
160 // For internal use only.
161 Transaction(
162 TableClient& table_client,
163 std::variant<NYdb::NQuery::TTransaction, NYdb::NTable::TTransaction> ydb_tx,
164 std::string name,
165 OperationSettings&& rollback_settings
166 ) noexcept;
167 /// @endcond
168
169 /// Get native transaction
170 /// @warning Use with care! Facilities from
171 /// `<core/include/userver/drivers/subscribable_futures.hpp>` can help with
172 /// non-blocking wait operations.
173 NYdb::TTransactionBase& GetNativeTransaction();
174
175private:
176 void MarkError() noexcept;
177 auto ErrorGuard();
178
179 void EnsureActive() const;
180
181 TableClient& table_client_;
182 std::string name_;
183 impl::StatsScope stats_scope_;
184 tracing::Span span_;
185 std::variant<NYdb::NQuery::TTransaction, NYdb::NTable::TTransaction> ydb_tx_;
186 OperationSettings rollback_settings_;
187 bool is_active_{true};
188 utils::trx_tracker::TransactionLock trx_lock_;
189};
190
191template <typename... Args>
192ExecuteResponse Transaction::Execute(const Query& query, Args&&... args) {
193 auto builder = GetBuilder();
194 builder.AddParams(std::forward<Args>(args)...);
195 return Execute(OperationSettings{}, query, std::move(builder));
196}
197
198template <typename... Args>
199ExecuteResponse Transaction::Execute(OperationSettings settings, const Query& query, Args&&... args) {
200 auto builder = GetBuilder();
201 builder.AddParams(std::forward<Args>(args)...);
202 return Execute(std::move(settings), query, std::move(builder));
203}
204
205} // namespace ydb
206
207USERVER_NAMESPACE_END