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