userver
C++ Async Framework
Toggle main menu visibility
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
<
cstdint
>
8
#
include
<
iosfwd
>
9
#
include
<
optional
>
10
#
include
<
string
>
11
#
include
<
unordered_map
>
12
#
include
<
unordered_set
>
13
14
#
include
<
userver
/
congestion_control
/
controllers
/
linear
.
hpp
>
15
#
include
<
userver
/
storages
/
postgres
/
postgres_fwd
.
hpp
>
16
#
include
<
userver
/
utils
/
impl
/
transparent_hash
.
hpp
>
17
#
include
<
userver
/
utils
/
str_icase
.
hpp
>
18
#
include
<
userver
/
utils
/
string_literal
.
hpp
>
19
20
USERVER_NAMESPACE_BEGIN
21
22
namespace
storages::
postgres
{
23
24
/*! [Isolation levels] */
25
/// @brief SQL transaction isolation level
26
/// @see https://www.postgresql.org/docs/current/static/sql-set-transaction.html
27
enum
class
IsolationLevel
:
std
::
uint16_t
{
28
kReadCommitted
,
//!< READ COMMITTED
29
kRepeatableRead
,
//!< REPEATABLE READ
30
kSerializable
,
//!< SERIALIZABLE
31
kReadUncommitted
//!< READ UNCOMMITTED @warning In Postgres READ UNCOMMITTED
32
//!< is treated as READ COMMITTED
33
};
34
/*! [Isolation levels] */
35
36
std::string_view
ToStringView
(
IsolationLevel
lvl);
37
38
/// @brief PostgreSQL transaction options
39
///
40
/// A transaction can be started using all isolation levels and modes
41
/// supported by PostgreSQL server as specified in its documentation.
42
///
43
/// Default isolation level is READ COMMITTED, default mode is READ WRITE.
44
/// @code
45
/// // Read-write read committed transaction.
46
/// TransactionOptions opts;
47
/// @endcode
48
///
49
/// Transaction class provides constants Transaction::RW, Transaction::RO and
50
/// Transaction::Deferrable for convenience.
51
///
52
/// Other variants can be created with TransactionOptions constructors
53
/// that are constexpr.
54
///
55
/// @see https://www.postgresql.org/docs/current/static/sql-set-transaction.html
56
struct
TransactionOptions
{
57
/*! [Transaction modes] */
58
enum
Mode
:
std
::
uint16_t
{
59
kReadWrite = 0,
60
kReadOnly = 1,
61
kDeferrable
= 3
//!< Deferrable transaction is read only
62
};
63
/*! [Transaction modes] */
64
IsolationLevel
isolation_level
=
IsolationLevel
::
kReadCommitted
;
65
Mode
mode = kReadWrite;
66
67
constexpr
TransactionOptions() =
default
;
68
constexpr
explicit
TransactionOptions(
IsolationLevel
lvl)
69
:
isolation_level
{lvl}
70
{}
71
constexpr
TransactionOptions(
IsolationLevel
lvl,
Mode
m)
72
:
isolation_level
{lvl},
73
mode{m}
74
{}
75
constexpr
explicit
TransactionOptions(
Mode
m)
76
: mode{m}
77
{}
78
79
bool
IsReadOnly()
const
{
return
mode & kReadOnly; }
80
81
/// The deferrable property has effect only if the transaction is also
82
/// serializable and read only
83
static
constexpr
TransactionOptions
Deferrable
() {
return
{
IsolationLevel
::
kSerializable
,
kDeferrable
}; }
84
};
85
86
constexpr
inline
bool
operator==(
TransactionOptions
lhs,
TransactionOptions
rhs) {
87
return
lhs
.
isolation_level
== rhs
.
isolation_level
&& lhs.mode == rhs.mode;
88
}
89
USERVER_NAMESPACE::
utils
::StringLiteral BeginStatement(
TransactionOptions
opts)
noexcept
;
90
91
/// A structure to control timeouts for PosrgreSQL queries
92
///
93
/// There are two parameters, `execute` and `statement`.
94
///
95
/// `execute` parameter controls the overall time the driver spends executing a
96
/// query, that includes:
97
/// * connecting to PostgreSQL server, if there are no connections available and
98
/// connection pool still has space for new connections;
99
/// * waiting for a connection to become idle if there are no idle connections
100
/// and connection pool already has reached its max size;
101
/// * preparing a statement if the statement is run for the first time on the
102
/// connection;
103
/// * binding parameters and executing the statement;
104
/// * waiting for the first results to arrive from the server. If the result set
105
/// is big, only time to the first data packet is taken into account.
106
///
107
/// `statement` is rather straightforward, it's the PostgreSQL server-side
108
/// parameter, and it controls the time the database backend can spend executing
109
/// a single statement. It is very costly to change the statement timeout
110
/// often, as it requires a roundtrip to the database to change the setting.
111
/// @see https://www.postgresql.org/docs/12/runtime-config-client.html
112
///
113
/// `execute` timeout should always be greater than the `statement` timeout!
114
/// If the `statement` timeout happens to be greater than (or too close to) the
115
/// `execute` timeout, the driver caps the effective `statement` timeout to be
116
/// below the `execute` timeout (by a small margin when the `execute` timeout is
117
/// large enough to spare it), so that the database gets a chance to cancel the
118
/// statement on its own before the driver gives up waiting on the network.
119
///
120
/// In case of a timeout, either back-end or overall, the client gets an
121
/// exception and the driver tries to clean up the connection for further reuse.
122
struct
CommandControl
{
123
/// Overall timeout for a command being executed
124
TimeoutDuration
network_timeout_ms
{};
125
/// PostgreSQL server-side timeout
126
TimeoutDuration
statement_timeout_ms
{};
127
128
enum
class
PreparedStatementsOptionOverride { kNoOverride, kEnabled, kDisabled };
129
130
PreparedStatementsOptionOverride prepared_statements_enabled{PreparedStatementsOptionOverride::kNoOverride};
131
132
constexpr
CommandControl(
133
TimeoutDuration network_timeout_ms,
134
TimeoutDuration statement_timeout_ms,
135
PreparedStatementsOptionOverride prepared_statements_enabled = PreparedStatementsOptionOverride::kNoOverride
136
)
137
:
network_timeout_ms
(network_timeout_ms),
138
statement_timeout_ms
(statement_timeout_ms),
139
prepared_statements_enabled(prepared_statements_enabled)
140
{}
141
142
constexpr
CommandControl
WithExecuteTimeout(TimeoutDuration n)
const
noexcept
{
return
{n,
statement_timeout_ms
}; }
143
144
constexpr
CommandControl
WithStatementTimeout(TimeoutDuration s)
const
noexcept
{
return
{
network_timeout_ms
, s}; }
145
146
bool
operator==(
const
CommandControl
& rhs)
const
{
147
return
network_timeout_ms
== rhs
.
network_timeout_ms
&&
statement_timeout_ms
== rhs
.
statement_timeout_ms
&&
148
prepared_statements_enabled == rhs.prepared_statements_enabled;
149
}
150
};
151
152
/// @brief storages::postgres::CommandControl that may not be set
153
using
OptionalCommandControl
= std::optional<
CommandControl
>;
154
155
using
CommandControlByMethodMap = USERVER_NAMESPACE::
utils
::impl::TransparentMap<std::string,
CommandControl
>;
156
using
CommandControlByHandlerMap =
157
USERVER_NAMESPACE::
utils
::impl::TransparentMap<std::string, CommandControlByMethodMap>;
158
using
CommandControlByQueryMap = USERVER_NAMESPACE::
utils
::impl::TransparentMap<std::string,
CommandControl
>;
159
160
OptionalCommandControl
GetHandlerOptionalCommandControl(
161
const
CommandControlByHandlerMap& map,
162
std::string_view path,
163
std::string_view method
164
);
165
166
OptionalCommandControl
GetQueryOptionalCommandControl(
const
CommandControlByQueryMap& map, std::string_view query_name);
167
168
/// Default initial pool connection count
169
inline
constexpr
std::size_t
kDefaultPoolMinSize
= 4;
170
171
/// Default maximum replication lag
172
inline
constexpr
auto
kDefaultMaxReplicationLag
= std::chrono::seconds{60};
173
174
/// Default pool connections limit
175
inline
constexpr
std::size_t
kDefaultPoolMaxSize
= 15;
176
177
/// Default size of queue for clients waiting for connections
178
inline
constexpr
std::size_t
kDefaultPoolMaxQueueSize
= 200;
179
180
/// Default limit for concurrent establishing connections number
181
inline
constexpr
std::size_t
kDefaultConnectingLimit
= 0;
182
183
/// Default minimum time between starting new connections per host in milliseconds
184
inline
constexpr
std::size_t
kDefaultConnectingIntervalMs
= 4000;
185
186
/// @brief PostgreSQL topology options
187
///
188
/// Dynamic option @ref POSTGRES_TOPOLOGY_SETTINGS
189
struct
TopologySettings
{
190
/// Maximum replication lag. Once the replica lag exceeds this value it will be automatically disabled.
191
std::chrono::milliseconds
max_replication_lag
{
kDefaultMaxReplicationLag
};
192
193
/// List of manually disabled replicas (FQDNs).
194
std::unordered_set<std::string, USERVER_NAMESPACE::
utils
::
StrIcaseHash
, USERVER_NAMESPACE::
utils
::
StrIcaseEqual
>
195
disabled_replicas
{};
196
};
197
198
/// @brief PostgreSQL connection pool options
199
///
200
/// Dynamic option @ref POSTGRES_CONNECTION_POOL_SETTINGS
201
struct
PoolSettings
final
{
202
/// Number of connections created initially
203
std::size_t
min_size
{
kDefaultPoolMinSize
};
204
205
/// Maximum number of created connections
206
std::size_t
max_size
{
kDefaultPoolMaxSize
};
207
208
/// Maximum number of clients waiting for a connection
209
std::size_t
max_queue_size
{
kDefaultPoolMaxQueueSize
};
210
211
/// Limits number of concurrent establishing connections (0 - unlimited)
212
std::size_t
connecting_limit
{
kDefaultConnectingLimit
};
213
214
/// Minimum time in milliseconds between starting new connections to each host (0 - unlimited)
215
std::size_t
connecting_interval_ms
{
kDefaultConnectingIntervalMs
};
216
217
bool
operator==(
const
PoolSettings& rhs)
const
{
218
return
min_size
== rhs
.
min_size
&&
max_size
== rhs
.
max_size
&&
max_queue_size
== rhs
.
max_queue_size
&&
219
connecting_limit
== rhs
.
connecting_limit
&&
connecting_interval_ms
== rhs
.
connecting_interval_ms
;
220
}
221
};
222
223
// Configs with a suffix `Dynamic` are need to compatibility with static:
224
// We must update only fields that were updated in a dynamic config (not a full config!).
225
struct
PoolSettingsDynamic
final
{
226
std::optional<std::size_t> min_size;
227
std::optional<std::size_t> max_size;
228
std::optional<std::size_t> max_queue_size;
229
std::optional<std::size_t> connecting_limit;
230
std::optional<std::size_t> connecting_interval_ms;
231
};
232
233
/// Minimal size for prepared statements cache. Matches the @ref POSTGRES_CONNECTION_SETTINGS minimum
234
inline
constexpr
std::size_t
kMinPreparedStatementsCacheSize
= 3;
235
236
/// Default size limit for prepared statements cache
237
inline
constexpr
std::size_t
kDefaultMaxPreparedCacheSize
= 200;
238
239
/// Connection pooler mode (e.g. Odyssey / PgBouncer)
240
enum
class
PoolerMode
{
241
kSession
,
///< One client connection maps to one server connection
242
kTransaction
,
///< Server connection is assigned for the duration of a transaction
243
};
244
245
/// PostgreSQL connection options
246
///
247
/// Dynamic option @ref POSTGRES_CONNECTION_SETTINGS
248
struct
ConnectionSettings
{
249
enum
PreparedStatementOptions {
250
kCachePreparedStatements,
251
kNoPreparedStatements,
252
};
253
enum
UserTypesOptions {
254
kUserTypesEnabled,
255
kUserTypesEnforced,
256
kPredefinedTypesOnly,
257
};
258
enum
CheckQueryParamsOptions {
259
kIgnoreUnused,
260
kCheckUnused,
261
};
262
enum
DiscardOnConnectOptions {
263
kDiscardNone,
264
kDiscardAll,
265
};
266
enum
StatementLogMode {
267
kLogSkip,
268
kLog,
269
};
270
using
SettingsVersion = std::size_t;
271
272
/// Cache prepared statements or not
273
PreparedStatementOptions
prepared_statements
= kCachePreparedStatements;
274
275
/// Enables the usage of user-defined types
276
UserTypesOptions
user_types
= kUserTypesEnabled;
277
278
/// Checks for not-NULL query params that are not used in query
279
CheckQueryParamsOptions
ignore_unused_query_params
= kCheckUnused;
280
281
/// Limits the size or prepared statements cache
282
std::size_t
max_prepared_cache_size
=
kDefaultMaxPreparedCacheSize
;
283
284
/// This many connection errors in 15 seconds block new connections opening
285
std::size_t
recent_errors_threshold
= 30;
286
287
/// The maximum lifetime of the connection after which it will be closed
288
std::optional<std::chrono::seconds>
max_ttl
{};
289
290
/// Execute DISCARD ALL after establishing a new connection
291
/// Has effect only in session pooler mode (@ref storages::postgres::PoolerMode::kSession)
292
DiscardOnConnectOptions
discard_on_connect
= kDiscardAll;
293
294
/// Statement logging in span tags
295
StatementLogMode
statement_log_mode
= kLog;
296
297
bool
deadline_propagation_enabled =
true
;
298
299
/// Helps keep track of the changes in settings
300
SettingsVersion
version
{0U};
301
302
std::optional<std::string> application_name{};
303
304
PoolerMode
pooler_mode{
PoolerMode
::
kSession
};
305
306
bool
operator==(
const
ConnectionSettings
& rhs)
const
{
307
return
!RequiresConnectionReset(rhs) &&
recent_errors_threshold
== rhs
.
recent_errors_threshold
;
308
}
309
310
bool
RequiresConnectionReset(
const
ConnectionSettings
& rhs)
const
{
311
// TODO: max_prepared_cache_size check could be relaxed
312
return
prepared_statements
!= rhs
.
prepared_statements
||
user_types
!= rhs
.
user_types
||
313
ignore_unused_query_params
!= rhs
.
ignore_unused_query_params
||
314
max_prepared_cache_size
!= rhs
.
max_prepared_cache_size
||
max_ttl
!= rhs
.
max_ttl
||
315
discard_on_connect
!= rhs
.
discard_on_connect
|| application_name != rhs.application_name ||
316
pooler_mode != rhs.pooler_mode;
317
}
318
};
319
320
struct
ConnectionSettingsDynamic
final
{
321
std::optional<
ConnectionSettings
::PreparedStatementOptions> prepared_statements{};
322
std::optional<
ConnectionSettings
::UserTypesOptions> user_types{};
323
std::optional<std::size_t> max_prepared_cache_size{};
324
std::optional<std::size_t> recent_errors_threshold{};
325
std::optional<
ConnectionSettings
::CheckQueryParamsOptions> ignore_unused_query_params{};
326
std::optional<std::chrono::seconds> max_ttl{};
327
std::optional<
ConnectionSettings
::DiscardOnConnectOptions> discard_on_connect{};
328
std::optional<
bool
> deadline_propagation_enabled{};
329
std::optional<
PoolerMode
> pooler_mode{};
330
};
331
332
/// @brief PostgreSQL statements metrics options
333
///
334
/// Dynamic option @ref POSTGRES_STATEMENT_METRICS_SETTINGS
335
struct
StatementMetricsSettings
final
{
336
/// Store metrics in LRU of this size
337
std::size_t
max_statements
{0};
338
339
bool
operator==(
const
StatementMetricsSettings& other)
const
{
return
max_statements
== other
.
max_statements
; }
340
};
341
342
/// Initialization modes
343
enum
class
InitMode
{
344
kSync = 0,
345
kAsync,
346
};
347
348
enum
class
ConnlimitMode {
349
kManual = 0,
350
kAuto,
351
};
352
353
/// Settings for storages::postgres::Cluster
354
struct
ClusterSettings
{
355
/// settings for statements metrics
356
StatementMetricsSettings
statement_metrics_settings
;
357
358
/// settings for host discovery
359
TopologySettings
topology_settings
;
360
361
/// settings for connection pools
362
PoolSettings
pool_settings
;
363
364
/// settings for individual connections
365
ConnectionSettings
conn_settings
;
366
367
/// initialization mode
368
InitMode
init_mode
=
InitMode
::kSync;
369
370
/// database name
371
std::string
db_name
;
372
373
/// connection limit change mode
374
ConnlimitMode
connlimit_mode
= ConnlimitMode::kAuto;
375
376
/// congestion control settings
377
congestion_control::v2::LinearController::StaticConfig
cc_config
;
378
};
379
380
}
// namespace storages::postgres
381
382
USERVER_NAMESPACE_END
userver
storages
postgres
options.hpp
Generated on
for userver by
Doxygen
1.17.0