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