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