userver: userver/storages/redis/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/redis/component.hpp
4/// @brief @copybrief components::Redis
5
6#include <memory>
7#include <string>
8#include <unordered_map>
9
10#include <userver/components/component_base.hpp>
11#include <userver/components/component_fwd.hpp>
12#include <userver/dynamic_config/source.hpp>
13#include <userver/rcu/rcu.hpp>
14#include <userver/storages/redis/base.hpp>
15#include <userver/storages/redis/fwd.hpp>
16#include <userver/storages/redis/wait_connected_mode.hpp>
17#include <userver/storages/secdist/secdist.hpp>
18#include <userver/testsuite/redis_control.hpp>
19#include <userver/utils/statistics/fwd.hpp>
20
21USERVER_NAMESPACE_BEGIN
22
23/// Components, clients and helpers for different databases and storages
24namespace storages {}
25
26/// Valkey and Redis client and helpers
27namespace storages::redis {
28
29class SubscribeClientImpl;
30
31namespace impl {
32class Sentinel;
33class ThreadPools;
34class HealthCheckManager;
35} // namespace impl
36} // namespace storages::redis
37
38namespace components {
39
40/// @ingroup userver_components
41///
42/// @brief Valkey and Redis client component
43///
44/// Provides access to a valkey or redis cluster.
45///
46/// ## Dynamic options:
47/// * @ref REDIS_COMMANDS_BUFFERING_SETTINGS
48/// * @ref REDIS_DEFAULT_COMMAND_CONTROL
49/// * @ref REDIS_METRICS_SETTINGS
50/// * @ref REDIS_PUBSUB_METRICS_SETTINGS
51/// * @ref REDIS_RETRY_BUDGET_SETTINGS
52/// * @ref REDIS_REPLICA_MONITORING_SETTINGS
53/// * @ref REDIS_SUBSCRIBER_DEFAULT_COMMAND_CONTROL
54/// * @ref REDIS_SUBSCRIPTIONS_REBALANCE_MIN_INTERVAL_SECONDS
55/// * @ref REDIS_WAIT_CONNECTED
56/// * @ref REDIS_IGNORE_HEALTH_CHECK
57///
58/// ## Static options of components::Redis :
59/// @include{doc} scripts/docs/en/components_schema/redis/src/storages/redis/component.md
60///
61/// Options inherited from @ref components::ComponentBase :
62/// @include{doc} scripts/docs/en/components_schema/core/src/components/impl/component_base.md
63///
64/// ## Static configuration example:
65///
66/// ```
67/// # yaml
68/// redis:
69/// groups:
70/// - config_name: cats
71/// db: hello_service_cats_catalogue
72/// sharding_strategy: RedisCluster
73/// - config_name: dogs
74/// db: hello_service_dogs_catalogue
75/// subscribe_groups:
76/// - config_name: food
77/// db: hello_service_pet_food_orders
78/// thread_pools:
79/// redis_thread_pool_size: 8
80/// sentinel_thread_pool_size: 1
81/// ```
82///
83/// ## Secdist format
84///
85/// If a `config_name` option is provided, for example
86/// `groups.some.config_name: some_name_of_your_database`, then the Secdist
87/// entry for that alias should look like following:
88/// @code{.json}
89/// {
90/// "redis_settings": {
91/// "some_name_of_your_database": {
92/// "password": "the_password_of_your_database",
93/// "sentinel_password": "the_password_for_sentinels_if_any",
94/// "secure_connection": false,
95/// "sentinels": [
96/// {"host": "the_host1_of_your_database", "port": 11564}
97/// ],
98/// "shards": [
99/// {"name": "test_master0"}
100/// ]
101/// }
102/// }
103/// }
104/// @endcode
105///
106/// For an example of Secdist setup for standalone, sentinel and cluster testsuite configurations see the snippet:
107///
108/// @snippet redis/functional_tests/integration_tests/tests/conftest.py Sample pytest redis configuration
109///
110/// Note that if the components::Secdist component has `update-period` other
111/// than 0, then new connections are created or gracefully closed as the secdist configuration change to new value.
112///
113/// ## Cluster Valkey or Cluster Redis setup
114///
115/// Valkey/Redis cluster is the new recommended way of setting up key-value datastores with improved stability.
116///
117/// To start, set `sharding_strategy: RedisCluster` in the static config
118/// as shown above.
119///
120/// Secdist configuration is simplified:
121///
122/// 1. `"shards"` field is ignored, you can specify an empty array there;
123/// 2. `"sentinels"` field should contain some of the cluster nodes. They are
124/// only used for topology discovery; it is not necessary to list all nodes.
125class Redis : public ComponentBase {
126public:
127 Redis(const ComponentConfig& config, const ComponentContext& component_context);
128
129 ~Redis() override;
130
131 /// @ingroup userver_component_names
132 /// @brief The default name of components::Redis
133 static constexpr std::string_view kName = "redis";
134
135 std::shared_ptr<storages::redis::Client> GetClient(
136 const std::string& name,
137 storages::redis::RedisWaitConnected wait_connected = {}
138 ) const;
139 [[deprecated("use GetClient()")]] std::shared_ptr<storages::redis::impl::Sentinel> Client(const std::string& name
140 ) const;
141 std::shared_ptr<storages::redis::SubscribeClient> GetSubscribeClient(
142 const std::string& name,
143 storages::redis::RedisWaitConnected wait_connected = {}
144 ) const;
145
147
148 static yaml_config::Schema GetStaticConfigSchema();
149
150private:
151 void OnConfigUpdate(const dynamic_config::Snapshot& cfg);
152 void OnSecdistUpdate(const storages::secdist::SecdistConfig& cfg);
153
154 void Connect(
155 const ComponentConfig& config,
156 const ComponentContext& component_context,
157 const testsuite::RedisControl& testsuite_redis_control
158 );
159
160 void WriteStatistics(utils::statistics::Writer& writer);
161 void WriteStatisticsPubsub(utils::statistics::Writer& writer);
162
163 std::shared_ptr<storages::redis::impl::ThreadPools> thread_pools_;
164 std::unordered_map<std::string, std::shared_ptr<storages::redis::impl::Sentinel>> sentinels_;
165 std::unordered_map<std::string, std::shared_ptr<storages::redis::Client>> clients_;
166 std::unordered_map<std::string, std::shared_ptr<storages::redis::SubscribeClientImpl>> subscribe_clients_;
167
168 std::shared_ptr<storages::redis::impl::HealthCheckManager> health_check_manager_;
169
170 dynamic_config::Source config_;
171 concurrent::AsyncEventSubscriberScope config_subscription_;
172 concurrent::AsyncEventSubscriberScope secdist_subscription_;
173
174 rcu::Variable<storages::redis::MetricsSettings> metrics_settings_;
175 rcu::Variable<storages::redis::PubsubMetricsSettings> pubsub_metrics_settings_;
176};
177
178template <>
179inline constexpr bool kHasValidate<Redis> = true;
180
181} // namespace components
182
183USERVER_NAMESPACE_END