| Index: net/url_request/url_request_throttler_entry.cc
|
| diff --git a/net/url_request/url_request_throttler_entry.cc b/net/url_request/url_request_throttler_entry.cc
|
| index 033787bda2d8db2f46b6e8c5ad7668cd0e3e80a2..ddb337bb458402a2ee7cd2f477adce5701056a7e 100644
|
| --- a/net/url_request/url_request_throttler_entry.cc
|
| +++ b/net/url_request/url_request_throttler_entry.cc
|
| @@ -16,7 +16,6 @@ namespace net {
|
| const int URLRequestThrottlerEntry::kDefaultSlidingWindowPeriodMs = 2000;
|
| const int URLRequestThrottlerEntry::kDefaultMaxSendThreshold = 20;
|
| const int URLRequestThrottlerEntry::kDefaultInitialBackoffMs = 700;
|
| -const int URLRequestThrottlerEntry::kDefaultAdditionalConstantMs = 100;
|
| const double URLRequestThrottlerEntry::kDefaultMultiplyFactor = 1.4;
|
| const double URLRequestThrottlerEntry::kDefaultJitterFactor = 0.4;
|
| const int URLRequestThrottlerEntry::kDefaultMaximumBackoffMs = 60 * 60 * 1000;
|
| @@ -27,12 +26,7 @@ URLRequestThrottlerEntry::URLRequestThrottlerEntry()
|
| : sliding_window_period_(
|
| base::TimeDelta::FromMilliseconds(kDefaultSlidingWindowPeriodMs)),
|
| max_send_threshold_(kDefaultMaxSendThreshold),
|
| - initial_backoff_ms_(kDefaultInitialBackoffMs),
|
| - additional_constant_ms_(kDefaultAdditionalConstantMs),
|
| - multiply_factor_(kDefaultMultiplyFactor),
|
| - jitter_factor_(kDefaultJitterFactor),
|
| - maximum_backoff_ms_(kDefaultMaximumBackoffMs),
|
| - entry_lifetime_ms_(kDefaultEntryLifetimeMs) {
|
| + backoff_entry_(&backoff_policy_) {
|
| Initialize();
|
| }
|
|
|
| @@ -40,77 +34,47 @@ URLRequestThrottlerEntry::URLRequestThrottlerEntry(
|
| int sliding_window_period_ms,
|
| int max_send_threshold,
|
| int initial_backoff_ms,
|
| - int additional_constant_ms,
|
| double multiply_factor,
|
| double jitter_factor,
|
| int maximum_backoff_ms)
|
| : sliding_window_period_(
|
| base::TimeDelta::FromMilliseconds(sliding_window_period_ms)),
|
| max_send_threshold_(max_send_threshold),
|
| - initial_backoff_ms_(initial_backoff_ms),
|
| - additional_constant_ms_(additional_constant_ms),
|
| - multiply_factor_(multiply_factor),
|
| - jitter_factor_(jitter_factor),
|
| - maximum_backoff_ms_(maximum_backoff_ms),
|
| - entry_lifetime_ms_(-1) {
|
| + backoff_entry_(&backoff_policy_) {
|
| DCHECK_GT(sliding_window_period_ms, 0);
|
| DCHECK_GT(max_send_threshold_, 0);
|
| - DCHECK_GE(initial_backoff_ms_, 0);
|
| - DCHECK_GE(additional_constant_ms_, 0);
|
| - DCHECK_GT(multiply_factor_, 0);
|
| - DCHECK_GE(jitter_factor_, 0);
|
| - DCHECK_LT(jitter_factor_, 1);
|
| - DCHECK_GE(maximum_backoff_ms_, 0);
|
| + DCHECK_GE(initial_backoff_ms, 0);
|
| + DCHECK_GT(multiply_factor, 0);
|
| + DCHECK_GE(jitter_factor, 0.0);
|
| + DCHECK_LT(jitter_factor, 1.0);
|
| + DCHECK_GE(maximum_backoff_ms, 0);
|
|
|
| Initialize();
|
| + backoff_policy_.initial_backoff_ms_ = initial_backoff_ms;
|
| + backoff_policy_.multiply_factor_ = multiply_factor;
|
| + backoff_policy_.jitter_factor_ = jitter_factor;
|
| + backoff_policy_.maximum_backoff_ms_ = maximum_backoff_ms;
|
| + backoff_policy_.entry_lifetime_ms_ = -1;
|
| }
|
|
|
| bool URLRequestThrottlerEntry::IsEntryOutdated() const {
|
| - CHECK(this); // to help track crbug.com/71721
|
| - if (entry_lifetime_ms_ == -1)
|
| - return false;
|
| -
|
| - base::TimeTicks now = GetTimeNow();
|
| -
|
| - // If there are send events in the sliding window period, we still need this
|
| - // entry.
|
| - if (!send_log_.empty() &&
|
| - send_log_.back() + sliding_window_period_ > now) {
|
| - return false;
|
| - }
|
| -
|
| - int64 unused_since_ms =
|
| - (now - exponential_backoff_release_time_).InMilliseconds();
|
| -
|
| - // Release time is further than now, we are managing it.
|
| - if (unused_since_ms < 0)
|
| - return false;
|
| -
|
| - // latest_response_was_failure_ is true indicates that the latest one or
|
| - // more requests encountered server errors or had malformed response bodies.
|
| - // In that case, we don't want to collect the entry unless it hasn't been used
|
| - // for longer than the maximum allowed back-off.
|
| - if (latest_response_was_failure_)
|
| - return unused_since_ms > std::max(maximum_backoff_ms_, entry_lifetime_ms_);
|
| -
|
| - // Otherwise, consider the entry is outdated if it hasn't been used for the
|
| - // specified lifetime period.
|
| - return unused_since_ms > entry_lifetime_ms_;
|
| + return GetBackoffEntry()->CanDiscard();
|
| }
|
|
|
| bool URLRequestThrottlerEntry::IsDuringExponentialBackoff() const {
|
| - return exponential_backoff_release_time_ > GetTimeNow();
|
| + return GetBackoffEntry()->ShouldRejectRequest();
|
| }
|
|
|
| int64 URLRequestThrottlerEntry::ReserveSendingTimeForNextRequest(
|
| const base::TimeTicks& earliest_time) {
|
| base::TimeTicks now = GetTimeNow();
|
| +
|
| // If a lot of requests were successfully made recently,
|
| // sliding_window_release_time_ may be greater than
|
| // exponential_backoff_release_time_.
|
| base::TimeTicks recommended_sending_time =
|
| std::max(std::max(now, earliest_time),
|
| - std::max(exponential_backoff_release_time_,
|
| + std::max(GetBackoffEntry()->GetReleaseTime(),
|
| sliding_window_release_time_));
|
|
|
| DCHECK(send_log_.empty() ||
|
| @@ -138,34 +102,15 @@ int64 URLRequestThrottlerEntry::ReserveSendingTimeForNextRequest(
|
|
|
| base::TimeTicks
|
| URLRequestThrottlerEntry::GetExponentialBackoffReleaseTime() const {
|
| - return exponential_backoff_release_time_;
|
| + return GetBackoffEntry()->GetReleaseTime();
|
| }
|
|
|
| void URLRequestThrottlerEntry::UpdateWithResponse(
|
| const URLRequestThrottlerHeaderInterface* response) {
|
| if (response->GetResponseCode() >= 500) {
|
| - failure_count_++;
|
| - latest_response_was_failure_ = true;
|
| - exponential_backoff_release_time_ =
|
| - CalculateExponentialBackoffReleaseTime();
|
| + GetBackoffEntry()->InformOfRequest(false);
|
| } else {
|
| - // We slowly decay the number of times delayed instead of resetting it to 0
|
| - // in order to stay stable if we received lots of requests with
|
| - // malformed bodies at the same time.
|
| - if (failure_count_ > 0)
|
| - failure_count_--;
|
| -
|
| - latest_response_was_failure_ = false;
|
| -
|
| - // The reason why we are not just cutting the release time to GetTimeNow()
|
| - // is on the one hand, it would unset delay put by our custom retry-after
|
| - // header and on the other we would like to push every request up to our
|
| - // "horizon" when dealing with multiple in-flight requests. Ex: If we send
|
| - // three requests and we receive 2 failures and 1 success. The success that
|
| - // follows those failures will not reset the release time, further requests
|
| - // will then need to wait the delay caused by the 2 failures.
|
| - exponential_backoff_release_time_ = std::max(
|
| - GetTimeNow(), exponential_backoff_release_time_);
|
| + GetBackoffEntry()->InformOfRequest(true);
|
|
|
| std::string retry_header = response->GetNormalizedValue(kRetryHeaderName);
|
| if (!retry_header.empty())
|
| @@ -174,49 +119,21 @@ void URLRequestThrottlerEntry::UpdateWithResponse(
|
| }
|
|
|
| void URLRequestThrottlerEntry::ReceivedContentWasMalformed() {
|
| - // For any response that is marked as malformed now, we have probably
|
| - // considered it as a success when receiving it and decreased the failure
|
| - // count by 1. As a result, we increase the failure count by 2 here to undo
|
| - // the effect and record a failure.
|
| - //
|
| - // Please note that this may lead to a larger failure count than expected,
|
| - // because we don't decrease the failure count for successful responses when
|
| - // it has already reached 0.
|
| - failure_count_ += 2;
|
| - latest_response_was_failure_ = true;
|
| - exponential_backoff_release_time_ = CalculateExponentialBackoffReleaseTime();
|
| -}
|
| -
|
| -void URLRequestThrottlerEntry::SetEntryLifetimeMsForTest(int lifetime_ms) {
|
| - entry_lifetime_ms_ = lifetime_ms;
|
| + // We keep this simple and just count it as an error.
|
| + GetBackoffEntry()->InformOfRequest(false);
|
| }
|
|
|
| URLRequestThrottlerEntry::~URLRequestThrottlerEntry() {
|
| }
|
|
|
| void URLRequestThrottlerEntry::Initialize() {
|
| - // Since this method is called by the constructors, GetTimeNow() (a virtual
|
| - // method) is not used.
|
| - exponential_backoff_release_time_ = base::TimeTicks::Now();
|
| - failure_count_ = 0;
|
| - latest_response_was_failure_ = false;
|
| -
|
| sliding_window_release_time_ = base::TimeTicks::Now();
|
| -}
|
| -
|
| -base::TimeTicks
|
| - URLRequestThrottlerEntry::CalculateExponentialBackoffReleaseTime() {
|
| - double delay = initial_backoff_ms_;
|
| - delay *= pow(multiply_factor_, failure_count_);
|
| - delay += additional_constant_ms_;
|
| - delay -= base::RandDouble() * jitter_factor_ * delay;
|
| -
|
| - // Ensure that we do not exceed maximum delay.
|
| - int64 delay_int = static_cast<int64>(delay + 0.5);
|
| - delay_int = std::min(delay_int, static_cast<int64>(maximum_backoff_ms_));
|
| -
|
| - return std::max(GetTimeNow() + base::TimeDelta::FromMilliseconds(delay_int),
|
| - exponential_backoff_release_time_);
|
| + backoff_policy_.num_errors_to_ignore_ = 0;
|
| + backoff_policy_.initial_backoff_ms_ = kDefaultInitialBackoffMs;
|
| + backoff_policy_.multiply_factor_ = kDefaultMultiplyFactor;
|
| + backoff_policy_.jitter_factor_ = kDefaultJitterFactor;
|
| + backoff_policy_.maximum_backoff_ms_ = kDefaultMaximumBackoffMs;
|
| + backoff_policy_.entry_lifetime_ms_ = kDefaultEntryLifetimeMs;
|
| }
|
|
|
| base::TimeTicks URLRequestThrottlerEntry::GetTimeNow() const {
|
| @@ -236,12 +153,21 @@ void URLRequestThrottlerEntry::HandleCustomRetryAfter(
|
| // We must use an int value later so we transform this in milliseconds.
|
| int64 value_ms = static_cast<int64>(0.5 + time_in_sec * 1000);
|
|
|
| - if (maximum_backoff_ms_ < value_ms || value_ms < 0)
|
| + // We do not check for an upper bound; the server can set any Retry-After it
|
| + // desires. Recovery from error would involve restarting the browser.
|
| + if (value_ms < 0)
|
| return;
|
|
|
| - exponential_backoff_release_time_ = std::max(
|
| - (GetTimeNow() + base::TimeDelta::FromMilliseconds(value_ms)),
|
| - exponential_backoff_release_time_);
|
| + GetBackoffEntry()->SetCustomReleaseTime(
|
| + GetTimeNow() + base::TimeDelta::FromMilliseconds(value_ms));
|
| +}
|
| +
|
| +const BackoffEntry* URLRequestThrottlerEntry::GetBackoffEntry() const {
|
| + return &backoff_entry_;
|
| +}
|
| +
|
| +BackoffEntry* URLRequestThrottlerEntry::GetBackoffEntry() {
|
| + return &backoff_entry_;
|
| }
|
|
|
| } // namespace net
|
|
|