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 {
* overflow due to the recursive nature of the retry implementation
*/
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);
namespace detail {
......@@ -269,6 +272,14 @@ retryingPolicyCappedJitteredExponentialBackoff(
} // 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>
auto retrying(Policy&& p, FF&& ff) {
using tag = typename detail::retrying_policy_traits<Policy>::tag;
......
......@@ -80,6 +80,17 @@ TEST(RetryingTest, basic) {
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) {
struct ReturnedException : exception {};
struct ThrownException : exception {};
......@@ -101,6 +112,27 @@ TEST(RetryingTest, future_factory_throws) {
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) {
struct eggs : exception {};
auto r = futures::retrying(
......@@ -109,6 +141,14 @@ TEST(RetryingTest, policy_throws) {
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) {
atomic<size_t> sleeps{0};
auto r =
......@@ -127,6 +167,24 @@ TEST(RetryingTest, policy_future) {
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) {
atomic<size_t> sleeps{0};
auto r = futures::retrying(
......@@ -155,6 +213,17 @@ TEST(RetryingTest, policy_basic) {
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) {
auto r = futures::retrying(
futures::retryingPolicyBasic(3),
......@@ -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) {
using namespace futures::detail;
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