13#include <userver/compiler/demangle.hpp>
14#include <userver/components/component_fwd.hpp>
15#include <userver/components/raw_component_base.hpp>
16#include <userver/engine/task/task_processor_fwd.hpp>
18USERVER_NAMESPACE_BEGIN
20namespace engine::impl {
27class ComponentContext;
31enum class ComponentLifetimeStage;
33class ComponentContextImpl;
35using ComponentFactory =
36 std::function<std::unique_ptr<components::RawComponentBase>(
const components::ComponentContext&)>;
39constexpr auto NameFromComponentType() ->
decltype(std::string_view{T::kName}) {
43template <
class T,
class... Args>
44constexpr auto NameFromComponentType(Args...) {
47 "Component does not have a 'kName' member convertible to "
48 "std::string_view. You have to explicitly specify the name: "
49 "context.FindComponent<T>(name) or "
50 "context.FindComponentOptional<T>(name)."
52 return std::string_view{};
61 ComponentsLoadCancelledException();
62 explicit ComponentsLoadCancelledException(
const std::string& message);
74class ComponentContext
final {
89 return FindComponent<T>(impl::NameFromComponentType<T>());
94 T& FindComponent(std::string_view name)
const {
95 if (!Contains(name)) {
96 ThrowNonRegisteredComponent(name, compiler::GetTypeName<T>());
99 auto* component_base = DoFindComponent(name);
100 T* ptr =
dynamic_cast<T*>(component_base);
102 ThrowComponentTypeMismatch(name, compiler::GetTypeName<T>(), component_base);
108 template <
typename T>
109 T& FindComponent(std::string_view = {}) {
110 return ReportMisuse<T>();
115 template <
typename T>
117 return FindComponentOptional<T>(impl::NameFromComponentType<T>());
121 template <
typename T>
122 T* FindComponentOptional(std::string_view name)
const {
123 if (!Contains(name)) {
126 return dynamic_cast<T*>(DoFindComponent(name));
129 template <
typename T>
130 T& FindComponentOptional(std::string_view = {}) {
131 return ReportMisuse<T>();
137 template <
typename T>
138 engine::TaskProcessor& GetTaskProcessor(
const T&) {
139 return ReportMisuse<T>();
142 const Manager& GetManager()
const;
147 bool Contains(std::string_view name)
const noexcept;
149 template <
typename T>
150 bool Contains(
const T&) {
151 return ReportMisuse<T>();
155 decltype(
auto) ReportMisuse() {
158 "components::ComponentContext should be accepted by "
159 "a constant reference, i.e. "
160 "`MyComponent(const components::ComponentConfig& config, "
161 "const components::ComponentContext& context)`"
166 friend class Manager;
169 ComponentContext()
noexcept;
171 void Emplace(
const Manager& manager, std::vector<std::string>&& loading_component_names);
173 void Reset()
noexcept;
177 RawComponentBase* AddComponent(std::string_view name,
const impl::ComponentFactory& factory);
179 void OnAllComponentsLoaded();
181 void OnGracefulShutdownStarted();
183 void OnAllComponentsAreStopping();
185 void ClearComponents();
187 void CancelComponentsLoad();
189 [[noreturn]]
void ThrowNonRegisteredComponent(std::string_view name, std::string_view type)
const;
191 ThrowComponentTypeMismatch(std::string_view name, std::string_view type,
RawComponentBase* component)
const;
195 std::unique_ptr<impl::ComponentContextImpl> impl_;