6#include <unordered_map>
8#include <userver/components/component_base.hpp>
9#include <userver/components/component_fwd.hpp>
10#include <userver/utils/meta_light.hpp>
11#include <userver/yaml_config/fwd.hpp>
13#include <userver/middlewares/impl/middleware_pipeline_config.hpp>
15USERVER_NAMESPACE_BEGIN
20namespace middlewares {
26enum class DependencyType {
34 std::string node_name{};
35 DependencyType type{DependencyType::kStrong};
38struct MiddlewareDependency
final {
39 std::string middleware_name{};
40 std::vector<Connect> befores{};
41 std::vector<Connect> afters{};
43 std::optional<std::string> group{};
46using Dependencies = std::unordered_map<std::string, MiddlewareDependency>;
48class MiddlewarePipeline
final {
50 explicit MiddlewarePipeline(Dependencies&& deps);
52 std::vector<std::string> GetPerServiceMiddlewares(
const MiddlewareRunnerConfig& config)
const;
54 const MiddlewareOrderedList& GetOrderedList()
const {
return pipeline_; }
58 MiddlewareOrderedList pipeline_{};
61template <
typename Group>
62std::string BeginOfGroup() {
63 return std::string{Group::kName} +
"#begin";
66template <
typename Group>
67std::string EndOfGroup() {
68 return std::string{Group::kName} +
"#end";
85 AnyMiddlewarePipelineComponent(
88 impl::BuiltInConfig&& builtin_config
95 const impl::MiddlewarePipeline& GetPipeline()
const;
99 impl::MiddlewarePipeline pipeline_;
110class MiddlewareDependencyBuilder
final {
113 MiddlewareDependencyBuilder() =
default;
115 MiddlewareDependencyBuilder(
const MiddlewareDependencyBuilder&) =
default;
116 MiddlewareDependencyBuilder(MiddlewareDependencyBuilder&&)
noexcept =
default;
117 MiddlewareDependencyBuilder& operator=(
const MiddlewareDependencyBuilder&) =
default;
118 MiddlewareDependencyBuilder& operator=(MiddlewareDependencyBuilder&&) =
default;
122 template <
typename MiddlewareBefore>
123 MiddlewareDependencyBuilder Before(DependencyType type = DependencyType::kStrong) &&;
128 MiddlewareDependencyBuilder Before(std::string_view before, DependencyType type = DependencyType::kStrong) &&;
132 template <
typename MiddlewareAfter>
133 MiddlewareDependencyBuilder After(DependencyType type = DependencyType::kStrong) &&;
138 MiddlewareDependencyBuilder After(std::string_view after, DependencyType type = DependencyType::kStrong) &&;
141 template <
typename Group>
142 MiddlewareDependencyBuilder InGroup() &&;
146 impl::MiddlewareDependency ExtractDependency(std::string_view middleware_name) &&;
147 impl::MiddlewareDependency ExtractGroupDependency(std::string_view group_name) &&;
151 void InUserGroupByDefault();
153 impl::MiddlewareDependency dep_{};
159using IsGroup =
decltype(T::kDependency);
162constexpr bool kIsGroup = std::is_same_v<meta::DetectedType<IsGroup, T>,
const MiddlewareDependencyBuilder>;
166template <
typename MiddlewareBefore>
167MiddlewareDependencyBuilder MiddlewareDependencyBuilder::Before(DependencyType type) && {
168 if constexpr (impl::kIsGroup<MiddlewareBefore>) {
169 return std::move(*
this).Before(impl::BeginOfGroup<MiddlewareBefore>(), type);
171 return std::move(*
this).Before(MiddlewareBefore::kName, type);
174template <
typename MiddlewareAfter>
175MiddlewareDependencyBuilder MiddlewareDependencyBuilder::After(DependencyType type) && {
176 if constexpr (impl::kIsGroup<MiddlewareAfter>) {
177 return std::move(*
this).After(impl::EndOfGroup<MiddlewareAfter>(), type);
179 return std::move(*
this).After(MiddlewareAfter::kName, type);
182template <
typename Group>
183MiddlewareDependencyBuilder MiddlewareDependencyBuilder::InGroup() && {
184 dep_.group = Group::kName;
185 dep_.afters.push_back(impl::Connect{impl::BeginOfGroup<Group>(), DependencyType::kStrong});
186 return std::move(*
this).Before(impl::EndOfGroup<Group>(), DependencyType::kWeak);