userver: userver/dynamic_config/updater/component.hpp Source File
Loading...
Searching...
No Matches
component.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/dynamic_config/updater/component.hpp
4/// @brief @copybrief components::DynamicConfigClientUpdater
5
6#include <chrono>
7#include <functional>
8#include <optional>
9#include <string>
10#include <unordered_set>
11
12#include <userver/cache/cache_statistics.hpp>
13#include <userver/cache/caching_component_base.hpp>
14#include <userver/cache/update_type.hpp>
15#include <userver/components/component_fwd.hpp>
16#include <userver/concurrent/variable.hpp>
17#include <userver/dynamic_config/client/client.hpp>
18#include <userver/dynamic_config/storage/component.hpp>
19#include <userver/dynamic_config/updater/additional_keys_token.hpp>
20#include <userver/dynamic_config/updates_sink/component.hpp>
21#include <userver/engine/mutex.hpp>
22#include <userver/utils/impl/transparent_hash.hpp>
23
24USERVER_NAMESPACE_BEGIN
25
26namespace components {
27
28// clang-format off
29
30/// @ingroup userver_components
31///
32/// @brief Component that does a periodic update of runtime configs.
33///
34/// Note that the service with dynamic config update component and without
35/// configs cache requires successful update to start. See
36/// @ref dynamic_config_fallback for details and explanation.
37///
38/// ## Optional update event deduplication
39///
40/// Config update types to deduplicate. If enabled, JSON of the whole config is
41/// compared to the previous one; if same, no config update event is sent to the
42/// subscribers of dynamic_config::Source (`OnConfigUpdate` functions).
43///
44/// `deduplicate-update-types` static config option specifies the update types
45/// of the config cache, for which event deduplication should be performed.
46/// Possible values:
47/// - `none` (the default)
48/// - `only-full`
49/// - `only-incremental`
50/// - `full-and-incremental`
51///
52/// Full updates will always send an event unless deduplicated. Incremental
53/// updates may send an extra event for some config service implementations.
54///
55/// Note: This is not a silver bullet against extra events, because the events
56/// will be sent to every dynamic config subscriber if *any* part of the config
57/// has updated, not if the interesting part has updated.
58///
59/// ## Static options:
60/// Name | Description | Default value
61/// ---- | ----------- | -------------
62/// updates-sink | name of the component derived from components::DynamicConfigUpdatesSinkBase to be used for storing received updates | dynamic-config
63/// store-enabled | store the retrieved values into the updates sink determined by the `updates-sink` option | true
64/// load-only-my-values | request from the client only the values used by this service | true
65/// deduplicate-update-types | update types for best-effort update event deduplication, see above | `full-and-incremental`
66///
67/// See also the options for components::CachingComponentBase.
68///
69/// ## Static configuration example:
70///
71/// @snippet components/common_component_list_test.cpp Sample dynamic config client updater component config
72
73// clang-format on
74class DynamicConfigClientUpdater final : public CachingComponentBase<dynamic_config::DocsMap> {
75public:
76 /// @ingroup userver_component_names
77 /// @brief The default name of components::DynamicConfigClientUpdater
78 static constexpr std::string_view kName = "dynamic-config-client-updater";
79
80 DynamicConfigClientUpdater(const ComponentConfig&, const ComponentContext&);
81
82 ~DynamicConfigClientUpdater() override;
83
84 // After calling this method, `Get()` will return a dynamic_config containing
85 // the specified keys while the token that this method returned is alive.
86 dynamic_config::AdditionalKeysToken SetAdditionalKeys(std::vector<std::string> keys);
87
88 static yaml_config::Schema GetStaticConfigSchema();
89
90private:
91 void
92 Update(cache::UpdateType update_type, const std::chrono::system_clock::time_point& last_update, const std::chrono::system_clock::time_point& now, cache::UpdateStatisticsScope&)
93 override;
94
95 void UpdateFull(const std::vector<std::string>& docs_map_keys, cache::UpdateStatisticsScope&);
96
97 void UpdateIncremental(const std::vector<std::string>& docs_map_keys, cache::UpdateStatisticsScope&);
98
99 void SetDisabledKillSwitchesToDefault(
100 dynamic_config::DocsMap& docs_map,
101 const std::vector<std::string>& kill_switches_disabled
102 );
103
104 dynamic_config::DocsMap MergeDocsMap(
105 const dynamic_config::DocsMap& current,
106 dynamic_config::DocsMap&& update,
107 const std::vector<std::string>& removed
108 );
109 void StoreIfEnabled(const dynamic_config::DocsMap& value);
110
111 using DocsMapKeys = utils::impl::TransparentSet<std::string>;
112 using AdditionalDocsMapKeys = std::unordered_set<std::shared_ptr<std::vector<std::string>>>;
113
114 std::vector<std::string> GetDocsMapKeysToFetch(AdditionalDocsMapKeys& additional_docs_map_keys);
115
116 void UpdateAdditionalKeys(const std::vector<std::string>& keys);
117
118 bool IsDuplicate(cache::UpdateType update_type, const dynamic_config::DocsMap& new_value) const;
119
120 DynamicConfigUpdatesSinkBase& updates_sink_;
121 const bool load_only_my_values_;
122 const bool store_enabled_;
123 const std::optional<cache::AllowedUpdateTypes> deduplicate_update_types_;
124 dynamic_config::Client& config_client_;
125
126 dynamic_config::Client::Timestamp server_timestamp_;
127 // for atomic updates of cached data
128 engine::Mutex update_config_mutex_;
129 dynamic_config::DocsMap docs_map_defaults_;
130 DocsMapKeys docs_map_keys_;
131 concurrent::Variable<AdditionalDocsMapKeys> additional_docs_map_keys_;
132};
133
134template <>
135inline constexpr bool kHasValidate<DynamicConfigClientUpdater> = true;
136
137} // namespace components
138
139USERVER_NAMESPACE_END