userver: userver/storages/mysql/cluster.hpp Source File
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 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
233 ExecuteCommand(OptionalCommandControl command_control, ClusterHostType host_type, const Query& command) const;
234
235 /// @brief Executes a statement with default deadline on a host of host_type,
236 /// filling statements placeholders with `args...`, and returns a read-only
237 /// cursor which fetches `batch_count` rows in each next fetch request.
238 /// See @ref scripts/docs/en/userver/mysql/supported_types.md for better
239 /// understanding of `Args` requirements.
240 ///
241 /// @note Deadline is processing-wide, not just for initial cursor creation.
242 ///
243 /// UINVARIANTs on params count mismatch, doesn't validate types.
244 template <typename T, typename... Args>
245 CursorResultSet<T>
246 GetCursor(ClusterHostType host_type, std::size_t batch_size, const Query& query, const Args&... args) const;
247
248 // clang-format off
249 /// @brief Executes a statement with provided CommandControl on
250 /// a host of host_type, filling statements placeholders with `args...`, and
251 /// returns a read-only cursor which fetches `batch_count` rows in each next
252 /// fetch request.
253 /// See @ref scripts/docs/en/userver/mysql/supported_types.md for better understanding of `Args`
254 /// requirements.
255 ///
256 /// @note Deadline is processing-wide, not just for initial cursor creation.
257 ///
258 /// UINVARIANTs on params count mismatch, doesn't validate types.
259 ///
260 /// @snippet mysql/tests/cluster.cpp uMySQL usage sample - Cluster GetCursor
261 // clang-format on
262 template <typename T, typename... Args>
263 CursorResultSet<T> GetCursor(
264 OptionalCommandControl command_control,
265 ClusterHostType host_type,
266 std::size_t batch_size,
267 const Query& query,
268 const Args&... args
269 ) const;
270
271 /// Write cluster statistics
272 void WriteStatistics(utils::statistics::Writer& writer) const;
273
274private:
275 static CommandControl GetDefaultCommandControl();
276
277 StatementResultSet DoExecute(
278 OptionalCommandControl command_control,
279 ClusterHostType host_type,
280 const Query& query,
281 impl::io::ParamsBinderBase& params,
282 std::optional<std::size_t> batch_size
283 ) const;
284
285 std::unique_ptr<infra::topology::TopologyBase> topology_;
286};
287
288template <typename... Args>
289StatementResultSet Cluster::Execute(ClusterHostType host_type, const Query& query, const Args&... args) const {
290 return Execute(std::nullopt, host_type, query, args...);
291}
292
293template <typename... Args>
294StatementResultSet Cluster::Execute(
295 OptionalCommandControl command_control,
296 ClusterHostType host_type,
297 const Query& query,
298 const Args&... args
299) const {
300 auto params_binder = impl::BindHelper::BindParams(args...);
301
302 return DoExecute(command_control, host_type, query.GetStatement(), params_binder, std::nullopt);
303}
304
305template <typename T>
306StatementResultSet Cluster::ExecuteDecompose(ClusterHostType host_type, const Query& query, const T& row) const {
307 return ExecuteDecompose(std::nullopt, host_type, query, row);
308}
309
310template <typename T>
311StatementResultSet Cluster::ExecuteDecompose(
312 OptionalCommandControl command_control,
313 ClusterHostType host_type,
314 const Query& query,
315 const T& row
316) const {
317 auto params_binder = impl::BindHelper::BindRowAsParams(row);
318
319 return DoExecute(command_control, host_type, query, params_binder, std::nullopt);
320}
321
322template <typename Container>
323StatementResultSet Cluster::ExecuteBulk(ClusterHostType host_type, const Query& query, const Container& params) const {
324 return ExecuteBulk(std::nullopt, host_type, query, params);
325}
326
327template <typename Container>
328StatementResultSet Cluster::ExecuteBulk(
329 OptionalCommandControl command_control,
330 ClusterHostType host_type,
331 const Query& query,
332 const Container& params
333) const {
334 UINVARIANT(!params.empty(), "Empty params in bulk execution");
335
336 auto params_binder = impl::BindHelper::BindContainerAsParams(params);
337
338 return DoExecute(command_control, host_type, query.GetStatement(), params_binder, std::nullopt);
339}
340
341template <typename MapTo, typename Container>
342StatementResultSet Cluster::ExecuteBulkMapped(ClusterHostType host_type, const Query& query, const Container& params)
343 const {
344 return ExecuteBulkMapped<MapTo>(std::nullopt, host_type, query, params);
345}
346
347template <typename MapTo, typename Container>
348StatementResultSet Cluster::ExecuteBulkMapped(
349 OptionalCommandControl command_control,
350 ClusterHostType host_type,
351 const Query& query,
352 const Container& params
353) const {
354 UINVARIANT(!params.empty(), "Empty params in bulk execution");
355
356 auto params_binder = impl::BindHelper::BindContainerAsParamsMapped<MapTo>(params);
357
358 return DoExecute(command_control, host_type, query.GetStatement(), params_binder, std::nullopt);
359}
360
361template <typename T, typename... Args>
362CursorResultSet<T>
363Cluster::GetCursor(ClusterHostType host_type, std::size_t batch_size, const Query& query, const Args&... args) const {
364 return GetCursor<T>(std::nullopt, host_type, batch_size, query, args...);
365}
366
367template <typename T, typename... Args>
368CursorResultSet<T> Cluster::GetCursor(
369 OptionalCommandControl command_control,
370 ClusterHostType host_type,
371 std::size_t batch_size,
372 const Query& query,
373 const Args&... args
374) const {
375 auto params_binder = impl::BindHelper::BindParams(args...);
376
377 return CursorResultSet<T>{DoExecute(command_control, host_type, query, params_binder, batch_size)};
378}
379
380} // namespace storages::mysql
381
382USERVER_NAMESPACE_END