1
#pragma once
2

            
3
#include "envoy/config/typed_config.h"
4
#include "envoy/singleton/manager.h"
5
#include "envoy/stream_info/stream_info.h"
6
#include "envoy/upstream/types.h"
7
#include "envoy/upstream/upstream.h"
8

            
9
namespace Envoy {
10
namespace Upstream {
11

            
12
/**
13
 * Used to optionally modify the PriorityLoad when selecting a priority for
14
 * a retry attempt.
15
 *
16
 * Each RetryPriority will live throughout the lifetime of a request and updated
17
 * with attempted hosts through onHostAttempted.
18
 */
19
class RetryPriority {
20
public:
21
26
  virtual ~RetryPriority() = default;
22

            
23
  /**
24
   * Function that maps a HostDescription to it's effective priority level in a cluster.
25
   * For most cluster types, the mapping is simply `return host.priority()`, but some
26
   * cluster types require more complex mapping.
27
   * @return either the effective priority, or absl::nullopt if the mapping cannot be determined,
28
   *         which can happen if the host has been removed from the configurations since it was
29
   *         used.
30
   */
31
  using PriorityMappingFunc =
32
      std::function<absl::optional<uint32_t>(const Upstream::HostDescription&)>;
33

            
34
24
  static absl::optional<uint32_t> defaultPriorityMapping(const Upstream::HostDescription& host) {
35
24
    return host.priority();
36
24
  }
37

            
38
  /**
39
   * Determines what PriorityLoad to use.
40
   *
41
   * @param stream_info request stream information.
42
   * @param priority_set current priority set of cluster.
43
   * @param original_priority_load the unmodified HealthAndDegradedLoad.
44
   * @param priority_mapping_func a callback to get the priority of a host that has
45
   *        been attempted. This function may only be called on hosts that were
46
   *        passed to calls to `onHostAttempted()` on this object.
47
   * @return HealthAndDegradedLoad load that should be used for the next retry. Return
48
   * original_priority_load if the original load should be used. a pointer to original_priority,
49
   * original_degraded_priority if no changes should be made.
50
   */
51
  virtual const HealthyAndDegradedLoad&
52
  determinePriorityLoad(StreamInfo::StreamInfo* stream_info, const PrioritySet& priority_set,
53
                        const HealthyAndDegradedLoad& original_priority_load,
54
                        const PriorityMappingFunc& priority_mapping_func) PURE;
55

            
56
  /**
57
   * Called after a host has been attempted but before host selection for the next attempt has
58
   * begun.
59
   *
60
   * @param attempted_host the host that was previously attempted.
61
   */
62
  virtual void onHostAttempted(HostDescriptionConstSharedPtr attempted_host) PURE;
63
};
64

            
65
using RetryPrioritySharedPtr = std::shared_ptr<RetryPriority>;
66

            
67
/**
68
 * Used to decide whether a selected host should be rejected during retries. Host selection will be
69
 * reattempted until either the host predicate accepts the host or a configured max number of
70
 * attempts is reached.
71
 *
72
 * Each RetryHostPredicate will live throughout the lifetime of a request and updated
73
 * with attempted hosts through onHostAttempted.
74
 */
75
class RetryHostPredicate {
76
public:
77
16
  virtual ~RetryHostPredicate() = default;
78

            
79
  /**
80
   * Determines whether a host should be rejected during host selection.
81
   *
82
   * @param candidate_host the host to either reject or accept.
83
   * @return whether the host should be rejected and host selection reattempted.
84
   */
85
  virtual bool shouldSelectAnotherHost(const Host& candidate_host) PURE;
86

            
87
  /**
88
   * Called after a host has been attempted but before host selection for the next attempt has
89
   * begun.
90
   *
91
   * @param attempted_host the host that was previously attempted.
92
   */
93
  virtual void onHostAttempted(HostDescriptionConstSharedPtr attempted_host) PURE;
94
};
95

            
96
using RetryHostPredicateSharedPtr = std::shared_ptr<RetryHostPredicate>;
97

            
98
/**
99
 * A predicate that is applied prior to retrying a request. Each predicate can customize request
100
 * behavior prior to the request being retried.
101
 */
102
class RetryOptionsPredicate {
103
public:
104
  struct UpdateOptionsParameters {
105
    // Stream info for the previous request attempt that is about to be retried.
106
    StreamInfo::StreamInfo& retriable_request_stream_info_;
107
    // The current upstream socket options that were used for connection pool selection on the
108
    // previous attempt, or the result of an updated set of options from a previously run
109
    // retry options predicate.
110
    Network::Socket::OptionsSharedPtr current_upstream_socket_options_;
111
  };
112

            
113
  struct UpdateOptionsReturn {
114
    // New upstream socket options to apply to the next request attempt. If changed, will affect
115
    // connection pool selection similar to that which was done for the initial request.
116
    absl::optional<Network::Socket::OptionsSharedPtr> new_upstream_socket_options_;
117
  };
118

            
119
5
  virtual ~RetryOptionsPredicate() = default;
120

            
121
  /**
122
   * Update request options.
123
   * @param parameters supplies the update parameters.
124
   * @return the new options to apply. Each option is wrapped in an optional and is only applied
125
   *         if valid.
126
   */
127
  virtual UpdateOptionsReturn updateOptions(const UpdateOptionsParameters& parameters) const PURE;
128
};
129

            
130
using RetryOptionsPredicateConstSharedPtr = std::shared_ptr<const RetryOptionsPredicate>;
131

            
132
/**
133
 * Context for all retry extensions.
134
 */
135
class RetryExtensionFactoryContext {
136
public:
137
  virtual ~RetryExtensionFactoryContext() = default;
138

            
139
  /**
140
   * @return Singleton::Manager& the server-wide singleton manager.
141
   */
142
  virtual Singleton::Manager& singletonManager() PURE;
143
};
144

            
145
/**
146
 * Factory for RetryPriority.
147
 */
148
class RetryPriorityFactory : public Config::TypedFactory {
149
public:
150
  virtual RetryPrioritySharedPtr
151
  createRetryPriority(const Protobuf::Message& config,
152
                      ProtobufMessage::ValidationVisitor& validation_visitor,
153
                      uint32_t retry_count) PURE;
154

            
155
18
  std::string category() const override { return "envoy.retry_priorities"; }
156
};
157

            
158
/**
159
 * Factory for RetryHostPredicate.
160
 */
161
class RetryHostPredicateFactory : public Config::TypedFactory {
162
public:
163
  virtual RetryHostPredicateSharedPtr createHostPredicate(const Protobuf::Message& config,
164
                                                          uint32_t retry_count) PURE;
165

            
166
76
  std::string category() const override { return "envoy.retry_host_predicates"; }
167
};
168

            
169
/**
170
 * Factory for RetryOptionsPredicate.
171
 */
172
class RetryOptionsPredicateFactory : public Config::TypedFactory {
173
public:
174
  virtual RetryOptionsPredicateConstSharedPtr
175
  createOptionsPredicate(const Protobuf::Message& config,
176
                         RetryExtensionFactoryContext& context) PURE;
177

            
178
2
  std::string category() const override { return "envoy.retry_options_predicates"; }
179
};
180

            
181
} // namespace Upstream
182
} // namespace Envoy