Github   Telegram
Loading...
Searching...
No Matches
component_list.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/components/component_list.hpp
4/// @brief @copybrief components::ComponentList
5
6#include <memory>
7#include <string>
8#include <unordered_set>
9#include <vector>
10
11#include <userver/components/component_fwd.hpp>
12#include <userver/components/manager.hpp>
13#include <userver/components/static_config_validator.hpp>
14
15USERVER_NAMESPACE_BEGIN
16
17namespace components {
18
19class Manager;
20
21namespace impl {
22
23class ComponentAdderBase {
24 public:
25 explicit ComponentAdderBase(std::string name,
26 ConfigFileMode config_file_mode);
27
28 virtual ~ComponentAdderBase() = default;
29
30 const std::string& GetComponentName() const { return name_; }
31
32 ConfigFileMode GetConfigFileMode() const { return config_file_mode_; }
33
34 virtual void operator()(Manager&,
35 const components::ComponentConfigMap&) const = 0;
36
37 virtual void ValidateStaticConfig(const ComponentConfig&,
38 ValidationMode) const = 0;
39
40 private:
41 std::string name_;
42 ConfigFileMode config_file_mode_;
43};
44
45} // namespace impl
46
47/// @brief A list to keep a unique list of components to start with
48/// components::Run(), utils::DaemonMain() or components::RunOnce().
49class ComponentList final {
50 public:
51 template <typename Component>
52 ComponentList& Append() &;
53
54 template <typename Component>
55 ComponentList& Append(std::string name) &;
56
57 ComponentList& AppendComponentList(ComponentList&& other) &;
58 ComponentList&& AppendComponentList(ComponentList&& other) &&;
59
60 template <typename Component, typename... Args>
61 ComponentList&& Append(Args&&...) &&;
62
63 using Adders = std::vector<std::unique_ptr<impl::ComponentAdderBase>>;
64
65 Adders::const_iterator begin() const { return adders_.begin(); }
66 Adders::const_iterator end() const { return adders_.end(); }
67
68 bool Contains(const std::string& name) const {
69 return component_names_.count(name) > 0;
70 }
71
72 private:
73 std::vector<std::unique_ptr<impl::ComponentAdderBase>> adders_;
74 std::unordered_set<std::string> component_names_;
75};
76
77namespace impl {
78
79template <typename Component>
80class DefaultComponentAdder final : public ComponentAdderBase {
81 public:
82 DefaultComponentAdder();
83 void operator()(Manager&,
84 const components::ComponentConfigMap&) const override;
85
86 void ValidateStaticConfig(const ComponentConfig& static_config,
87 ValidationMode validation_condition) const override;
88};
89
90template <typename Component>
91class CustomNameComponentAdder final : public ComponentAdderBase {
92 public:
93 CustomNameComponentAdder(std::string name);
94
95 void operator()(Manager&,
96 const components::ComponentConfigMap&) const override;
97
98 void ValidateStaticConfig(const ComponentConfig& static_config,
99 ValidationMode validation_condition) const override;
100};
101
102} // namespace impl
103
104template <typename Component>
105ComponentList& ComponentList::Append() & {
106 static_assert(std::is_base_of_v<impl::ComponentBase, Component>,
107 "Either you are trying to register a non-component, or the "
108 "component definition is not visible at its registration");
109 auto adder = std::make_unique<impl::DefaultComponentAdder<Component>>();
110 component_names_.insert(adder->GetComponentName());
111 adders_.push_back(std::move(adder));
112 return *this;
113}
114
115template <typename Component>
116ComponentList& ComponentList::Append(std::string name) & {
117 static_assert(std::is_base_of_v<impl::ComponentBase, Component>,
118 "Either you are trying to register a non-component, or the "
119 "component definition is not visible at its registration");
120 auto adder = std::make_unique<impl::CustomNameComponentAdder<Component>>(
121 std::move(name));
122 component_names_.insert(adder->GetComponentName());
123 adders_.push_back(std::move(adder));
124 return *this;
125}
126
127template <typename Component, typename... Args>
128ComponentList&& ComponentList::Append(Args&&... args) && {
129 return std::move(Append<Component>(std::forward<Args>(args)...));
130}
131
132namespace impl {
133
134template <typename Component>
135DefaultComponentAdder<Component>::DefaultComponentAdder()
136 : ComponentAdderBase(std::string{Component::kName},
137 kConfigFileMode<Component>) {}
138
139template <typename Component>
140void DefaultComponentAdder<Component>::operator()(
141 Manager& manager, const components::ComponentConfigMap& config_map) const {
142 manager.AddComponent<Component>(config_map, GetComponentName());
143}
144
145template <typename Component>
146void DefaultComponentAdder<Component>::ValidateStaticConfig(
147 const ComponentConfig& static_config,
148 ValidationMode validation_condition) const {
149 TryValidateStaticConfig<Component>(static_config, validation_condition);
150}
151
152template <typename Component>
153CustomNameComponentAdder<Component>::CustomNameComponentAdder(std::string name)
154 : ComponentAdderBase(std::move(name), kConfigFileMode<Component>) {}
155
156template <typename Component>
157void CustomNameComponentAdder<Component>::operator()(
158 Manager& manager, const components::ComponentConfigMap& config_map) const {
159 manager.AddComponent<Component>(config_map, GetComponentName());
160}
161
162template <typename Component>
163void CustomNameComponentAdder<Component>::ValidateStaticConfig(
164 const ComponentConfig& static_config,
165 ValidationMode validation_condition) const {
166 TryValidateStaticConfig<Component>(static_config, validation_condition);
167}
168
169} // namespace impl
170} // namespace components
171
172USERVER_NAMESPACE_END