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