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 it's 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 it's 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
///
115
/// In case of a timeout, either back-end or overall, the client gets an
116
/// exception and the driver tries to clean up the connection for further reuse.
117
struct
CommandControl
{
118
/// Overall timeout for a command being executed
119
TimeoutDuration
network_timeout_ms
{};
120
/// PostgreSQL server-side timeout
121
TimeoutDuration
statement_timeout_ms
{};
122
123
enum
class
PreparedStatementsOptionOverride { kNoOverride, kEnabled, kDisabled };
124
125
PreparedStatementsOptionOverride prepared_statements_enabled{PreparedStatementsOptionOverride::kNoOverride};
126
127
constexpr
CommandControl(
128
TimeoutDuration network_timeout_ms,
129
TimeoutDuration statement_timeout_ms,
130
PreparedStatementsOptionOverride prepared_statements_enabled = PreparedStatementsOptionOverride::kNoOverride
131
)
132
:
network_timeout_ms
(network_timeout_ms),
133
statement_timeout_ms
(statement_timeout_ms),
134
prepared_statements_enabled(prepared_statements_enabled)
135
{}
136
137
constexpr
CommandControl
WithExecuteTimeout(TimeoutDuration n)
const
noexcept
{
return
{n,
statement_timeout_ms
}; }
138
139
constexpr
CommandControl
WithStatementTimeout(TimeoutDuration s)
const
noexcept
{
return
{
network_timeout_ms
, s}; }
140
141
bool
operator==(
const
CommandControl
& rhs)
const
{
142
return
network_timeout_ms
== rhs
.
network_timeout_ms
&&
statement_timeout_ms
== rhs
.
statement_timeout_ms
&&
143
prepared_statements_enabled == rhs.prepared_statements_enabled;
144
}
145
};
146
147
/// @brief storages::postgres::CommandControl that may not be set
148
using
OptionalCommandControl
= std::optional<
CommandControl
>;
149
150
using
CommandControlByMethodMap = USERVER_NAMESPACE::
utils
::impl::TransparentMap<std::string,
CommandControl
>;
151
using
CommandControlByHandlerMap =
152
USERVER_NAMESPACE::
utils
::impl::TransparentMap<std::string, CommandControlByMethodMap>;
153
using
CommandControlByQueryMap = USERVER_NAMESPACE::
utils
::impl::TransparentMap<std::string,
CommandControl
>;
154
155
OptionalCommandControl
GetHandlerOptionalCommandControl(
156
const
CommandControlByHandlerMap& map,
157
std::string_view path,
158
std::string_view method
159
);
160
161
OptionalCommandControl
GetQueryOptionalCommandControl(
const
CommandControlByQueryMap& map, std::string_view query_name);
162
163
/// Default initial pool connection count
164
inline
constexpr
std::size_t
kDefaultPoolMinSize
= 4;
165
166
/// Default maximum replication lag
167
inline
constexpr
auto
kDefaultMaxReplicationLag
= std::chrono::seconds{60};
168
169
/// Default pool connections limit
170
inline
constexpr
std::size_t
kDefaultPoolMaxSize
= 15;
171
172
/// Default size of queue for clients waiting for connections
173
inline
constexpr
std::size_t
kDefaultPoolMaxQueueSize
= 200;
174
175
/// Default limit for concurrent establishing connections number
176
inline
constexpr
std::size_t
kDefaultConnectingLimit
= 0;
177
178
/// Default minimum time between starting new connections per host in milliseconds
179
inline
constexpr
std::size_t
kDefaultConnectingIntervalMs
= 0;
180
181
/// Default connecting interval when pg-connecting-rate-limit experiment is enabled
182
inline
constexpr
std::size_t
kExperimentDefaultConnectingIntervalMs
= 4000;
183
184
/// @brief PostgreSQL topology options
185
///
186
/// Dynamic option @ref POSTGRES_TOPOLOGY_SETTINGS
187
struct
TopologySettings
{
188
/// Maximum replication lag. Once the replica lag exceeds this value it will be automatically disabled.
189
std::chrono::milliseconds
max_replication_lag
{
kDefaultMaxReplicationLag
};
190
191
/// List of manually disabled replicas (FQDNs).
192
std::unordered_set<std::string, USERVER_NAMESPACE::
utils
::
StrIcaseHash
, USERVER_NAMESPACE::
utils
::
StrIcaseEqual
>
193
disabled_replicas
{};
194
};
195
196
/// @brief PostgreSQL connection pool options
197
///
198
/// Dynamic option @ref POSTGRES_CONNECTION_POOL_SETTINGS
199
struct
PoolSettings
final
{
200
/// Number of connections created initially
201
std::size_t
min_size
{
kDefaultPoolMinSize
};
202
203
/// Maximum number of created connections
204
std::size_t
max_size
{
kDefaultPoolMaxSize
};
205
206
/// Maximum number of clients waiting for a connection
207
std::size_t
max_queue_size
{
kDefaultPoolMaxQueueSize
};
208
209
/// Limits number of concurrent establishing connections (0 - unlimited)
210
std::size_t
connecting_limit
{
kDefaultConnectingLimit
};
211
212
/// Minimum time in milliseconds between starting new connections to each host (0 - unlimited)
213
std::size_t
connecting_interval_ms
{
kDefaultConnectingIntervalMs
};
214
215
bool
operator==(
const
PoolSettings& rhs)
const
{
216
return
min_size
== rhs
.
min_size
&&
max_size
== rhs
.
max_size
&&
max_queue_size
== rhs
.
max_queue_size
&&
217
connecting_limit
== rhs
.
connecting_limit
&&
connecting_interval_ms
== rhs
.
connecting_interval_ms
;
218
}
219
};
220
221
// Configs with a suffix `Dynamic` are need to compatibility with static:
222
// We must update only fields that were updated in a dynamic config (not a full config!).
223
struct
PoolSettingsDynamic
final
{
224
std::optional<std::size_t> min_size;
225
std::optional<std::size_t> max_size;
226
std::optional<std::size_t> max_queue_size;
227
std::optional<std::size_t> connecting_limit;
228
std::optional<std::size_t> connecting_interval_ms;
229
};
230
231
/// Minimal size for prepared statements cache. Matches the @ref POSTGRES_CONNECTION_SETTINGS minimum
232
inline
constexpr
std::size_t
kMinPreparedStatementsCacheSize
= 3;
233
234
/// Default size limit for prepared statements cache
235
inline
constexpr
std::size_t
kDefaultMaxPreparedCacheSize
= 200;
236
237
/// Pipeline mode configuration
238
///
239
/// Dynamic option @ref POSTGRES_CONNECTION_PIPELINE_EXPERIMENT
240
enum
class
PipelineMode
{ kDisabled, kEnabled };
241
242
/// Whether to omit excessive D(escribe) message
243
/// when executing prepared statements
244
///
245
/// Dynamic option @ref POSTGRES_OMIT_DESCRIBE_IN_EXECUTE
246
enum
class
OmitDescribeInExecuteMode
{ kDisabled, kEnabled };
247
248
/// Connection pooler mode (e.g. Odyssey / PgBouncer)
249
enum
class
PoolerMode
{ kSession, kTransaction };
250
251
/// PostgreSQL connection options
252
///
253
/// Dynamic option @ref POSTGRES_CONNECTION_SETTINGS
254
struct
ConnectionSettings
{
255
enum
PreparedStatementOptions {
256
kCachePreparedStatements,
257
kNoPreparedStatements,
258
};
259
enum
UserTypesOptions {
260
kUserTypesEnabled,
261
kUserTypesEnforced,
262
kPredefinedTypesOnly,
263
};
264
enum
CheckQueryParamsOptions {
265
kIgnoreUnused,
266
kCheckUnused,
267
};
268
enum
DiscardOnConnectOptions {
269
kDiscardNone,
270
kDiscardAll,
271
};
272
enum
StatementLogMode {
273
kLogSkip,
274
kLog,
275
};
276
using
SettingsVersion = std::size_t;
277
278
/// Cache prepared statements or not
279
PreparedStatementOptions
prepared_statements
= kCachePreparedStatements;
280
281
/// Enables the usage of user-defined types
282
UserTypesOptions
user_types
= kUserTypesEnabled;
283
284
/// Checks for not-NULL query params that are not used in query
285
CheckQueryParamsOptions
ignore_unused_query_params
= kCheckUnused;
286
287
/// Limits the size or prepared statements cache
288
std::size_t
max_prepared_cache_size
=
kDefaultMaxPreparedCacheSize
;
289
290
/// Turns on connection pipeline mode
291
PipelineMode
pipeline_mode
=
PipelineMode
::kDisabled;
292
293
/// Enables protocol-level optimization when executing prepared statements
294
OmitDescribeInExecuteMode
omit_describe_mode
=
OmitDescribeInExecuteMode
::kDisabled;
295
296
/// This many connection errors in 15 seconds block new connections opening
297
std::size_t
recent_errors_threshold
= 5;
298
299
/// The maximum lifetime of the connection after which it will be closed
300
std::optional<std::chrono::seconds>
max_ttl
{};
301
302
/// Execute DISCARD ALL after establishing a new connection
303
/// Has effect only in session pooler mode (@ref PoolerMode::kSession)
304
DiscardOnConnectOptions
discard_on_connect
= kDiscardAll;
305
306
/// Statement logging in span tags
307
StatementLogMode
statement_log_mode
= kLog;
308
309
bool
deadline_propagation_enabled =
true
;
310
311
/// Helps keep track of the changes in settings
312
SettingsVersion
version
{0U};
313
314
std::optional<std::string> application_name{};
315
316
PoolerMode
pooler_mode{
PoolerMode
::kSession};
317
318
/// DANGEROUS. Has effect only in @ref PoolerMode::kTransaction. When set, no `SET statement_timeout` is sent
319
/// before autocommit statements, saving a round trip at the cost of losing statement_timeout enforcement (and
320
/// deadline propagation built on top of it) for such queries
321
bool
omit_statement_timeout_for_autocommit
=
false
;
322
323
bool
operator==(
const
ConnectionSettings
& rhs)
const
{
324
return
!RequiresConnectionReset(rhs) &&
recent_errors_threshold
== rhs
.
recent_errors_threshold
;
325
}
326
327
bool
RequiresConnectionReset(
const
ConnectionSettings
& rhs)
const
{
328
// TODO: max_prepared_cache_size check could be relaxed
329
return
prepared_statements
!= rhs
.
prepared_statements
||
user_types
!= rhs
.
user_types
||
330
ignore_unused_query_params
!= rhs
.
ignore_unused_query_params
||
331
max_prepared_cache_size
!= rhs
.
max_prepared_cache_size
||
pipeline_mode
!= rhs
.
pipeline_mode
||
332
max_ttl
!= rhs
.
max_ttl
||
discard_on_connect
!= rhs
.
discard_on_connect
||
333
omit_describe_mode
!= rhs
.
omit_describe_mode
|| application_name != rhs.application_name ||
334
pooler_mode != rhs.pooler_mode ||
335
omit_statement_timeout_for_autocommit
!= rhs
.
omit_statement_timeout_for_autocommit
;
336
}
337
};
338
339
struct
ConnectionSettingsDynamic
final
{
340
std::optional<
ConnectionSettings
::PreparedStatementOptions> prepared_statements{};
341
std::optional<
ConnectionSettings
::UserTypesOptions> user_types{};
342
std::optional<std::size_t> max_prepared_cache_size{};
343
std::optional<std::size_t> recent_errors_threshold{};
344
std::optional<
ConnectionSettings
::CheckQueryParamsOptions> ignore_unused_query_params{};
345
std::optional<std::chrono::seconds> max_ttl{};
346
std::optional<
ConnectionSettings
::DiscardOnConnectOptions> discard_on_connect{};
347
std::optional<
bool
> deadline_propagation_enabled{};
348
std::optional<
bool
> omit_statement_timeout_for_autocommit{};
349
};
350
351
/// @brief PostgreSQL statements metrics options
352
///
353
/// Dynamic option @ref POSTGRES_STATEMENT_METRICS_SETTINGS
354
struct
StatementMetricsSettings
final
{
355
/// Store metrics in LRU of this size
356
std::size_t
max_statements
{0};
357
358
bool
operator==(
const
StatementMetricsSettings& other)
const
{
return
max_statements
== other
.
max_statements
; }
359
};
360
361
/// Initialization modes
362
enum
class
InitMode
{
363
kSync = 0,
364
kAsync,
365
};
366
367
enum
class
ConnlimitMode {
368
kManual = 0,
369
kAuto,
370
};
371
372
/// Settings for storages::postgres::Cluster
373
struct
ClusterSettings
{
374
/// settings for statements metrics
375
StatementMetricsSettings
statement_metrics_settings
;
376
377
/// settings for host discovery
378
TopologySettings
topology_settings
;
379
380
/// settings for connection pools
381
PoolSettings
pool_settings
;
382
383
/// settings for individual connections
384
ConnectionSettings
conn_settings
;
385
386
/// initialization mode
387
InitMode
init_mode
=
InitMode
::kSync;
388
389
/// database name
390
std::string
db_name
;
391
392
/// connection limit change mode
393
ConnlimitMode
connlimit_mode
= ConnlimitMode::kAuto;
394
395
/// congestion control settings
396
congestion_control
::v2::LinearController::StaticConfig
cc_config
;
397
};
398
399
}
// namespace storages::postgres
400
401
USERVER_NAMESPACE_END
userver
storages
postgres
options.hpp
Generated on
for userver by
Doxygen
1.17.0