11#include <userver/components/component_fwd.hpp>
12#include <userver/components/static_config_validator.hpp>
14USERVER_NAMESPACE_BEGIN
23auto NameRegistrationFromComponentType() ->
decltype(std::string{T::kName}) {
24 return std::string{T::kName};
27template <
class T,
class... Args>
28auto NameRegistrationFromComponentType(Args...) {
29 static_assert(!
sizeof(T),
30 "Component does not have a 'kName' member convertible to "
31 "std::string. You have to explicitly specify the name: "
32 "component_list.Append<T>(name).");
36using ComponentBaseFactory =
37 std::function<std::unique_ptr<components::impl::ComponentBase>(
38 const components::ComponentConfig&,
39 const components::ComponentContext&)>;
42void AddComponentImpl(Manager& manager,
43 const components::ComponentConfigMap& config_map,
44 const std::string& name, ComponentBaseFactory factory);
46class ComponentAdderBase {
48 ComponentAdderBase() =
delete;
49 ComponentAdderBase(
const ComponentAdderBase&) =
delete;
50 ComponentAdderBase(ComponentAdderBase&&) =
delete;
51 ComponentAdderBase& operator=(
const ComponentAdderBase&) =
delete;
52 ComponentAdderBase& operator=(ComponentAdderBase&&) =
delete;
54 ComponentAdderBase(std::string name,
ConfigFileMode config_file_mode);
56 virtual ~ComponentAdderBase();
58 const std::string& GetComponentName()
const noexcept {
return name_; }
60 ConfigFileMode GetConfigFileMode()
const {
return config_file_mode_; }
62 virtual void operator()(Manager&,
63 const components::ComponentConfigMap&)
const = 0;
65 virtual void ValidateStaticConfig(
const ComponentConfig&,
66 ValidationMode)
const = 0;
68 virtual yaml_config::Schema GetStaticConfigSchema()
const = 0;
75template <
typename Component>
76class ComponentAdder
final :
public ComponentAdderBase {
78 explicit ComponentAdder(std::string name)
79 : ComponentAdderBase(std::move(name), kConfigFileMode<Component>) {}
81 void operator()(Manager&,
82 const components::ComponentConfigMap&)
const override;
84 void ValidateStaticConfig(
const ComponentConfig& static_config,
85 ValidationMode validation_mode)
const override {
86 impl::TryValidateStaticConfig<Component>(static_config, validation_mode);
89 yaml_config::Schema GetStaticConfigSchema()
const override {
90 return impl::GetStaticConfigSchema<Component>();
94template <
typename Component>
95void ComponentAdder<Component>::operator()(
96 Manager& manager,
const components::ComponentConfigMap& config_map)
const {
100 std::is_convertible_v<Component*,
components::impl::ComponentBase*>,
101 "Component should publicly inherit from components::LoggableComponentBase"
102 " and the component definition should be visible at its registration");
103 impl::AddComponentImpl(manager, config_map, GetComponentName(),
104 [](
const components::ComponentConfig& config,
105 const components::ComponentContext& context) {
106 return std::make_unique<Component>(config, context);
110using ComponentAdderPtr = std::unique_ptr<
const impl::ComponentAdderBase>;
112struct ComponentAdderComparator {
113 using is_transparent = std::true_type;
115 static std::string_view ToStringView(
const ComponentAdderPtr& x)
noexcept {
116 return std::string_view{x->GetComponentName()};
119 static std::string_view ToStringView(std::string_view x)
noexcept {
123 template <
class T,
class U>
124 bool operator()(
const T& x,
const U& y)
const noexcept {
125 return ToStringView(x) < ToStringView(y);
133class ComponentList
final {
136 template <
typename Component>
137 ComponentList&
Append() &;
140 template <
typename Component>
141 ComponentList&
Append(std::string name) &;
150 template <
typename Component,
typename... Args>
154 bool Contains(std::string_view name)
const {
return adders_.count(name) > 0; }
158 std::set<impl::ComponentAdderPtr, impl::ComponentAdderComparator>;
160 Adders::const_iterator begin()
const {
return adders_.begin(); }
161 Adders::const_iterator end()
const {
return adders_.end(); }
163 ComponentList& Append(impl::ComponentAdderPtr&& added) &;
172template <
typename Component>
173ComponentList& ComponentList::
Append() & {
174 return Append<Component>(
175 impl::NameRegistrationFromComponentType<Component>());
178template <
typename Component>
179ComponentList& ComponentList::
Append(std::string name) & {
180 using Adder = impl::ComponentAdder<Component>;
181 auto adder = std::make_unique<
const Adder>(std::move(name));
182 return Append(std::move(adder));
185template <
typename Component,
typename... Args>
186ComponentList&& ComponentList::
Append(Args&&... args) && {
187 return std::move(Append<Component>(std::forward<Args>(args)...));