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#include <userver/utils/str_icase.hpp>
16
17USERVER_NAMESPACE_BEGIN
18
19namespace storages::postgres {
20
21/*! [Isolation levels] */
22/// @brief SQL transaction isolation level
23/// @see https://www.postgresql.org/docs/current/static/sql-set-transaction.html
24enum class IsolationLevel {
25 kReadCommitted, //!< READ COMMITTED
26 kRepeatableRead, //!< REPEATABLE READ
27 kSerializable, //!< SERIALIZABLE
28 kReadUncommitted //!< READ UNCOMMITTED @warning In Postgres READ UNCOMMITTED
29 //!< is treated as READ COMMITTED
30};
31/*! [Isolation levels] */
32
33std::ostream& operator<<(std::ostream&, IsolationLevel);
34
35/// @brief PostgreSQL transaction options
36///
37/// A transaction can be started using all isolation levels and modes
38/// supported by PostgreSQL server as specified in it's documentation.
39///
40/// Default isolation level is READ COMMITTED, default mode is READ WRITE.
41/// @code
42/// // Read-write read committed transaction.
43/// TransactionOptions opts;
44/// @endcode
45///
46/// Transaction class provides constants Transaction::RW, Transaction::RO and
47/// Transaction::Deferrable for convenience.
48///
49/// Other variants can be created with TransactionOptions constructors
50/// that are constexpr.
51///
52/// @see https://www.postgresql.org/docs/current/static/sql-set-transaction.html
54 /*! [Transaction modes] */
55 enum Mode {
56 kReadWrite = 0,
57 kReadOnly = 1,
58 kDeferrable = 3 //!< Deferrable transaction is read only
59 };
60 /*! [Transaction modes] */
62 Mode mode = kReadWrite;
63
64 constexpr TransactionOptions() = default;
65 constexpr explicit TransactionOptions(IsolationLevel lvl) : isolation_level{lvl} {}
66 constexpr TransactionOptions(IsolationLevel lvl, Mode m) : isolation_level{lvl}, mode{m} {}
67 constexpr explicit TransactionOptions(Mode m) : mode{m} {}
68
69 bool IsReadOnly() const { return mode & kReadOnly; }
70
71 /// The deferrable property has effect only if the transaction is also
72 /// serializable and read only
74};
75
76constexpr inline bool operator==(const TransactionOptions& lhs, const TransactionOptions& rhs) {
77 return lhs.isolation_level == rhs.isolation_level && lhs.mode == rhs.mode;
78}
79const std::string& BeginStatement(const TransactionOptions&);
80
81/// A structure to control timeouts for PosrgreSQL queries
82///
83/// There are two parameters, `execute` and `statement`.
84///
85/// `execute` parameter controls the overall time the driver spends executing a
86/// query, that includes:
87/// * connecting to PostgreSQL server, if there are no connections available and
88/// connection pool still has space for new connections;
89/// * waiting for a connection to become idle if there are no idle connections
90/// and connection pool already has reached it's max size;
91/// * preparing a statement if the statement is run for the first time on the
92/// connection;
93/// * binding parameters and executing the statement;
94/// * waiting for the first results to arrive from the server. If the result set
95/// is big, only time to the first data packet is taken into account.
96///
97/// `statement` is rather straightforward, it's the PostgreSQL server-side
98/// parameter, and it controls the time the database backend can spend executing
99/// a single statement. It is very costly to change the statement timeout
100/// often, as it requires a roundtrip to the database to change the setting.
101/// @see https://www.postgresql.org/docs/12/runtime-config-client.html
102///
103/// `execute` timeout should always be greater than the `statement` timeout!
104///
105/// In case of a timeout, either back-end or overall, the client gets an
106/// exception and the driver tries to clean up the connection for further reuse.
108 /// Overall timeout for a command being executed
109 TimeoutDuration execute{};
110 /// PostgreSQL server-side timeout
111 TimeoutDuration statement{};
112
113 constexpr CommandControl(TimeoutDuration execute, TimeoutDuration statement)
114 : execute(execute), statement(statement) {}
115
116 constexpr CommandControl WithExecuteTimeout(TimeoutDuration n) const noexcept { return {n, statement}; }
117
118 constexpr CommandControl WithStatementTimeout(TimeoutDuration s) const noexcept { return {execute, s}; }
119
120 bool operator==(const CommandControl& rhs) const { return execute == rhs.execute && statement == rhs.statement; }
121
122 bool operator!=(const CommandControl& rhs) const { return !(*this == rhs); }
123};
124
125/// @brief storages::postgres::CommandControl that may not be set
126using OptionalCommandControl = std::optional<CommandControl>;
127
132
133OptionalCommandControl
134GetHandlerOptionalCommandControl(const CommandControlByHandlerMap& map, std::string_view path, std::string_view method);
135
136OptionalCommandControl
137GetQueryOptionalCommandControl(const CommandControlByQueryMap& map, const std::string& query_name);
138
139/// Default initial pool connection count
140inline constexpr std::size_t kDefaultPoolMinSize = 4;
141
142/// Default maximum replication lag
143inline constexpr auto kDefaultMaxReplicationLag = std::chrono::seconds{60};
144
145/// Default pool connections limit
146inline constexpr std::size_t kDefaultPoolMaxSize = 15;
147
148/// Default size of queue for clients waiting for connections
149inline constexpr std::size_t kDefaultPoolMaxQueueSize = 200;
150
151/// Default limit for concurrent establishing connections number
152inline constexpr std::size_t kDefaultConnectingLimit = 0;
153
154/// @brief PostgreSQL topology options
155///
156/// Dynamic option @ref POSTGRES_TOPOLOGY_SETTINGS
158 /// Maximum replication lag. Once the replica lag exceeds this value it will be automatically disabled.
160
161 /// List of manually disabled replicas (FQDNs).
162 std::unordered_set<std::string, USERVER_NAMESPACE::utils::StrIcaseHash, USERVER_NAMESPACE::utils::StrIcaseEqual>
164};
165
166/// @brief PostgreSQL connection pool options
167///
168/// Dynamic option @ref POSTGRES_CONNECTION_POOL_SETTINGS
170 /// Number of connections created initially
172
173 /// Maximum number of created connections
175
176 /// Maximum number of clients waiting for a connection
178
179 /// Limits number of concurrent establishing connections (0 - unlimited)
181
182 bool operator==(const PoolSettings& rhs) const {
183 return min_size == rhs.min_size && max_size == rhs.max_size && max_queue_size == rhs.max_queue_size &&
185 }
186};
187
188/// Default size limit for prepared statements cache
189inline constexpr std::size_t kDefaultMaxPreparedCacheSize = 200;
190
191/// Pipeline mode configuration
192///
193/// Dynamic option @ref POSTGRES_CONNECTION_PIPELINE_EXPERIMENT
194enum class PipelineMode { kDisabled, kEnabled };
195
196/// Whether to omit excessive D(escribe) message
197/// when executing prepared statements
198///
199/// Dynamic option @ref POSTGRES_OMIT_DESCRIBE_IN_EXECUTE
200enum class OmitDescribeInExecuteMode { 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 kUserTypesEnforced,
213 kPredefinedTypesOnly,
214 };
215 enum CheckQueryParamsOptions {
216 kIgnoreUnused,
217 kCheckUnused,
218 };
219 enum DiscardOnConnectOptions {
220 kDiscardNone,
221 kDiscardAll,
222 };
223 using SettingsVersion = std::size_t;
224
225 /// Cache prepared statements or not
226 PreparedStatementOptions prepared_statements = kCachePreparedStatements;
227
228 /// Enables the usage of user-defined types
229 UserTypesOptions user_types = kUserTypesEnabled;
230
231 /// Checks for not-NULL query params that are not used in query
232 CheckQueryParamsOptions ignore_unused_query_params = kCheckUnused;
233
234 /// Limits the size or prepared statements cache
236
237 /// Turns on connection pipeline mode
239
240 /// Enables protocol-level optimization when executing prepared statements
242
243 /// This many connection errors in 15 seconds block new connections opening
244 std::size_t recent_errors_threshold = 2;
245
246 /// The maximum lifetime of the connection after which it will be closed
248
249 /// Execute discard all after establishing a new connection
250 DiscardOnConnectOptions discard_on_connect = kDiscardAll;
251
252 /// Helps keep track of the changes in settings
253 SettingsVersion version{0U};
254
255 bool operator==(const ConnectionSettings& rhs) const {
256 return !RequiresConnectionReset(rhs) && recent_errors_threshold == rhs.recent_errors_threshold;
257 }
258
259 bool operator!=(const ConnectionSettings& rhs) const { return !(*this == rhs); }
260
261 bool RequiresConnectionReset(const ConnectionSettings& rhs) const {
262 // TODO: max_prepared_cache_size check could be relaxed
263 return prepared_statements != rhs.prepared_statements || user_types != rhs.user_types ||
264 ignore_unused_query_params != rhs.ignore_unused_query_params ||
265 max_prepared_cache_size != rhs.max_prepared_cache_size || pipeline_mode != rhs.pipeline_mode ||
266 max_ttl != rhs.max_ttl || discard_on_connect != rhs.discard_on_connect ||
267 omit_describe_mode != rhs.omit_describe_mode;
268 }
269};
270
271/// @brief PostgreSQL statements metrics options
272///
273/// Dynamic option @ref POSTGRES_STATEMENT_METRICS_SETTINGS
274struct StatementMetricsSettings final {
275 /// Store metrics in LRU of this size
276 std::size_t max_statements{0};
277
278 bool operator==(const StatementMetricsSettings& other) const { return max_statements == other.max_statements; }
279};
280
281/// Initialization modes
282enum class InitMode {
283 kSync = 0,
284 kAsync,
285};
286
287enum class ConnlimitMode {
288 kManual = 0,
289 kAuto,
290};
291
292/// Settings for storages::postgres::Cluster
294 /// settings for statements metrics
295 StatementMetricsSettings statement_metrics_settings;
296
297 /// settings for host discovery
299
300 /// settings for connection pools
302
303 /// settings for individual connections
305
306 /// initialization mode
308
309 /// database name
310 std::string db_name;
311
312 /// connection limit change mode
313 ConnlimitMode connlimit_mode = ConnlimitMode::kAuto;
314
315 /// congestion control settings
316 congestion_control::v2::LinearController::StaticConfig cc_config;
317};
318
319} // namespace storages::postgres
320
321USERVER_NAMESPACE_END