userver: userver/storages/mysql/cluster.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
cluster.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/storages/mysql/cluster.hpp
4/// @copybrief @copybrief storages::mysql::Cluster
5
6#include <memory>
7#include <optional>
8#include <string>
9
10#include <userver/clients/dns/resolver_fwd.hpp>
11#include <userver/components/component_fwd.hpp>
12#include <userver/engine/deadline.hpp>
13#include <userver/utils/statistics/writer.hpp>
14
15#include <userver/storages/mysql/cluster_host_type.hpp>
16#include <userver/storages/mysql/command_result_set.hpp>
17#include <userver/storages/mysql/cursor_result_set.hpp>
18#include <userver/storages/mysql/impl/bind_helper.hpp>
19#include <userver/storages/mysql/options.hpp>
20#include <userver/storages/mysql/query.hpp>
21#include <userver/storages/mysql/statement_result_set.hpp>
22#include <userver/storages/mysql/transaction.hpp>
23
24USERVER_NAMESPACE_BEGIN
25
26namespace storages::mysql {
27
28namespace settings {
29struct MysqlSettings;
30}
31
32namespace infra::topology {
33class TopologyBase;
34}
35
36/// @ingroup userver_clients
37///
38/// @brief Client interface for a cluster of MySQL servers.
39/// Usually retrieved from components::MySQL
40class Cluster final {
41 public:
42 /// @brief Cluster constructor
43 Cluster(clients::dns::Resolver& resolver,
44 const settings::MysqlSettings& settings,
45 const components::ComponentConfig& config);
46 /// @brief Cluster destructor
48
49 /// @brief Executes a statement on a host of host_type with default deadline.
50 /// Fills placeholders of the statement with args..., `Args` are expected to
51 /// be of supported types.
52 /// See @ref scripts/docs/en/userver/mysql/supported_types.md for better
53 /// understanding of `Args` requirements.
54 ///
55 /// UINVARIANTs on params count mismatch doesn't validate types.
56 template <typename... Args>
57 StatementResultSet Execute(ClusterHostType host_type, const Query& query,
58 const Args&... args) const;
59
60 // clang-format off
61 /// @brief Executes a statement on a host of host_type with provided
62 /// CommandControl.
63 /// Fills placeholders of the statement with args..., `Args` are expected to
64 /// be of supported types.
65 /// See @ref scripts/docs/en/userver/mysql/supported_types.md for better understanding of `Args`
66 /// requirements.
67 ///
68 /// UINVARIANTs on params count mismatch doesn't validate types.
69 ///
70 /// @snippet storages/tests/unittests/cluster_mysqltest.cpp uMySQL usage sample - Cluster Execute
71 // clang-format on
72 template <typename... Args>
73 StatementResultSet Execute(OptionalCommandControl command_control,
74 ClusterHostType host_type, const Query& query,
75 const Args&... args) const;
76
77 /// @brief Executes a statement on a host of host_type with default deadline
78 ///
79 /// Basically an alias for Execute(host_type, query, AsArgs<T>(row)),
80 /// where AsArgs is an imaginary function which passes fields of T as
81 /// variadic params. Handy for one-liner inserts.
82 /// See @ref scripts/docs/en/userver/mysql/supported_types.md for better
83 /// understanding of `T` requirements.
84 ///
85 /// UINVARIANTs on params count mismatch, doesn't validate types.
86 template <typename T>
87 StatementResultSet ExecuteDecompose(ClusterHostType host_type,
88 const Query& query, const T& row) const;
89
90 // clang-format off
91 /// @brief Executes a statement on a host of host_type with provided
92 /// CommandControl.
93 ///
94 /// Basically an alias for Execute(command_control, host_type, query,
95 /// AsArgs<T>(row)), where AsArgs is an imaginary function which passes
96 /// fields of T as variadic params. Handy for one-liner inserts.
97 /// See @ref scripts/docs/en/userver/mysql/supported_types.md for better understanding of `T` requirements.
98 ///
99 /// UINVARIANTs on params count mismatch, doesn't validate types.
100 ///
101 /// @snippet storages/tests/unittests/cluster_mysqltest.cpp uMySQL usage sample - Cluster ExecuteDecompose
102 // clang-format on
103 template <typename T>
104 StatementResultSet ExecuteDecompose(OptionalCommandControl command_control,
105 ClusterHostType host_type,
106 const Query& query, const T& row) const;
107
108 /// @brief Executes a statement on a host of host_type with default deadline.
109 /// Fills placeholders of the statements with Container::value_type in a
110 /// bulk-manner.
111 /// Container is expected to be a std::Container, Container::value_type is
112 /// expected to be an aggregate of supported types.
113 /// See @ref scripts/docs/en/userver/mysql/supported_types.md for better
114 /// understanding of `Container::value_type` requirements.
115 ///
116 /// @note Requires MariaDB 10.2.6+ as a server
117 ///
118 /// UINVARIANTs on params count mismatch, doesn't validate types.
119 /// UINVARIANTs on empty params container.
120 template <typename Container>
121 StatementResultSet ExecuteBulk(ClusterHostType host_type, const Query& query,
122 const Container& params) const;
123
124 // clang-format off
125 /// @brief Executes a statement on a host of host_type with provided
126 /// CommandControl.
127 /// Fills placeholders of the statements with
128 /// Container::value_type in a bulk-manner.
129 /// Container is expected to be a std::Container, Container::value_type is
130 /// expected to be an aggregate of supported types.
131 /// See @ref scripts/docs/en/userver/mysql/supported_types.md for better understanding of
132 /// `Container::value_type` requirements.
133 ///
134 /// @note Requires MariaDB 10.2.6+ as a server
135 ///
136 /// UINVARIANTs on params count mismatch, doesn't validate types.
137 /// UINVARIANTs on empty params container.
138 /// @snippet storages/tests/unittests/cluster_mysqltest.cpp uMySQL usage sample - Cluster ExecuteBulk
139 // clang-format on
140 template <typename Container>
141 StatementResultSet ExecuteBulk(OptionalCommandControl command_control,
142 ClusterHostType host_type, const Query& query,
143 const Container& params) const;
144
145 // TODO : don't require Container to be const, so Convert can move
146 // clang-format off
147 /// @brief Executes a statement on a host of host_type with default deadline,
148 /// on the flight remapping from `Container::value_type` to `MapTo`.
149 /// `Container` is expected to be a std::Container of whatever type pleases
150 /// you, `MapTo` is expected to be an aggregate of supported types.
151 /// See @ref scripts/docs/en/userver/mysql/supported_types.md for better understanding of `MapTo` requirements.
152 /// You are expected to provide a converter function
153 /// `MapTo Convert(const Container::value_type&, storages::mysql::convert::To<MapTo>)`
154 /// in namespace of `MapTo` or storages::mysql::convert.
155 ///
156 /// @note Requires MariaDB 10.2.6+ as a server
157 ///
158 /// UINVARIANTs on params count mismatch, doesn't validate types.
159 /// UINVARIANTs on empty params container.
160 template <typename MapTo, typename Container>
161 StatementResultSet ExecuteBulkMapped(ClusterHostType host_type,
162 const Query& query,
163 const Container& params) const;
164 // clang-format on
165
166 // TODO : don't require Container to be const, so Convert can move
167 // clang-format off
168 /// @brief Executes a statement on a host of host_type with provided
169 /// CommandControl, on the flight remapping from `Container::value_type`
170 /// to `MapTo`.
171 /// `Container` is expected to be a std::Container of whatever type pleases
172 /// you, `MapTo` is expected to be an aggregate of supported types.
173 /// See @ref scripts/docs/en/userver/mysql/supported_types.md for better understanding of `MapTo` requirements.
174 /// You are expected to provide a converter function
175 /// `MapTo Convert(const Container::value_type&, storages::mysql::convert::To<MapTo>)`
176 /// in namespace of `MapTo` or storages::mysql::convert.
177 ///
178 /// @note Requires MariaDB 10.2.6+ as a server
179 ///
180 /// UINVARIANTs on params count mismatch, doesn't validate types.
181 /// UINVARIANTs on empty params container.
182 ///
183 /// @snippet storages/tests/unittests/cluster_mysqltest.cpp uMySQL usage sample - Cluster ExecuteBulkMapped
184 // clang-format on
185 template <typename MapTo, typename Container>
186 StatementResultSet ExecuteBulkMapped(OptionalCommandControl command_control,
187 ClusterHostType host_type,
188 const Query& query,
189 const Container& params) const;
190
191 /// @brief Begin a transaction with default deadline.
192 ///
193 /// @note The deadline is transaction-wide, not just for Begin query itself.
194 ///
195 /// @param host_type Host type on which to execute transaction.
196 Transaction Begin(ClusterHostType host_type) const;
197
198 /// @brief Being a transaction with specified CommandControl.
199 ///
200 /// @note The deadline is transaction-wide, not just for Begin query itself.
201 ///
202 /// @param host_type Host type on which to execute transaction.
203 Transaction Begin(OptionalCommandControl command_control,
204 ClusterHostType host_type) const;
205
206 /// @brief Executes a command on host of type host_type over plan-text
207 /// protocol, with default deadline.
208 ///
209 /// This method is intended to be used for statements that cannot be prepared
210 /// or as an escape hatch from typed parsing if you really need to, but such
211 /// use is neither recommended nor optimized for.
212 CommandResultSet ExecuteCommand(ClusterHostType host_type,
213 const Query& command) const;
214
215 // clang-format off
216 /// @brief Executes a command on host of type host_type over plan-text
217 /// protocol, with provided CommandControl.
218 ///
219 /// This method is intended to be used for statements that cannot be prepared
220 /// or as an escape hatch from typed parsing if you really need to, but such
221 /// use is neither recommended nor optimized for.
222 ///
223 /// @snippet storages/tests/unittests/cluster_mysqltest.cpp uMySQL usage sample - Cluster ExecuteCommand
224 // clang-format on
225 CommandResultSet ExecuteCommand(OptionalCommandControl command_control,
226 ClusterHostType host_type,
227 const Query& command) const;
228
229 /// @brief Executes a statement with default deadline on a host of host_type,
230 /// filling statements placeholders with `args...`, and returns a read-only
231 /// cursor which fetches `batch_count` rows in each next fetch request.
232 /// See @ref scripts/docs/en/userver/mysql/supported_types.md for better
233 /// understanding of `Args` requirements.
234 ///
235 /// @note Deadline is processing-wide, not just for initial cursor creation.
236 ///
237 /// UINVARIANTs on params count mismatch, doesn't validate types.
238 template <typename T, typename... Args>
239 CursorResultSet<T> GetCursor(ClusterHostType host_type,
240 std::size_t batch_size, const Query& query,
241 const Args&... args) const;
242
243 // clang-format off
244 /// @brief Executes a statement with provided CommandControl on
245 /// a host of host_type, filling statements placeholders with `args...`, and
246 /// returns a read-only cursor which fetches `batch_count` rows in each next
247 /// fetch request.
248 /// See @ref scripts/docs/en/userver/mysql/supported_types.md for better understanding of `Args`
249 /// requirements.
250 ///
251 /// @note Deadline is processing-wide, not just for initial cursor creation.
252 ///
253 /// UINVARIANTs on params count mismatch, doesn't validate types.
254 ///
255 /// @snippet storages/tests/unittests/cluster_mysqltest.cpp uMySQL usage sample - Cluster GetCursor
256 // clang-format on
257 template <typename T, typename... Args>
258 CursorResultSet<T> GetCursor(OptionalCommandControl command_control,
259 ClusterHostType host_type,
260 std::size_t batch_size, const Query& query,
261 const Args&... args) const;
262
263 /// Write cluster statistics
264 void WriteStatistics(utils::statistics::Writer& writer) const;
265
266 private:
267 static CommandControl GetDefaultCommandControl();
268
269 StatementResultSet DoExecute(OptionalCommandControl command_control,
270 ClusterHostType host_type, const Query& query,
271 impl::io::ParamsBinderBase& params,
272 std::optional<std::size_t> batch_size) const;
273
274 std::unique_ptr<infra::topology::TopologyBase> topology_;
275};
276
277template <typename... Args>
278StatementResultSet Cluster::Execute(ClusterHostType host_type,
279 const Query& query,
280 const Args&... args) const {
281 return Execute(std::nullopt, host_type, query, args...);
282}
283
284template <typename... Args>
285StatementResultSet Cluster::Execute(OptionalCommandControl command_control,
286 ClusterHostType host_type,
287 const Query& query,
288 const Args&... args) const {
289 auto params_binder = impl::BindHelper::BindParams(args...);
290
291 return DoExecute(command_control, host_type, query.GetStatement(),
292 params_binder, std::nullopt);
293}
294
295template <typename T>
296StatementResultSet Cluster::ExecuteDecompose(ClusterHostType host_type,
297 const Query& query,
298 const T& row) const {
299 return ExecuteDecompose(std::nullopt, host_type, query, row);
300}
301
302template <typename T>
303StatementResultSet Cluster::ExecuteDecompose(
304 OptionalCommandControl command_control, ClusterHostType host_type,
305 const Query& query, const T& row) const {
306 auto params_binder = impl::BindHelper::BindRowAsParams(row);
307
308 return DoExecute(command_control, host_type, query, params_binder,
309 std::nullopt);
310}
311
312template <typename Container>
313StatementResultSet Cluster::ExecuteBulk(ClusterHostType host_type,
314 const Query& query,
315 const Container& params) const {
316 return ExecuteBulk(std::nullopt, host_type, query, params);
317}
318
319template <typename Container>
320StatementResultSet Cluster::ExecuteBulk(OptionalCommandControl command_control,
321 ClusterHostType host_type,
322 const Query& query,
323 const Container& params) const {
324 UINVARIANT(!params.empty(), "Empty params in bulk execution");
325
326 auto params_binder = impl::BindHelper::BindContainerAsParams(params);
327
328 return DoExecute(command_control, host_type, query.GetStatement(),
329 params_binder, std::nullopt);
330}
331
332template <typename MapTo, typename Container>
333StatementResultSet Cluster::ExecuteBulkMapped(ClusterHostType host_type,
334 const Query& query,
335 const Container& params) const {
336 return ExecuteBulkMapped<MapTo>(std::nullopt, host_type, query, params);
337}
338
339template <typename MapTo, typename Container>
340StatementResultSet Cluster::ExecuteBulkMapped(
341 OptionalCommandControl command_control, ClusterHostType host_type,
342 const Query& query, const Container& params) const {
343 UINVARIANT(!params.empty(), "Empty params in bulk execution");
344
345 auto params_binder =
346 impl::BindHelper::BindContainerAsParamsMapped<MapTo>(params);
347
348 return DoExecute(command_control, host_type, query.GetStatement(),
349 params_binder, std::nullopt);
350}
351
352template <typename T, typename... Args>
353CursorResultSet<T> Cluster::GetCursor(ClusterHostType host_type,
354 std::size_t batch_size,
355 const Query& query,
356 const Args&... args) const {
357 return GetCursor<T>(std::nullopt, host_type, batch_size, query, args...);
358}
359
360template <typename T, typename... Args>
361CursorResultSet<T> Cluster::GetCursor(OptionalCommandControl command_control,
362 ClusterHostType host_type,
363 std::size_t batch_size,
364 const Query& query,
365 const Args&... args) const {
366 auto params_binder = impl::BindHelper::BindParams(args...);
367
368 return CursorResultSet<T>{
369 DoExecute(command_control, host_type, query, params_binder, batch_size)};
370}
371
372} // namespace storages::mysql
373
374USERVER_NAMESPACE_END