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 {
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