userver: userver/dynamic_config/storage/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/storage/component.hpp
4/// @brief @copybrief components::DynamicConfig
5
6#include <memory>
7#include <string_view>
8#include <type_traits>
9
10#include <userver/components/component_base.hpp>
11#include <userver/concurrent/async_event_source.hpp>
12#include <userver/dynamic_config/snapshot.hpp>
13#include <userver/dynamic_config/source.hpp>
14#include <userver/dynamic_config/updates_sink/component.hpp>
15#include <userver/utils/fast_pimpl.hpp>
16
17USERVER_NAMESPACE_BEGIN
18
19namespace components {
20
21/// @ingroup userver_components
22///
23/// @brief Component that stores the
24/// @ref scripts/docs/en/userver/dynamic_config.md "dynamic config".
25///
26/// Note that the service with `updates-enabled: true` and without
27/// configs cache requires successful update to start. See
28/// @ref dynamic_config_fallback for details and explanation.
29///
30/// ## Behavior on missing configs
31///
32/// If a config variable is entirely missing the fetched config, the value from
33/// `dynamic_config_fallback.json` is used (see `fallback-path` static config option).
34///
35/// ## Behavior on config parsing failure
36///
37/// If a config variable from the fetched config fails to be parsed (the parser
38/// fails with an exception), then the whole config update fails. It means that:
39///
40/// - If the service is just starting, it will shut down
41/// - If the service is already running, the config updates will stop until
42/// the config in the config service changes to a valid one. You can
43/// monitor this situation using the metric at path `cache.any.time.time-from-last-successful-start-ms`
44///
45/// ## Static options of components::DynamicConfigClient :
46/// @include{doc} scripts/docs/en/components_schema/core/src/dynamic_config/storage/component.md
47///
48/// Options inherited from @ref components::ComponentBase :
49/// @include{doc} scripts/docs/en/components_schema/core/src/components/impl/component_base.md
50///
51/// ## Static configuration example:
52///
53/// @snippet components/common_component_list_test.cpp Sample dynamic config component config
54///
55/// ## Usage example:
56/// @snippet components/component_sample_test.cpp Sample user component runtime config source
57class DynamicConfig final : public DynamicConfigUpdatesSinkBase {
58public:
59 /// @ingroup userver_component_names
60 /// @brief The default name of @ref components::DynamicConfig
61 static constexpr std::string_view kName = "dynamic-config";
62
63 class NoblockSubscriber;
64
65 DynamicConfig(const ComponentConfig&, const ComponentContext&);
66 ~DynamicConfig() override;
67
68 /// Use `dynamic_config::Source` to get up-to-date config values, or to do
69 /// something special on config updates
70 dynamic_config::Source GetSource();
71
72 /// Get config defaults with overrides applied. Useful in the implementation
73 /// of custom config clients. Most code does not need to deal with these
74 const dynamic_config::DocsMap& GetDefaultDocsMap() const;
75
76 static yaml_config::Schema GetStaticConfigSchema();
77
78private:
79 ComponentHealth GetComponentHealth() const override;
80 void OnLoadingCancelled() override;
81
82 void SetConfig(std::string_view updater, dynamic_config::DocsMap&& value) override;
83
84 void SetConfig(std::string_view updater, const dynamic_config::DocsMap& value) override;
85
86 void NotifyLoadingFailed(std::string_view updater, std::string_view error) override;
87
88 class Impl;
89 std::unique_ptr<Impl> impl_;
90};
91
92/// @brief Allows to subscribe to `DynamicConfig` updates without waiting for
93/// the first update to complete. Primarily intended for internal use.
94class DynamicConfig::NoblockSubscriber final {
95public:
96 explicit NoblockSubscriber(DynamicConfig& config_component) noexcept;
97
98 NoblockSubscriber(NoblockSubscriber&&) = delete;
99 NoblockSubscriber& operator=(NoblockSubscriber&&) = delete;
100
101 /// @brief Subscribes to dynamic-config updates with information about the
102 /// current and previous states.
103 ///
104 /// Subscribes to dynamic-config updates using a member function, named
105 /// `OnConfigUpdate` by convention. actual configs values are already loaded, also constructs @ref
106 /// dynamic_config::Diff object using `std::nullopt` and current config snapshot, then immediately invokes the
107 /// function with it (this invocation will be executed synchronously).
108 ///
109 /// @note Callbacks occur in full accordance with
110 /// @ref components::DynamicConfigClientUpdater options.
111 ///
112 /// @warning In debug mode the last notification for any subscriber will be
113 /// called with `std::nullopt` and current config snapshot.
114 ///
115 /// Example usage:
116 /// @snippet dynamic_config/config_test.cpp Custom subscription for dynamic config update
117 ///
118 /// @param obj the subscriber, which is the owner of the listener method, and
119 /// is also used as the unique identifier of the subscription
120 /// @param name the name of the subscriber, for diagnostic purposes
121 /// @param func the listener method, named `OnConfigUpdate` by convention.
122 /// @returns a @ref concurrent::AsyncEventSubscriberScope controlling the
123 /// subscription, which should be stored as a member in the subscriber;
124 /// `Unsubscribe` should be called explicitly
125 ///
126 /// @see based on @ref concurrent::AsyncEventSource engine
127 ///
128 /// @see dynamic_config::Diff
129 template <typename Class>
130 concurrent::AsyncEventSubscriberScope UpdateIfHasConfigAndListen(
131 Class* obj,
132 std::string_view name,
133 void (Class::*func)(const dynamic_config::Diff& diff)
134 ) {
135 return DoUpdateIfHasConfigAndListen(
136 concurrent::FunctionId(obj),
137 name,
138 [obj, func](const dynamic_config::Diff& diff) { (obj->*func)(diff); }
139 );
140 }
141
142private:
143 concurrent::AsyncEventSubscriberScope DoUpdateIfHasConfigAndListen(
144 concurrent::FunctionId id,
145 std::string_view name,
146 concurrent::AsyncEventSource<const dynamic_config::Diff&>::Function&& func
147 );
148
149 DynamicConfig& config_component_;
150};
151
152template <>
153inline constexpr bool kHasValidate<DynamicConfig> = true;
154
155template <>
156inline constexpr auto kConfigFileMode<DynamicConfig> = ConfigFileMode::kNotRequired;
157
158dynamic_config::Source LocateDependency(
159 const components::WithType<dynamic_config::Source>&,
160 const components::ComponentConfig& config,
161 const components::ComponentContext& context
162);
163
164} // namespace components
165
166USERVER_NAMESPACE_END