userver: userver/storages/postgres/options.hpp Source File
Loading...
Searching...
No Matches
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) : isolation_level{lvl} {}
65 constexpr TransactionOptions(IsolationLevel lvl, Mode m) : isolation_level{lvl}, mode{m} {}
66 constexpr explicit TransactionOptions(Mode m) : mode{m} {}
67
68 bool IsReadOnly() const { return mode & kReadOnly; }
69
70 /// The deferrable property has effect only if the transaction is also
71 /// serializable and read only
73};
74
75constexpr inline bool operator==(const TransactionOptions& lhs, const TransactionOptions& rhs) {
76 return lhs.isolation_level == rhs.isolation_level && lhs.mode == rhs.mode;
77}
78const std::string& BeginStatement(const TransactionOptions&);
79
80/// A structure to control timeouts for PosrgreSQL queries
81///
82/// There are two parameters, `execute` and `statement`.
83///
84/// `execute` parameter controls the overall time the driver spends executing a
85/// query, that includes:
86/// * connecting to PostgreSQL server, if there are no connections available and
87/// connection pool still has space for new connections;
88/// * waiting for a connection to become idle if there are no idle connections
89/// and connection pool already has reached it's max size;
90/// * preparing a statement if the statement is run for the first time on the
91/// connection;
92/// * binding parameters and executing the statement;
93/// * waiting for the first results to arrive from the server. If the result set
94/// is big, only time to the first data packet is taken into account.
95///
96/// `statement` is rather straightforward, it's the PostgreSQL server-side
97/// parameter, and it controls the time the database backend can spend executing
98/// a single statement. It is very costly to change the statement timeout
99/// often, as it requires a roundtrip to the database to change the setting.
100/// @see https://www.postgresql.org/docs/12/runtime-config-client.html
101///
102/// `execute` timeout should always be greater than the `statement` timeout!
103///
104/// In case of a timeout, either back-end or overall, the client gets an
105/// exception and the driver tries to clean up the connection for further reuse.
107 /// Overall timeout for a command being executed
108 TimeoutDuration execute{};
109 /// PostgreSQL server-side timeout
110 TimeoutDuration statement{};
111
112 constexpr CommandControl(TimeoutDuration execute, TimeoutDuration statement)
113 : execute(execute), statement(statement) {}
114
115 constexpr CommandControl WithExecuteTimeout(TimeoutDuration n) const noexcept { return {n, statement}; }
116
117 constexpr CommandControl WithStatementTimeout(TimeoutDuration s) const noexcept { return {execute, s}; }
118
119 bool operator==(const CommandControl& rhs) const { return execute == rhs.execute && statement == rhs.statement; }
120
121 bool operator!=(const CommandControl& rhs) const { return !(*this == rhs); }
122};
123
124/// @brief storages::postgres::CommandControl that may not be set
125using OptionalCommandControl = std::optional<CommandControl>;
126
131
132OptionalCommandControl
133GetHandlerOptionalCommandControl(const CommandControlByHandlerMap& map, std::string_view path, std::string_view method);
134
135OptionalCommandControl
136GetQueryOptionalCommandControl(const CommandControlByQueryMap& map, const std::string& query_name);
137
138/// Default initial pool connection count
139inline constexpr std::size_t kDefaultPoolMinSize = 4;
140
141/// Default maximum replication lag
142inline constexpr auto kDefaultMaxReplicationLag = std::chrono::seconds{60};
143
144/// Default pool connections limit
145inline constexpr std::size_t kDefaultPoolMaxSize = 15;
146
147/// Default size of queue for clients waiting for connections
148inline constexpr std::size_t kDefaultPoolMaxQueueSize = 200;
149
150/// Default limit for concurrent establishing connections number
151inline constexpr std::size_t kDefaultConnectingLimit = 0;
152
154 std::chrono::milliseconds max_replication_lag{kDefaultMaxReplicationLag};
155};
156
157/// @brief PostgreSQL connection pool options
158///
159/// Dynamic option @ref POSTGRES_CONNECTION_POOL_SETTINGS
161 /// Number of connections created initially
163
164 /// Maximum number of created connections
166
167 /// Maximum number of clients waiting for a connection
169
170 /// Limits number of concurrent establishing connections (0 - unlimited)
172
173 bool operator==(const PoolSettings& rhs) const {
174 return min_size == rhs.min_size && max_size == rhs.max_size && max_queue_size == rhs.max_queue_size &&
176 }
177};
178
179/// Default size limit for prepared statements cache
180inline constexpr std::size_t kDefaultMaxPreparedCacheSize = 200;
181
182/// Pipeline mode configuration
183///
184/// Dynamic option @ref POSTGRES_CONNECTION_PIPELINE_EXPERIMENT
185enum class PipelineMode { kDisabled, kEnabled };
186
187/// Whether to omit excessive D(escribe) message
188/// when executing prepared statements
189///
190/// Dynamic option @ref POSTGRES_OMIT_DESCRIBE_IN_EXECUTE
191enum class OmitDescribeInExecuteMode { kDisabled, kEnabled };
192
193/// PostgreSQL connection options
194///
195/// Dynamic option @ref POSTGRES_CONNECTION_SETTINGS
197 enum PreparedStatementOptions {
198 kCachePreparedStatements,
199 kNoPreparedStatements,
200 };
201 enum UserTypesOptions {
202 kUserTypesEnabled,
203 kUserTypesEnforced,
204 kPredefinedTypesOnly,
205 };
206 enum CheckQueryParamsOptions {
207 kIgnoreUnused,
208 kCheckUnused,
209 };
210 enum DiscardOnConnectOptions {
211 kDiscardNone,
212 kDiscardAll,
213 };
214 using SettingsVersion = std::size_t;
215
216 /// Cache prepared statements or not
217 PreparedStatementOptions prepared_statements = kCachePreparedStatements;
218
219 /// Enables the usage of user-defined types
220 UserTypesOptions user_types = kUserTypesEnabled;
221
222 /// Checks for not-NULL query params that are not used in query
223 CheckQueryParamsOptions ignore_unused_query_params = kCheckUnused;
224
225 /// Limits the size or prepared statements cache
227
228 /// Turns on connection pipeline mode
230
231 /// Enables protocol-level optimization when executing prepared statements
233
234 /// This many connection errors in 15 seconds block new connections opening
235 std::size_t recent_errors_threshold = 2;
236
237 /// The maximum lifetime of the connection after which it will be closed
239
240 /// Execute discard all after establishing a new connection
241 DiscardOnConnectOptions discard_on_connect = kDiscardAll;
242
243 /// Helps keep track of the changes in settings
244 SettingsVersion version{0U};
245
246 bool operator==(const ConnectionSettings& rhs) const {
247 return !RequiresConnectionReset(rhs) && recent_errors_threshold == rhs.recent_errors_threshold;
248 }
249
250 bool operator!=(const ConnectionSettings& rhs) const { return !(*this == rhs); }
251
252 bool RequiresConnectionReset(const ConnectionSettings& rhs) const {
253 // TODO: max_prepared_cache_size check could be relaxed
254 return prepared_statements != rhs.prepared_statements || user_types != rhs.user_types ||
255 ignore_unused_query_params != rhs.ignore_unused_query_params ||
256 max_prepared_cache_size != rhs.max_prepared_cache_size || pipeline_mode != rhs.pipeline_mode ||
257 max_ttl != rhs.max_ttl || discard_on_connect != rhs.discard_on_connect ||
258 omit_describe_mode != rhs.omit_describe_mode;
259 }
260};
261
262/// @brief PostgreSQL statements metrics options
263///
264/// Dynamic option @ref POSTGRES_STATEMENT_METRICS_SETTINGS
265struct StatementMetricsSettings final {
266 /// Store metrics in LRU of this size
267 std::size_t max_statements{0};
268
269 bool operator==(const StatementMetricsSettings& other) const { return max_statements == other.max_statements; }
270};
271
272/// Initialization modes
273enum class InitMode {
274 kSync = 0,
275 kAsync,
276};
277
278enum class ConnlimitMode {
279 kManual = 0,
280 kAuto,
281};
282
283/// Settings for storages::postgres::Cluster
285 /// settings for statements metrics
286 StatementMetricsSettings statement_metrics_settings;
287
288 /// settings for host discovery
290
291 /// settings for connection pools
293
294 /// settings for individual connections
296
297 /// initialization mode
299
300 /// database name
301 std::string db_name;
302
303 /// connection limit change mode
304 ConnlimitMode connlimit_mode = ConnlimitMode::kAuto;
305
306 /// congestion control settings
307 congestion_control::v2::LinearController::StaticConfig cc_config;
308};
309
310} // namespace storages::postgres
311
312USERVER_NAMESPACE_END