1
#pragma once
2

            
3
#include "source/common/upstream/upstream_impl.h"
4
#include "source/extensions/load_balancing_policies/common/load_balancer_impl.h"
5

            
6
namespace Envoy {
7
namespace Extensions {
8
namespace Clusters {
9
namespace Composite {
10

            
11
// CompositeLoadBalancerContext wraps the original load balancer context to provide
12
// retry-aware cluster selection. It delegates most operations to the underlying
13
// context while tracking the selected cluster index for debugging purposes.
14
class CompositeLoadBalancerContext : public Upstream::LoadBalancerContextBase {
15
public:
16
  CompositeLoadBalancerContext(Upstream::LoadBalancerContext* context,
17
                               size_t selected_cluster_index)
18
19
      : selected_cluster_index_(selected_cluster_index) {
19
19
    if (context == nullptr) {
20
1
      owned_context_ = std::make_unique<Upstream::LoadBalancerContextBase>();
21
1
      context_ = owned_context_.get();
22
18
    } else {
23
18
      context_ = context;
24
18
    }
25
19
  }
26

            
27
  // Upstream::LoadBalancerContext - delegate all methods to the wrapped context.
28
2
  absl::optional<uint64_t> computeHashKey() override { return context_->computeHashKey(); }
29

            
30
2
  const Network::Connection* downstreamConnection() const override {
31
2
    return context_->downstreamConnection();
32
2
  }
33

            
34
1
  const Router::MetadataMatchCriteria* metadataMatchCriteria() override {
35
1
    return context_->metadataMatchCriteria();
36
1
  }
37

            
38
1
  const Http::RequestHeaderMap* downstreamHeaders() const override {
39
1
    return context_->downstreamHeaders();
40
1
  }
41

            
42
2
  StreamInfo::StreamInfo* requestStreamInfo() const override {
43
2
    return context_->requestStreamInfo();
44
2
  }
45

            
46
  const Upstream::HealthyAndDegradedLoad& determinePriorityLoad(
47
      const Upstream::PrioritySet& priority_set,
48
      const Upstream::HealthyAndDegradedLoad& original_priority_load,
49
13
      const Upstream::RetryPriority::PriorityMappingFunc& priority_mapping_func) override {
50
    // Delegate priority load determination to the wrapped context.
51
    // The selected cluster maintains its own priority handling.
52
13
    return context_->determinePriorityLoad(priority_set, original_priority_load,
53
13
                                           priority_mapping_func);
54
13
  }
55

            
56
14
  bool shouldSelectAnotherHost(const Upstream::Host& host) override {
57
14
    return context_->shouldSelectAnotherHost(host);
58
14
  }
59

            
60
14
  uint32_t hostSelectionRetryCount() const override { return context_->hostSelectionRetryCount(); }
61

            
62
1
  Network::Socket::OptionsSharedPtr upstreamSocketOptions() const override {
63
1
    return context_->upstreamSocketOptions();
64
1
  }
65

            
66
1
  Network::TransportSocketOptionsConstSharedPtr upstreamTransportSocketOptions() const override {
67
1
    return context_->upstreamTransportSocketOptions();
68
1
  }
69

            
70
1
  absl::optional<OverrideHost> overrideHostToSelect() const override {
71
1
    return context_->overrideHostToSelect();
72
1
  }
73

            
74
1
  void onAsyncHostSelection(Upstream::HostConstSharedPtr&& host, std::string&& details) override {
75
1
    context_->onAsyncHostSelection(std::move(host), std::move(details));
76
1
  }
77

            
78
1
  void setHeadersModifier(std::function<void(Http::ResponseHeaderMap&)> modifier) override {
79
1
    context_->setHeadersModifier(std::move(modifier));
80
1
  }
81

            
82
  // Get the selected cluster index for this request.
83
2
  size_t selectedClusterIndex() const { return selected_cluster_index_; }
84

            
85
private:
86
  std::unique_ptr<Upstream::LoadBalancerContext> owned_context_;
87
  Upstream::LoadBalancerContext* context_{nullptr};
88
  const size_t selected_cluster_index_;
89
};
90

            
91
} // namespace Composite
92
} // namespace Clusters
93
} // namespace Extensions
94
} // namespace Envoy