userver: userver/storages/postgres/component.hpp Source File
Loading...
Searching...
No Matches
component.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/storages/postgres/component.hpp
4/// @brief @copybrief components::Postgres
5
6#include <chrono>
7
8#include <userver/components/component_base.hpp>
9#include <userver/concurrent/async_event_source.hpp>
10#include <userver/dynamic_config/snapshot.hpp>
11#include <userver/engine/mutex.hpp>
12#include <userver/utils/statistics/entry.hpp>
13
14#include <userver/storages/postgres/database.hpp>
15
16USERVER_NAMESPACE_BEGIN
17
18namespace components {
19
20// clang-format off
21
22/// @ingroup userver_components
23///
24/// @brief PosgreSQL client component
25///
26/// Provides access to a PostgreSQL cluster.
27///
28/// ## Dynamic options:
29/// * @ref POSTGRES_DEFAULT_COMMAND_CONTROL
30/// * @ref POSTGRES_HANDLERS_COMMAND_CONTROL
31/// * @ref POSTGRES_QUERIES_COMMAND_CONTROL
32/// * @ref POSTGRES_CONNECTION_POOL_SETTINGS
33/// * @ref POSTGRES_TOPOLOGY_SETTINGS
34/// * @ref POSTGRES_CONNECTION_SETTINGS
35/// * @ref POSTGRES_STATEMENT_METRICS_SETTINGS
36/// * @ref POSTGRES_CONNLIMIT_MODE_AUTO_ENABLED
37///
38/// ## Static configuration example:
39///
40/// ```
41/// # yaml
42/// postgres-taxi:
43/// dbalias: taxi
44/// blocking_task_processor: task-processor-name
45/// max_replication_lag: 60s
46/// min_pool_size: 4
47/// max_pool_size: 15
48/// max_queue_size: 200
49/// max_statement_metrics: 50
50/// ```
51/// You must specify either `dbalias` or `dbconnection`.
52/// If the component is configured with an alias, it will lookup connection data
53/// in Secdist.
54///
55/// It is a common practice to provide a database connection string via
56/// environment variables. To retrieve a value from the environment use
57/// `dbconnection#env: THE_ENV_VARIABLE_WITH_CONNECTION_STRING` as described
58/// in yaml_config::YamlConfig.
59///
60/// You must specify `blocking_task_processor` as well.
61///
62/// `max_replication_lag` can be used to tune replication lag limit for replicas.
63/// Once the replica lag exceeds this value it will be automatically disabled.
64/// Note, however, that client-size lag detection is not precise in nature
65/// and can only provide the precision of couple seconds.
66///
67/// ## Secdist format
68///
69/// A PosgreSQL alias in secdist is described as a JSON array of objects
70/// containing a single cluster description. There are two formats of describing
71/// a cluster, the first one assigns predefined roles to DSNs, the second one
72/// is just a list of DSNs and the Postgres component takes care of discovering
73/// the cluster's topology itself.
74///
75/// ### Predefined roles
76///
77/// In predefined roles format the component requires single-host connection
78/// strings.
79///
80/// ```json
81/// {
82/// "shard_number" : 0,
83/// "master": "host=localhost dbname=example",
84/// "sync_slave": "host=localhost dbname=example",
85/// "slaves": [
86/// "host=localhost dbname=example"
87/// ]
88/// }
89/// ```
90///
91/// The predefined roles format is deprecated and the support will be removed
92/// soon.
93///
94/// ### Automatic discovery
95///
96/// In automatic discovery format the connection strings are any valid
97/// PostgreSQL connection strings including multi-host ones with the exception
98/// of `target_session_attrs` which will be ignored.
99///
100/// ```json
101/// {
102/// "shard_number" : 0,
103/// "hosts": [
104/// "host=host1,host2,host3 dbname=example",
105/// "postgresql://host1:5432,host2:6432,host3:12000/example"
106/// ]
107/// }
108/// ```
109///
110/// The `shard_number` parameter is required in both formats and must match the
111/// index of cluster description object in the alias array.
112///
113/// Please see [PostgreSQL documentation](https://www.postgresql.org/docs/12/libpq-connect.html#LIBPQ-CONNSTRING)
114/// on connection strings.
115///
116/// ## Static options:
117/// Name | Description | Default value
118/// ----------------------- | ----------------------------------------------------------------------------- | -------------
119/// dbalias | name of the database in secdist config (if available) | --
120/// dbconnection | connection DSN string (used if no dbalias specified) | --
121/// blocking_task_processor | name of task processor for background blocking operations | --
122/// max_replication_lag | replication lag limit for usable slaves | 60s
123/// sync-start | perform initial connections synchronously | false
124/// dns_resolver | server hostname resolver type (getaddrinfo or async) | 'async'
125/// persistent-prepared-statements | cache prepared statements or not | true
126/// user-types-enabled | allow use of user-defined types | true
127/// check-user-types | cancel service start if some user types have not been loaded, which helps to detect missing migrations | false
128/// ignore_unused_query_params| disable check for not-NULL query params that are not used in query | false
129/// monitoring-dbalias | name of the database for monitorings | calculated from dbalias or dbconnection options
130/// max_prepared_cache_size | prepared statements cache size limit | 200
131/// max_statement_metrics | limit of exported metrics for named statements | 0
132/// min_pool_size | number of connections created initially | 4
133/// max_pool_size | maximum number of created connections for "connlimit_mode: manual" | 15
134/// max_queue_size | maximum number of clients waiting for a connection | 200
135/// connecting_limit | limit for concurrent establishing connections number per pool (0 - unlimited) | 0
136/// connlimit_mode | max_connections setup mode (manual or auto), also see @ref scripts/docs/en/userver/pg_connlimit_mode_auto.md | auto
137/// error-injection | artificial error injection settings, error_injection::Settings | --
138
139// clang-format on
140
141class Postgres : public ComponentBase {
142public:
143 /// Default shard number
144 static constexpr size_t kDefaultShardNumber = 0;
145 /// Default command control
146 static constexpr storages::postgres::CommandControl kDefaultCommandControl{
147 std::chrono::milliseconds{500}, // network timeout
148 std::chrono::milliseconds{250} // statement timeout
149 };
150
151 /// Component constructor
152 Postgres(const ComponentConfig&, const ComponentContext&);
153 /// Component destructor
154 ~Postgres() override;
155
156 /// Cluster accessor for default shard number
157 storages::postgres::ClusterPtr GetCluster() const;
158
159 /// Cluster accessor for specific shard number
160 storages::postgres::ClusterPtr GetClusterForShard(size_t shard) const;
161
162 /// Get total shard count
164
165 /// Get database object
166 storages::postgres::DatabasePtr GetDatabase() const { return database_; }
167
168 /// Reports statistics for PostgreSQL driver
169 void ExtendStatistics(utils::statistics::Writer& writer);
170
171 static yaml_config::Schema GetStaticConfigSchema();
172
173private:
174 void OnConfigUpdate(const dynamic_config::Snapshot& cfg);
175
176 std::string name_;
177 std::string db_name_;
178 storages::postgres::ClusterSettings initial_settings_;
179 storages::postgres::DatabasePtr database_;
180
181 // Subscriptions must be the last fields, because the fields above are used
182 // from callbacks.
183 concurrent::AsyncEventSubscriberScope config_subscription_;
184 utils::statistics::Entry statistics_holder_;
185};
186
187template <>
188inline constexpr bool kHasValidate<Postgres> = true;
189
190} // namespace components
191
192USERVER_NAMESPACE_END