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