YOrch 1.0.0
Loading...
Searching...
No Matches
retry.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "concepts.hpp" // IWYU pragma: keep
4#include "../detail/task_adapters/result_helpers.hpp"
5
6namespace yorch {
7
17 std::size_t max_retries = 0;
18
19 [[nodiscard]] constexpr bool should_retry(std::size_t retry_count) const noexcept {
20 return retry_count < max_retries;
21 }
22
23 template <typename Raw>
24 [[nodiscard]] static constexpr auto on_exhausted(Raw&& raw) noexcept {
25 return detail::retry_exhausted_as_failure(std::forward<Raw>(raw));
26 }
27};
28
34 std::size_t max_retries = 0;
35
36 [[nodiscard]] constexpr bool should_retry(std::size_t retry_count) const noexcept {
37 return retry_count < max_retries;
38 }
39
40 template <typename Raw>
41 [[nodiscard]] static constexpr std::remove_cvref_t<Raw> on_exhausted(Raw&& raw) noexcept {
42 return std::forward<Raw>(raw);
43 }
44};
45
50 [[nodiscard]] static constexpr bool should_retry(std::size_t) noexcept {
51 return true;
52 }
53};
54
67template <typename Task, typename Policy>
72 Task task;
73 Policy policy;
74
75 constexpr retry_task(Task&& stored_task, Policy&& stored_policy)
76 noexcept(std::is_nothrow_move_constructible_v<Task> &&
77 std::is_nothrow_move_constructible_v<Policy>)
78 : task(std::move(stored_task)),
79 policy(std::move(stored_policy)) {}
80
81 constexpr retry_task(const Task& stored_task, const Policy& stored_policy)
82 noexcept(std::is_nothrow_copy_constructible_v<Task> &&
83 std::is_nothrow_copy_constructible_v<Policy>)
84 : task(stored_task),
85 policy(stored_policy) {}
86
100 template <typename Ctx, typename Prev>
102 constexpr decltype(auto) invoke_raw(exec_context<Ctx, Prev>& ec)
103 noexcept(noexcept(task.invoke_raw(ec)) &&
104 noexcept(policy.should_retry(std::size_t {})) &&
106 policy,
107 std::declval<std::remove_cvref_t<detail::raw_task_result_t<Task&, Ctx, Prev>>>()))) {
109 using raw_value_t = std::remove_cvref_t<raw_result_t>;
110
112 "Wrapped task raw_result_type must match invoke_raw(exec_context<...>&) return type");
113
115 return task.invoke_raw(ec);
116 } else {
117 static_assert(!std::is_reference_v<raw_result_t>,
118 "with_retry(...) does not support retry-capable reference raw results");
119
120 std::size_t retry_count = 0;
121
122 while (true) {
123 raw_value_t raw = task.invoke_raw(ec);
124
126 return raw;
127 }
128
129 if (!policy.should_retry(retry_count)) {
130 return detail::handle_retry_exhausted(policy, std::move(raw));
131 }
132
133 ++retry_count;
134 }
135 }
136 }
137
138 template <typename Ctx, typename Prev, typename U = Task>
139 requires direct_output_task<U, Ctx, Prev> && retry_policy<Policy>
143 noexcept(task.invoke_into(ec, out)) &&
144 noexcept(policy.should_retry(std::size_t {})) &&
146 policy,
147 step_result::retry()))) {
148 std::size_t retry_count = 0;
149
150 while (true) {
151 const auto step = task.invoke_into(ec, out);
152
153 if (step.status != step_status::retry) {
154 return step;
155 }
156
157 if (!policy.should_retry(retry_count)) {
158 return detail::handle_retry_exhausted(policy, step);
159 }
160
161 // if the task requested retry, it should not have produced an output value, but just in case, destroy it before the next attempt to avoid leaking resources or causing double-destruction on the next success
162 if (out.has_value()) {
163 out.destroy();
164 }
165
166 ++retry_count;
167 }
168 }
169};
170
184template <typename Task, typename Policy>
185 requires retry_policy<std::decay_t<Policy>>
186constexpr auto with_retry(Task&& task, Policy&& policy) {
187 return retry_task<
188 std::decay_t<Task>,
189 std::decay_t<Policy>
190 >{
191 std::forward<Task>(task),
192 std::forward<Policy>(policy)
193 };
194}
195
196} // namespace yorch
Reports whether a task object exposes the raw execution protocol for a concrete exec_context.
Definition concepts.hpp:21
Reports whether a retry policy exposes the minimal protocol required by with_retry(....
Definition concepts.hpp:83
constexpr bool raw_result_requests_retry(const R &r) noexcept
typename declared_task_output< Task >::type declared_task_output_t
Definition traits.hpp:41
decltype(std::declval< Task >().invoke_raw(std::declval< exec_context< Ctx, Prev > & >())) raw_task_result_t
Definition traits.hpp:16
constexpr auto retry_exhausted_as_failure(const Raw &raw) noexcept
constexpr auto handle_retry_exhausted(const Policy &policy, Raw &&raw) noexcept
constexpr bool is_adapter_descriptor_v
Definition adapters.hpp:63
constexpr auto with_retry(Task &&task, Policy &&policy)
Wraps a task so retry results are handled by a user retry policy.
Definition retry.hpp:186
constexpr auto task(F &&f)
Definition core.hpp:207
Output sink passed to direct-output tasks.
Lightweight borrowed view used during execution.
Definition context.hpp:187
Retry policy that allows a fixed number of retries and then preserves the final retry result unchange...
Definition retry.hpp:33
constexpr bool should_retry(std::size_t retry_count) const noexcept
Definition retry.hpp:36
static constexpr std::remove_cvref_t< Raw > on_exhausted(Raw &&raw) noexcept
Definition retry.hpp:41
Retry policy that allows a fixed number of additional retries.
Definition retry.hpp:16
static constexpr auto on_exhausted(Raw &&raw) noexcept
Definition retry.hpp:24
constexpr bool should_retry(std::size_t retry_count) const noexcept
Definition retry.hpp:19
std::size_t max_retries
Definition retry.hpp:17
Retry policy that keeps retrying for as long as the task requests it.
Definition retry.hpp:49
static constexpr bool should_retry(std::size_t) noexcept
Definition retry.hpp:50
Retry adapter that re-invokes a task when it returns retry.
Definition retry.hpp:71
constexpr decltype(auto) invoke_raw(exec_context< Ctx, Prev > &ec) noexcept(noexcept(task.invoke_raw(ec)) &&noexcept(policy.should_retry(std::size_t {})) &&noexcept(detail::handle_retry_exhausted(policy, std::declval< std::remove_cvref_t< detail::raw_task_result_t< Task &, Ctx, Prev > > >())))
Executes the wrapped task and re-runs it while policy permits.
Definition retry.hpp:102
constexpr retry_task(Task &&stored_task, Policy &&stored_policy) noexcept(std::is_nothrow_move_constructible_v< Task > &&std::is_nothrow_move_constructible_v< Policy >)
Definition retry.hpp:75
constexpr retry_task(const Task &stored_task, const Policy &stored_policy) noexcept(std::is_nothrow_copy_constructible_v< Task > &&std::is_nothrow_copy_constructible_v< Policy >)
Definition retry.hpp:81
constexpr step_result invoke_into(exec_context< Ctx, Prev > &ec, direct_out< detail::declared_task_output_t< U > > out) noexcept(noexcept(task.invoke_into(ec, out)) &&noexcept(policy.should_retry(std::size_t {})) &&noexcept(detail::handle_retry_exhausted(policy, step_result::retry())))
Definition retry.hpp:140
Represents the basic outcome of a task step.
Definition result.hpp:42
static constexpr step_result retry() noexcept
Creates a retry result.
Definition result.hpp:56