Commit e5bb59b3 authored by Lee Howes's avatar Lee Howes Committed by Facebook GitHub Bot

Add retryingUnsafe

Summary: Add retryingUnsafe as a duplicate of retrying that forces the return type to be a Future rather than a SemiFuture.

Reviewed By: yfeldblum

Differential Revision: D24707194

fbshipit-source-id: cb2a107f51d4d4dd47a41ce6f8a009c4d82e3138
parent cfa6e9c6
...@@ -67,6 +67,9 @@ namespace futures { ...@@ -67,6 +67,9 @@ namespace futures {
* overflow due to the recursive nature of the retry implementation * overflow due to the recursive nature of the retry implementation
*/ */
template <class Policy, class FF> template <class Policy, class FF>
Future<typename isFutureOrSemiFuture<invoke_result_t<FF, size_t>>::Inner>
retryingUnsafe(Policy&& p, FF&& ff);
template <class Policy, class FF>
auto retrying(Policy&& p, FF&& ff); auto retrying(Policy&& p, FF&& ff);
namespace detail { namespace detail {
...@@ -269,6 +272,14 @@ retryingPolicyCappedJitteredExponentialBackoff( ...@@ -269,6 +272,14 @@ retryingPolicyCappedJitteredExponentialBackoff(
} // namespace detail } // namespace detail
template <class Policy, class FF>
Future<typename isFutureOrSemiFuture<invoke_result_t<FF, size_t>>::Inner>
retryingUnsafe(Policy&& p, FF&& ff) {
using tag = typename detail::retrying_policy_traits<Policy>::tag;
return detail::retrying(
static_cast<Policy&&>(p), static_cast<FF&&>(ff), tag());
}
template <class Policy, class FF> template <class Policy, class FF>
auto retrying(Policy&& p, FF&& ff) { auto retrying(Policy&& p, FF&& ff) {
using tag = typename detail::retrying_policy_traits<Policy>::tag; using tag = typename detail::retrying_policy_traits<Policy>::tag;
......
...@@ -80,6 +80,17 @@ TEST(RetryingTest, basic) { ...@@ -80,6 +80,17 @@ TEST(RetryingTest, basic) {
EXPECT_EQ(2, r.value()); EXPECT_EQ(2, r.value());
} }
TEST(RetryingTest, basic_unsafe) {
auto r = futures::retryingUnsafe(
[](size_t n, const exception_wrapper&) { return n < 3; },
[](size_t n) {
return n < 2 ? makeFuture<size_t>(runtime_error("ha"))
: makeFuture(n);
})
.wait();
EXPECT_EQ(2, r.value());
}
TEST(RetryingTest, future_factory_throws) { TEST(RetryingTest, future_factory_throws) {
struct ReturnedException : exception {}; struct ReturnedException : exception {};
struct ThrownException : exception {}; struct ThrownException : exception {};
...@@ -101,6 +112,27 @@ TEST(RetryingTest, future_factory_throws) { ...@@ -101,6 +112,27 @@ TEST(RetryingTest, future_factory_throws) {
EXPECT_THROW(result.throwIfFailed(), ThrownException); EXPECT_THROW(result.throwIfFailed(), ThrownException);
} }
TEST(RetryingTest, future_factory_throws_unsafe) {
struct ReturnedException : exception {};
struct ThrownException : exception {};
auto result = futures::retryingUnsafe(
[](size_t n, const exception_wrapper&) { return n < 2; },
[](size_t n) {
switch (n) {
case 0:
return makeFuture<size_t>(
make_exception_wrapper<ReturnedException>());
case 1:
throw ThrownException();
default:
return makeFuture(n);
}
})
.wait()
.result();
EXPECT_THROW(result.throwIfFailed(), ThrownException);
}
TEST(RetryingTest, policy_throws) { TEST(RetryingTest, policy_throws) {
struct eggs : exception {}; struct eggs : exception {};
auto r = futures::retrying( auto r = futures::retrying(
...@@ -109,6 +141,14 @@ TEST(RetryingTest, policy_throws) { ...@@ -109,6 +141,14 @@ TEST(RetryingTest, policy_throws) {
EXPECT_THROW(std::move(r).get(), eggs); EXPECT_THROW(std::move(r).get(), eggs);
} }
TEST(RetryingTest, policy_throws_unsafe) {
struct eggs : exception {};
auto r = futures::retryingUnsafe(
[](size_t, exception_wrapper) -> bool { throw eggs(); },
[](size_t) -> Future<size_t> { throw std::runtime_error("ha"); });
EXPECT_THROW(std::move(r).get(), eggs);
}
TEST(RetryingTest, policy_future) { TEST(RetryingTest, policy_future) {
atomic<size_t> sleeps{0}; atomic<size_t> sleeps{0};
auto r = auto r =
...@@ -127,6 +167,24 @@ TEST(RetryingTest, policy_future) { ...@@ -127,6 +167,24 @@ TEST(RetryingTest, policy_future) {
EXPECT_EQ(2, sleeps); EXPECT_EQ(2, sleeps);
} }
TEST(RetryingTest, policy_future_unsafe) {
atomic<size_t> sleeps{0};
auto r =
futures::retryingUnsafe(
[&](size_t n, const exception_wrapper&) {
return n < 3
? makeFuture(++sleeps).thenValue([](auto&&) { return true; })
: makeFuture(false);
},
[](size_t n) {
return n < 2 ? makeFuture<size_t>(runtime_error("ha"))
: makeFuture(n);
})
.wait();
EXPECT_EQ(2, r.value());
EXPECT_EQ(2, sleeps);
}
TEST(RetryingTest, policy_semi_future) { TEST(RetryingTest, policy_semi_future) {
atomic<size_t> sleeps{0}; atomic<size_t> sleeps{0};
auto r = futures::retrying( auto r = futures::retrying(
...@@ -155,6 +213,17 @@ TEST(RetryingTest, policy_basic) { ...@@ -155,6 +213,17 @@ TEST(RetryingTest, policy_basic) {
EXPECT_EQ(2, r.value()); EXPECT_EQ(2, r.value());
} }
TEST(RetryingTest, policy_basic_unsafe) {
auto r = futures::retryingUnsafe(
futures::retryingPolicyBasic(3),
[](size_t n) {
return n < 2 ? makeFuture<size_t>(runtime_error("ha"))
: makeFuture(n);
})
.wait();
EXPECT_EQ(2, r.value());
}
TEST(RetryingTest, semifuture_policy_basic) { TEST(RetryingTest, semifuture_policy_basic) {
auto r = futures::retrying( auto r = futures::retrying(
futures::retryingPolicyBasic(3), futures::retryingPolicyBasic(3),
...@@ -186,6 +255,26 @@ TEST(RetryingTest, policy_capped_jittered_exponential_backoff) { ...@@ -186,6 +255,26 @@ TEST(RetryingTest, policy_capped_jittered_exponential_backoff) {
}); });
} }
TEST(RetryingTest, policy_capped_jittered_exponential_backoff_unsafe) {
multiAttemptExpectDurationWithin(5, milliseconds(200), milliseconds(400), [] {
using ms = milliseconds;
auto r = futures::retryingUnsafe(
futures::retryingPolicyCappedJitteredExponentialBackoff(
3,
ms(100),
ms(1000),
0.1,
mt19937_64(0),
[](size_t, const exception_wrapper&) { return true; }),
[](size_t n) {
return n < 2 ? makeFuture<size_t>(runtime_error("ha"))
: makeFuture(n);
})
.wait();
EXPECT_EQ(2, r.value());
});
}
TEST(RetryingTest, policy_capped_jittered_exponential_backoff_many_retries) { TEST(RetryingTest, policy_capped_jittered_exponential_backoff_many_retries) {
using namespace futures::detail; using namespace futures::detail;
mt19937_64 rng(0); mt19937_64 rng(0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment