userver: userver/storages/postgres/options.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
options.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/storages/postgres/options.hpp
4/// @brief Options
5
6#include <chrono>
7#include <iosfwd>
8#include <optional>
9#include <string>
10#include <unordered_map>
11
12#include <userver/congestion_control/controllers/linear.hpp>
13#include <userver/storages/postgres/postgres_fwd.hpp>
14#include <userver/utils/impl/transparent_hash.hpp>
15
16USERVER_NAMESPACE_BEGIN
17
18namespace storages::postgres {
19
20/*! [Isolation levels] */
21/// @brief SQL transaction isolation level
22/// @see https://www.postgresql.org/docs/current/static/sql-set-transaction.html
23enum class IsolationLevel {
24 kReadCommitted, //!< READ COMMITTED
25 kRepeatableRead, //!< REPEATABLE READ
26 kSerializable, //!< SERIALIZABLE
27 kReadUncommitted //!< READ UNCOMMITTED @warning In Postgres READ UNCOMMITTED
28 //!< is treated as READ COMMITTED
29};
30/*! [Isolation levels] */
31
32std::ostream& operator<<(std::ostream&, IsolationLevel);
33
34/// @brief PostgreSQL transaction options
35///
36/// A transaction can be started using all isolation levels and modes
37/// supported by PostgreSQL server as specified in it's documentation.
38///
39/// Default isolation level is READ COMMITTED, default mode is READ WRITE.
40/// @code
41/// // Read-write read committed transaction.
42/// TransactionOptions opts;
43/// @endcode
44///
45/// Transaction class provides constants Transaction::RW, Transaction::RO and
46/// Transaction::Deferrable for convenience.
47///
48/// Other variants can be created with TransactionOptions constructors
49/// that are constexpr.
50///
51/// @see https://www.postgresql.org/docs/current/static/sql-set-transaction.html
53 /*! [Transaction modes] */
54 enum Mode {
55 kReadWrite = 0,
56 kReadOnly = 1,
57 kDeferrable = 3 //!< Deferrable transaction is read only
58 };
59 /*! [Transaction modes] */
61 Mode mode = kReadWrite;
62
63 constexpr TransactionOptions() = default;
64 constexpr explicit TransactionOptions(IsolationLevel lvl)
65 : isolation_level{lvl} {}
66 constexpr TransactionOptions(IsolationLevel lvl, Mode m)
67 : isolation_level{lvl}, mode{m} {}
68 constexpr explicit TransactionOptions(Mode m) : mode{m} {}
69
70 bool IsReadOnly() const { return mode & kReadOnly; }
71
72 /// The deferrable property has effect only if the transaction is also
73 /// serializable and read only
74 static constexpr TransactionOptions Deferrable() {
76 }
77};
78
79constexpr inline bool operator==(const TransactionOptions& lhs,
80 const TransactionOptions& rhs) {
81 return lhs.isolation_level == rhs.isolation_level && lhs.mode == rhs.mode;
82}
83const std::string& BeginStatement(const TransactionOptions&);
84
85/// A structure to control timeouts for PosrgreSQL queries
86///
87/// There are two parameters, `execute` and `statement`.
88///
89/// `execute` parameter controls the overall time the driver spends executing a
90/// query, that includes:
91/// * connecting to PostgreSQL server, if there are no connections available and
92/// connection pool still has space for new connections;
93/// * waiting for a connection to become idle if there are no idle connections
94/// and connection pool already has reached it's max size;
95/// * preparing a statement if the statement is run for the first time on the
96/// connection;
97/// * binding parameters and executing the statement;
98/// * waiting for the first results to arrive from the server. If the result set
99/// is big, only time to the first data packet is taken into account.
100///
101/// `statement` is rather straightforward, it's the PostgreSQL server-side
102/// parameter, and it controls the time the database backend can spend executing
103/// a single statement. It is very costly to change the statement timeout
104/// often, as it requires a roundtrip to the database to change the setting.
105/// @see https://www.postgresql.org/docs/12/runtime-config-client.html
106///
107/// `execute` timeout should always be greater than the `statement` timeout!
108///
109/// In case of a timeout, either back-end or overall, the client gets an
110/// exception and the driver tries to clean up the connection for further reuse.
112 /// Overall timeout for a command being executed
113 TimeoutDuration execute{};
114 /// PostgreSQL server-side timeout
115 TimeoutDuration statement{};
116
117 constexpr CommandControl(TimeoutDuration execute, TimeoutDuration statement)
118 : execute(execute), statement(statement) {}
119
120 constexpr CommandControl WithExecuteTimeout(TimeoutDuration n) const
121 noexcept {
122 return {n, statement};
123 }
124
125 constexpr CommandControl WithStatementTimeout(TimeoutDuration s) const
126 noexcept {
127 return {execute, s};
128 }
129
130 bool operator==(const CommandControl& rhs) const {
131 return execute == rhs.execute && statement == rhs.statement;
132 }
133
134 bool operator!=(const CommandControl& rhs) const { return !(*this == rhs); }
135};
136
137/// @brief storages::postgres::CommandControl that may not be set
138using OptionalCommandControl = std::optional<CommandControl>;
139
141 USERVER_NAMESPACE::utils::impl::TransparentMap<std::string, CommandControl>;
143 USERVER_NAMESPACE::utils::impl::TransparentMap<std::string,
147
148OptionalCommandControl GetHandlerOptionalCommandControl(
149 const CommandControlByHandlerMap& map, std::string_view path,
150 std::string_view method);
151
152OptionalCommandControl GetQueryOptionalCommandControl(
153 const CommandControlByQueryMap& map, const std::string& query_name);
154
156 std::chrono::milliseconds max_replication_lag{0};
157};
158
159/// Default initial pool connection count
160static constexpr size_t kDefaultPoolMinSize = 4;
161
162/// Default pool connections limit
163static constexpr size_t kDefaultPoolMaxSize = 15;
164
165/// Default size of queue for clients waiting for connections
166static constexpr size_t kDefaultPoolMaxQueueSize = 200;
167
168/// Default limit for concurrent establishing connections number
169static constexpr size_t kDefaultConnectingLimit = 0;
170
171/// @brief PostgreSQL connection pool options
172///
173/// Dynamic option @ref POSTGRES_CONNECTION_POOL_SETTINGS
175 /// Number of connections created initially
177
178 /// Maximum number of created connections
180
181 /// Maximum number of clients waiting for a connection
183
184 /// Limits number of concurrent establishing connections (0 - unlimited)
186
187 bool operator==(const PoolSettings& rhs) const {
188 return min_size == rhs.min_size && max_size == rhs.max_size &&
189 max_queue_size == rhs.max_queue_size &&
190 connecting_limit == rhs.connecting_limit;
191 }
192};
193
194/// Default size limit for prepared statements cache
195static constexpr size_t kDefaultMaxPreparedCacheSize = 5000;
196
197/// Pipeline mode configuration
198///
199/// Dynamic option @ref POSTGRES_CONNECTION_PIPELINE_EXPERIMENT
200enum class PipelineMode { kDisabled, kEnabled };
201
202/// PostgreSQL connection options
203///
204/// Dynamic option @ref POSTGRES_CONNECTION_SETTINGS
206 enum PreparedStatementOptions {
207 kCachePreparedStatements,
208 kNoPreparedStatements,
209 };
210 enum UserTypesOptions {
211 kUserTypesEnabled,
212 kPredefinedTypesOnly,
213 };
214 enum CheckQueryParamsOptions {
215 kIgnoreUnused,
216 kCheckUnused,
217 };
218 using SettingsVersion = size_t;
219
220 /// Cache prepared statements or not
221 PreparedStatementOptions prepared_statements = kCachePreparedStatements;
222
223 /// Enables the usage of user-defined types
224 UserTypesOptions user_types = kUserTypesEnabled;
225
226 /// Checks for not-NULL query params that are not used in query
227 CheckQueryParamsOptions ignore_unused_query_params = kCheckUnused;
228
229 /// Limits the size or prepared statements cache
231
232 /// Turns on connection pipeline mode
234
235 /// This many connection errors in 15 seconds block new connections opening
237
238 /// Helps keep track of the changes in settings
240
241 bool operator==(const ConnectionSettings& rhs) const {
242 return prepared_statements == rhs.prepared_statements &&
243 user_types == rhs.user_types &&
244 ignore_unused_query_params == rhs.ignore_unused_query_params &&
245 max_prepared_cache_size == rhs.max_prepared_cache_size &&
246 pipeline_mode == rhs.pipeline_mode &&
247 recent_errors_threshold == rhs.recent_errors_threshold;
248 }
249
250 bool operator!=(const ConnectionSettings& rhs) const {
251 return !(*this == rhs);
252 }
253
254 bool RequiresConnectionReset(const ConnectionSettings& rhs) const {
255 // TODO: max_prepared_cache_size check could be relaxed
256 return prepared_statements != rhs.prepared_statements ||
257 user_types != rhs.user_types ||
258 ignore_unused_query_params != rhs.ignore_unused_query_params ||
259 max_prepared_cache_size != rhs.max_prepared_cache_size ||
260 pipeline_mode != rhs.pipeline_mode;
261 }
262};
263
264/// @brief PostgreSQL statements metrics options
265///
266/// Dynamic option @ref POSTGRES_STATEMENT_METRICS_SETTINGS
267struct StatementMetricsSettings final {
268 /// Store metrics in LRU of this size
270
271 bool operator==(const StatementMetricsSettings& other) const {
272 return max_statements == other.max_statements;
273 }
274};
275
276/// Initialization modes
277enum class InitMode {
278 kSync = 0,
279 kAsync,
280};
281
282enum class ConnlimitMode {
283 kManual = 0,
284 kAuto,
285};
286
287/// Settings for storages::postgres::Cluster
289 /// settings for statements metrics
290 StatementMetricsSettings statement_metrics_settings;
291
292 /// settings for host discovery
294
295 /// settings for connection pools
297
298 /// settings for individual connections
300
301 /// initialization mode
303
304 /// database name
305 std::string db_name;
306
307 /// connection limit change mode
308 ConnlimitMode connlimit_mode = ConnlimitMode::kManual;
309
310 /// congestion control settings
311 congestion_control::v2::LinearController::StaticConfig cc_config;
312};
313
314} // namespace storages::postgres
315
316USERVER_NAMESPACE_END