userver: userver/components/state.hpp Source File
Loading...
Searching...
No Matches
state.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/components/state.hpp
4/// @brief @copybrief components::State
5
6#include <string_view>
7#include <unordered_set>
8#include <vector>
9
10USERVER_NAMESPACE_BEGIN
11
12namespace components {
13
14class ComponentContext;
15
16enum class ComponentHealth;
17
18namespace impl {
19class ComponentContextImpl;
20}
21
22// clang-format off
23/// @brief All components pass through these stages during the service lifetime.
24/// @see @ref scripts/docs/en/userver/component_system.md
25///
26/// @dot
27/// digraph ServiceLifetimeStages {
28/// rankdir=TB;
29/// nodesep=0.4;
30/// ranksep=0.5;
31/// node [shape=box, fontsize=11];
32/// edge [fontsize=10];
33///
34/// kLoading [group=states, width=4.75, label=< <B>kLoading</B><BR/><FONT POINT-SIZE="5">&nbsp;</FONT><BR/>Components are constructed. >];
35/// kOnAllComponentsLoadedIsRunning [group=states, width=4.75, label=< <B>kOnAllComponentsLoadedIsRunning</B><BR/><FONT POINT-SIZE="5">&nbsp;</FONT><BR/>OnAllComponentsLoaded is called. >];
36/// kRunning [group=states, width=4.75, label=< <B>kRunning</B><BR/><FONT POINT-SIZE="5">&nbsp;</FONT><BR/>All components loaded successfully.<BR/>Service is fully operational. >];
37/// GracefulShutdownDecision [shape=diamond, label="Graceful\nshutdown?"];
38/// kGracefulShutdown [group=states, width=4.75, label=< <B>kGracefulShutdown</B><BR/><FONT POINT-SIZE="5">&nbsp;</FONT><BR/>Waits for<BR/>graceful_shutdown_continue_accepting_requests_interval.<BR/>Then OnGracefulShutdown is called. >];
39/// kOnAllComponentsAreStoppingIsRunning [group=states, width=4.75, label=< <B>kOnAllComponentsAreStoppingIsRunning</B><BR/><FONT POINT-SIZE="5">&nbsp;</FONT><BR/>OnAllComponentsAreStopping is called.<BR/>Hooks run in reverse-dependency order. >];
40/// kStopping [group=states, width=4.75, label=< <B>kStopping</B><BR/><FONT POINT-SIZE="5">&nbsp;</FONT><BR/>Components are destroyed.<BR/>Destructors run in reverse-dependency order. >];
41///
42/// exc1Top [shape=none, width=0.01, height=0.01, group=exc1, label=""];
43/// exc1Run [shape=none, width=0.01, height=0.01, group=exc1, label=""];
44/// exc1Bot [shape=none, width=0.01, height=0.01, group=exc1, label=""];
45/// exc2Top [shape=none, width=0.01, height=0.01, group=exc2, label=""];
46/// exc2Bot [shape=none, width=0.01, height=0.01, group=exc2, label=""];
47///
48/// kLoading -> kOnAllComponentsLoadedIsRunning [weight=100];
49/// kOnAllComponentsLoadedIsRunning -> kRunning [weight=100];
50/// kRunning -> kGracefulShutdown [penwidth=0, arrowhead=none, weight=100];
51/// kGracefulShutdown -> kOnAllComponentsAreStoppingIsRunning [weight=100];
52/// kOnAllComponentsAreStoppingIsRunning -> kStopping [weight=100];
53/// kRunning:e -> GracefulShutdownDecision:n [label="Received SIGINT\nor SIGTERM"];
54/// {rank=same; kGracefulShutdown; GracefulShutdownDecision}
55/// kGracefulShutdown -> GracefulShutdownDecision [penwidth=0, arrowhead=none, weight=10];
56/// GracefulShutdownDecision -> kGracefulShutdown [label="yes", constraint=false];
57/// GracefulShutdownDecision -> kOnAllComponentsAreStoppingIsRunning [label="no", constraint=false];
58///
59/// {rank=same; exc1Top; kOnAllComponentsLoadedIsRunning}
60/// {rank=same; exc1Run; exc2Top; kRunning}
61/// {rank=same; exc1Bot; exc2Bot; kGracefulShutdown}
62/// exc1Top -> kOnAllComponentsLoadedIsRunning [penwidth=0, arrowhead=none, weight=50];
63/// exc1Run -> exc2Top [penwidth=0, arrowhead=none, weight=40];
64/// exc2Top -> kRunning [penwidth=0, arrowhead=none, weight=50];
65/// exc1Bot -> exc2Bot [penwidth=0, arrowhead=none, weight=40];
66/// exc2Bot -> kGracefulShutdown [penwidth=0, arrowhead=none, weight=50];
67///
68/// kLoading -> exc1Top [arrowhead=none];
69/// exc1Top -> exc1Run [arrowhead=none, label="Exception during\nconstruction"];
70/// exc1Run -> exc1Bot [arrowhead=none];
71/// exc1Bot -> kOnAllComponentsAreStoppingIsRunning;
72/// kOnAllComponentsLoadedIsRunning -> exc2Top [arrowhead=none];
73/// exc2Top -> exc2Bot [arrowhead=none, label="OnAllComponentsLoaded\nthrows"];
74/// exc2Bot -> kOnAllComponentsAreStoppingIsRunning;
75/// }
76/// @enddot
77// clang-format on
79 /// Constructors are running for all registered components. Components can depend on each other at this stage
80 /// by calling @ref components::ComponentContext::FindComponent and friends.
81 ///
82 /// If any component throws an exception, then the service transitions
83 /// into @ref ServiceLifetimeStage::kOnAllComponentsAreStoppingIsRunning stage.
85
86 /// @ref components::ComponentBase::OnAllComponentsLoaded (noop by default) is running for all components.
87 /// This stage starts after constructors for all components have completed without an exception.
88 ///
89 /// The order of `OnAllComponentsLoaded` hooks invocations respects the order of components defined
90 /// at @ref ServiceLifetimeStage::kLoading stage.
92
93 /// This stage marks that all `OnAllComponentsLoaded` hooks (as described
94 /// in @ref ServiceLifetimeStage::kOnAllComponentsLoadedIsRunning) have completed
95 /// successfully (without an exception). At this point the service is fully running.
96 ///
97 /// This stage ends once the service receives a shutdown signal (`SIGINT` or `SIGTERM`).
99
100 /// The service performs a graceful shutdown if either `graceful_shutdown_continue_accepting_requests_interval`
101 /// or `graceful_shutdown_pending_requests_completion_interval` is non-zero.
102 /// First, it waits for `graceful_shutdown_pending_requests_completion_interval` unless the interval is zero.
103 /// Second, it stops accepting new requests and continues processing of already running requests for
104 /// `graceful_shutdown_pending_requests_completion_interval` unless the interval is zero.
105 /// Then the normal shutdown procedure continues in @ref ServiceLifetimeStage::kOnAllComponentsAreStoppingIsRunning.
106 ///
107 /// @see @ref scripts/docs/en/userver/graceful_shutdown.md
108 /// @see @ref components::ManagerControllerComponent
109 ///
110 /// Example:
111 /// @snippet core/functional_tests/graceful_shutdown/static_config.yaml graceful_shutdown_settings
113
114 /// @ref components::ComponentBase::OnAllComponentsAreStopping (noop by default) is running for all components.
115 /// This stage starts once the service has received a shutdown signal (see @ref ServiceLifetimeStage::kRunning) and
116 /// @ref ServiceLifetimeStage::kGracefulShutdown stage (if any) has completed.
117 ///
118 /// If an error occurs during service startup, then `OnAllComponentsAreStopping` runs after
119 /// @ref components::ComponentBase::OnLoadingCancelled for all constructed components.
120 ///
121 /// The order of `OnAllComponentsAreStopping` hooks invocations respects the order of components defined
122 /// at @ref ServiceLifetimeStage::kLoading stage (they run in the reverse-dependency order).
124
125 /// Destructors are running for all components. This stage starts once
126 /// @ref ServiceLifetimeStage::kOnAllComponentsAreStoppingIsRunning stage.
127 ///
128 /// If an error occurs during service startup, then destructors run
129 /// after @ref ServiceLifetimeStage::kOnAllComponentsAreStoppingIsRunning for all constructed components.
130 ///
131 /// The order of destructor invocations respects the order of components defined
132 /// at @ref ServiceLifetimeStage::kLoading stage (they run in the reverse-dependency order).
134};
135
136/// Converts a @ref components::ServiceLifetimeStage to debug string for logging.
138
139/// A view of the components' state that is usable after the components are
140/// constructed and until all the components are destroyed.
141///
142/// @see components::ComponentContext
143class State final {
144public:
145 /// Component name together with its current health.
147 std::string_view name;
148 ComponentHealth health;
149 };
150
151 explicit State(const ComponentContext& cc) noexcept;
152
153 /// @returns true if one of the components is in fatal state and can not
154 /// work. A component is in fatal state if the
155 /// components::ComponentHealth::kFatal value is returned from the overridden
156 /// components::ComponentBase::GetComponentHealth().
158
159 /// @returns all components that are not in
160 /// components::ComponentHealth::kOk state.
161 ///
162 /// Components construction should finish before any call to this function
163 /// is made. The result should not outlive the components destruction.
165
166 /// @returns the current service lifetime stage.
167 /// @see @ref components::ServiceLifetimeStage
169
170 /// @returns true if the service is being shut down gracefully.
172
173 /// @returns true if component with name `component_name` depends
174 /// (directly or transitively) on a component with name `dependency`.
175 ///
176 /// Component with name `component_name` should be loaded.
177 /// Components construction should finish before any call to this function
178 /// is made.
179 ///
180 /// Note that GetAllDependencies usually is more effective, if you are
181 /// planning multiple calls for the same component name.
182 bool HasDependencyOn(std::string_view component_name, std::string_view dependency) const;
183
184 /// @returns all the components that `component_name` depends on directly or
185 /// transitively.
186 ///
187 /// Component with name `component_name` should be loaded.
188 /// Components construction should finish before any call to this function
189 /// is made. The result should now outlive the all the components
190 /// destruction.
191 std::unordered_set<std::string_view> GetAllDependencies(std::string_view component_name) const;
192
193private:
194 const impl::ComponentContextImpl& impl_;
195};
196
197} // namespace components
198
199USERVER_NAMESPACE_END