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
155/// Default initial pool connection count
156inline constexpr std::size_t kDefaultPoolMinSize = 4;
157
158/// Default maximum replication lag
159inline constexpr auto kDefaultMaxReplicationLag = std::chrono::seconds{60};
160
161/// Default pool connections limit
162inline constexpr std::size_t kDefaultPoolMaxSize = 15;
163
164/// Default size of queue for clients waiting for connections
165inline constexpr std::size_t kDefaultPoolMaxQueueSize = 200;
166
167/// Default limit for concurrent establishing connections number
168inline constexpr std::size_t kDefaultConnectingLimit = 0;
169
171 std::chrono::milliseconds max_replication_lag{kDefaultMaxReplicationLag};
172};
173
174/// @brief PostgreSQL connection pool options
175///
176/// Dynamic option @ref POSTGRES_CONNECTION_POOL_SETTINGS
178 /// Number of connections created initially
180
181 /// Maximum number of created connections
183
184 /// Maximum number of clients waiting for a connection
186
187 /// Limits number of concurrent establishing connections (0 - unlimited)
189
190 bool operator==(const PoolSettings& rhs) const {
191 return min_size == rhs.min_size && max_size == rhs.max_size &&
194 }
195};
196
197/// Default size limit for prepared statements cache
198inline constexpr std::size_t kDefaultMaxPreparedCacheSize = 200;
199
200/// Pipeline mode configuration
201///
202/// Dynamic option @ref POSTGRES_CONNECTION_PIPELINE_EXPERIMENT
203enum class PipelineMode { kDisabled, kEnabled };
204
205/// Whether to omit excessive D(escribe) message
206/// when executing prepared statements
207///
208/// Dynamic option @ref POSTGRES_OMIT_DESCRIBE_IN_EXECUTE
209enum class OmitDescribeInExecuteMode { kDisabled, kEnabled };
210
211/// PostgreSQL connection options
212///
213/// Dynamic option @ref POSTGRES_CONNECTION_SETTINGS
215 enum PreparedStatementOptions {
216 kCachePreparedStatements,
217 kNoPreparedStatements,
218 };
219 enum UserTypesOptions {
220 kUserTypesEnabled,
221 kUserTypesEnforced,
222 kPredefinedTypesOnly,
223 };
224 enum CheckQueryParamsOptions {
225 kIgnoreUnused,
226 kCheckUnused,
227 };
228 enum DiscardOnConnectOptions {
229 kDiscardNone,
230 kDiscardAll,
231 };
232 using SettingsVersion = std::size_t;
233
234 /// Cache prepared statements or not
235 PreparedStatementOptions prepared_statements = kCachePreparedStatements;
236
237 /// Enables the usage of user-defined types
238 UserTypesOptions user_types = kUserTypesEnabled;
239
240 /// Checks for not-NULL query params that are not used in query
241 CheckQueryParamsOptions ignore_unused_query_params = kCheckUnused;
242
243 /// Limits the size or prepared statements cache
245
246 /// Turns on connection pipeline mode
248
249 /// Enables protocol-level optimization when executing prepared statements
251 OmitDescribeInExecuteMode::kDisabled;
252
253 /// This many connection errors in 15 seconds block new connections opening
254 std::size_t recent_errors_threshold = 2;
255
256 /// The maximum lifetime of the connection after which it will be closed
258
259 /// Execute discard all after establishing a new connection
260 DiscardOnConnectOptions discard_on_connect = kDiscardAll;
261
262 /// Helps keep track of the changes in settings
263 SettingsVersion version{0U};
264
265 bool operator==(const ConnectionSettings& rhs) const {
266 return !RequiresConnectionReset(rhs) &&
268 }
269
270 bool operator!=(const ConnectionSettings& rhs) const {
271 return !(*this == rhs);
272 }
273
274 bool RequiresConnectionReset(const ConnectionSettings& rhs) const {
275 // TODO: max_prepared_cache_size check could be relaxed
276 return prepared_statements != rhs.prepared_statements ||
277 user_types != rhs.user_types ||
278 ignore_unused_query_params != rhs.ignore_unused_query_params ||
279 max_prepared_cache_size != rhs.max_prepared_cache_size ||
280 pipeline_mode != rhs.pipeline_mode || max_ttl != rhs.max_ttl ||
281 discard_on_connect != rhs.discard_on_connect ||
282 omit_describe_mode != rhs.omit_describe_mode;
283 }
284};
285
286/// @brief PostgreSQL statements metrics options
287///
288/// Dynamic option @ref POSTGRES_STATEMENT_METRICS_SETTINGS
289struct StatementMetricsSettings final {
290 /// Store metrics in LRU of this size
291 std::size_t max_statements{0};
292
293 bool operator==(const StatementMetricsSettings& other) const {
294 return max_statements == other.max_statements;
295 }
296};
297
298/// Initialization modes
299enum class InitMode {
300 kSync = 0,
301 kAsync,
302};
303
304enum class ConnlimitMode {
305 kManual = 0,
306 kAuto,
307};
308
309/// Settings for storages::postgres::Cluster
311 /// settings for statements metrics
312 StatementMetricsSettings statement_metrics_settings;
313
314 /// settings for host discovery
316
317 /// settings for connection pools
319
320 /// settings for individual connections
322
323 /// initialization mode
325
326 /// database name
327 std::string db_name;
328
329 /// connection limit change mode
330 ConnlimitMode connlimit_mode = ConnlimitMode::kAuto;
331
332 /// congestion control settings
333 congestion_control::v2::LinearController::StaticConfig cc_config;
334};
335
336} // namespace storages::postgres
337
338USERVER_NAMESPACE_END