Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(74)

Side by Side Diff: components/domain_reliability/scheduler.cc

Issue 704893002: Domain Reliability: Switch to BackoffEntry in Scheduler (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@parse_retry_after_header
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/domain_reliability/scheduler.h" 5 #include "components/domain_reliability/scheduler.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/metrics/field_trial.h" 9 #include "base/metrics/field_trial.h"
10 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_number_conversions.h"
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 62
63 return params; 63 return params;
64 } 64 }
65 65
66 DomainReliabilityScheduler::DomainReliabilityScheduler( 66 DomainReliabilityScheduler::DomainReliabilityScheduler(
67 MockableTime* time, 67 MockableTime* time,
68 size_t num_collectors, 68 size_t num_collectors,
69 const Params& params, 69 const Params& params,
70 const ScheduleUploadCallback& callback) 70 const ScheduleUploadCallback& callback)
71 : time_(time), 71 : time_(time),
72 collectors_(num_collectors),
73 params_(params), 72 params_(params),
74 callback_(callback), 73 callback_(callback),
75 upload_pending_(false), 74 upload_pending_(false),
76 upload_scheduled_(false), 75 upload_scheduled_(false),
77 upload_running_(false), 76 upload_running_(false),
78 collector_index_(kInvalidCollectorIndex), 77 collector_index_(kInvalidCollectorIndex),
79 last_upload_finished_(false) { 78 last_upload_finished_(false) {
79 backoff_policy_.num_errors_to_ignore = 0;
80 backoff_policy_.initial_delay_ms =
81 params.upload_retry_interval.InMilliseconds();
82 backoff_policy_.multiply_factor = 2.0;
83 backoff_policy_.jitter_factor = 0.1;
84 backoff_policy_.maximum_backoff_ms = 60 * 60 * 1000;
85 backoff_policy_.entry_lifetime_ms = 60 * 60 * 1000;
davidben 2014/11/06 22:39:36 Nit: maybe pull these up into constants.
Deprecated (see juliatuttle) 2014/11/07 19:45:09 Done.
86 backoff_policy_.always_use_initial_delay = false;
87
88 for (size_t i = 0; i < num_collectors; ++i) {
89 collectors_.push_back(
90 new MockableTimeBackoffEntry(&backoff_policy_, time_));
91 }
80 } 92 }
81 93
82 DomainReliabilityScheduler::~DomainReliabilityScheduler() {} 94 DomainReliabilityScheduler::~DomainReliabilityScheduler() {}
83 95
84 void DomainReliabilityScheduler::OnBeaconAdded() { 96 void DomainReliabilityScheduler::OnBeaconAdded() {
85 if (!upload_pending_) 97 if (!upload_pending_)
86 first_beacon_time_ = time_->NowTicks(); 98 first_beacon_time_ = time_->NowTicks();
87 upload_pending_ = true; 99 upload_pending_ = true;
88 MaybeScheduleUpload(); 100 MaybeScheduleUpload();
89 } 101 }
(...skipping 19 matching lines...) Expand all
109 } 121 }
110 122
111 void DomainReliabilityScheduler::OnUploadComplete(bool success) { 123 void DomainReliabilityScheduler::OnUploadComplete(bool success) {
112 DCHECK(upload_running_); 124 DCHECK(upload_running_);
113 DCHECK_NE(kInvalidCollectorIndex, collector_index_); 125 DCHECK_NE(kInvalidCollectorIndex, collector_index_);
114 upload_running_ = false; 126 upload_running_ = false;
115 127
116 VLOG(1) << "Upload to collector " << collector_index_ 128 VLOG(1) << "Upload to collector " << collector_index_
117 << (success ? " succeeded." : " failed."); 129 << (success ? " succeeded." : " failed.");
118 130
119 CollectorState* collector = &collectors_[collector_index_]; 131 net::BackoffEntry* backoff = collectors_[collector_index_];
120 collector_index_ = kInvalidCollectorIndex; 132 collector_index_ = kInvalidCollectorIndex;
133 backoff->InformOfRequest(success);
121 134
122 if (success) { 135 if (!success) {
123 collector->failures = 0;
124 } else {
125 // Restore upload_pending_ and first_beacon_time_ to pre-upload state, 136 // Restore upload_pending_ and first_beacon_time_ to pre-upload state,
126 // since upload failed. 137 // since upload failed.
127 upload_pending_ = true; 138 upload_pending_ = true;
128 first_beacon_time_ = old_first_beacon_time_; 139 first_beacon_time_ = old_first_beacon_time_;
129
130 ++collector->failures;
131 } 140 }
132 141
133 base::TimeTicks now = time_->NowTicks(); 142 last_upload_end_time_ = time_->NowTicks();
134 base::TimeDelta retry_interval = GetUploadRetryInterval(collector->failures);
135 collector->next_upload = now + retry_interval;
136
137 last_upload_end_time_ = now;
138 last_upload_success_ = success; 143 last_upload_success_ = success;
139 last_upload_finished_ = true; 144 last_upload_finished_ = true;
140 145
141 VLOG(1) << "Next upload to collector at least "
142 << retry_interval.InSeconds() << " seconds from now.";
143
144 MaybeScheduleUpload(); 146 MaybeScheduleUpload();
145 } 147 }
146 148
147 base::Value* DomainReliabilityScheduler::GetWebUIData() const { 149 base::Value* DomainReliabilityScheduler::GetWebUIData() const {
148 base::TimeTicks now = time_->NowTicks(); 150 base::TimeTicks now = time_->NowTicks();
149 151
150 base::DictionaryValue* data = new base::DictionaryValue(); 152 base::DictionaryValue* data = new base::DictionaryValue();
151 153
152 data->SetBoolean("upload_pending", upload_pending_); 154 data->SetBoolean("upload_pending", upload_pending_);
153 data->SetBoolean("upload_scheduled", upload_scheduled_); 155 data->SetBoolean("upload_scheduled", upload_scheduled_);
154 data->SetBoolean("upload_running", upload_running_); 156 data->SetBoolean("upload_running", upload_running_);
155 157
156 data->SetInteger("scheduled_min", (scheduled_min_time_ - now).InSeconds()); 158 data->SetInteger("scheduled_min", (scheduled_min_time_ - now).InSeconds());
157 data->SetInteger("scheduled_max", (scheduled_max_time_ - now).InSeconds()); 159 data->SetInteger("scheduled_max", (scheduled_max_time_ - now).InSeconds());
158 160
159 data->SetInteger("collector_index", static_cast<int>(collector_index_)); 161 data->SetInteger("collector_index", static_cast<int>(collector_index_));
160 162
161 if (last_upload_finished_) { 163 if (last_upload_finished_) {
162 base::DictionaryValue* last = new base::DictionaryValue(); 164 base::DictionaryValue* last = new base::DictionaryValue();
163 last->SetInteger("start_time", (now - last_upload_start_time_).InSeconds()); 165 last->SetInteger("start_time", (now - last_upload_start_time_).InSeconds());
164 last->SetInteger("end_time", (now - last_upload_end_time_).InSeconds()); 166 last->SetInteger("end_time", (now - last_upload_end_time_).InSeconds());
165 last->SetInteger("collector_index", 167 last->SetInteger("collector_index",
166 static_cast<int>(last_upload_collector_index_)); 168 static_cast<int>(last_upload_collector_index_));
167 last->SetBoolean("success", last_upload_success_); 169 last->SetBoolean("success", last_upload_success_);
168 data->Set("last_upload", last); 170 data->Set("last_upload", last);
169 } 171 }
170 172
171 base::ListValue* collectors = new base::ListValue(); 173 /* base::ListValue* collectors = new base::ListValue();
172 for (size_t i = 0; i < collectors_.size(); ++i) { 174 for (size_t i = 0; i < collectors_.size(); ++i) {
173 const CollectorState* state = &collectors_[i]; 175 const CollectorState* state = collectors_[i];
174 base::DictionaryValue* value = new base::DictionaryValue(); 176 base::DictionaryValue* value = new base::DictionaryValue();
175 value->SetInteger("failures", state->failures); 177 value->SetInteger("failures", state->failures);
176 value->SetInteger("next_upload", (state->next_upload - now).InSeconds()); 178 value->SetInteger("next_upload", (state->next_upload - now).InSeconds());
177 collectors->Append(value); 179 collectors->Append(value);
178 } 180 }
179 data->Set("collectors", collectors); 181 data->Set("collectors", collectors); */
davidben 2014/11/06 22:39:36 Did you mean to delete this code or revise it?
Deprecated (see juliatuttle) 2014/11/07 19:45:09 Revise; it turns out it's fairly simple, so done.
180 182
181 return data; 183 return data;
182 } 184 }
183 185
184 DomainReliabilityScheduler::CollectorState::CollectorState() : failures(0) {} 186 void DomainReliabilityScheduler::MakeDeterministicForTesting() {
187 backoff_policy_.jitter_factor = 0.0;
188 }
185 189
186 void DomainReliabilityScheduler::MaybeScheduleUpload() { 190 void DomainReliabilityScheduler::MaybeScheduleUpload() {
187 if (!upload_pending_ || upload_scheduled_ || upload_running_) 191 if (!upload_pending_ || upload_scheduled_ || upload_running_)
188 return; 192 return;
189 193
190 upload_scheduled_ = true; 194 upload_scheduled_ = true;
191 old_first_beacon_time_ = first_beacon_time_; 195 old_first_beacon_time_ = first_beacon_time_;
192 196
193 base::TimeTicks now = time_->NowTicks(); 197 base::TimeTicks now = time_->NowTicks();
194 198
(...skipping 26 matching lines...) Expand all
221 base::TimeTicks now, 225 base::TimeTicks now,
222 base::TimeTicks* upload_time_out, 226 base::TimeTicks* upload_time_out,
223 size_t* collector_index_out) { 227 size_t* collector_index_out) {
224 DCHECK(upload_time_out); 228 DCHECK(upload_time_out);
225 DCHECK(collector_index_out); 229 DCHECK(collector_index_out);
226 230
227 base::TimeTicks min_time; 231 base::TimeTicks min_time;
228 size_t min_index = kInvalidCollectorIndex; 232 size_t min_index = kInvalidCollectorIndex;
229 233
230 for (size_t i = 0; i < collectors_.size(); ++i) { 234 for (size_t i = 0; i < collectors_.size(); ++i) {
231 CollectorState* collector = &collectors_[i]; 235 net::BackoffEntry* backoff = collectors_[i];
232 // If a collector is usable, use the first one in the list. 236 // If a collector is usable, use the first one in the list.
233 if (collector->failures == 0 || collector->next_upload <= now) { 237 if (!backoff->ShouldRejectRequest()) {
234 min_time = now; 238 min_time = now;
235 min_index = i; 239 min_index = i;
236 break; 240 break;
241 }
242
237 // If not, keep track of which will be usable soonest: 243 // If not, keep track of which will be usable soonest:
238 } else if (min_index == kInvalidCollectorIndex || 244 base::TimeTicks time = backoff->GetReleaseTime();
239 collector->next_upload < min_time) { 245 if (min_index == kInvalidCollectorIndex || time < min_time) {
240 min_time = collector->next_upload; 246 min_time = time;
241 min_index = i; 247 min_index = i;
242 } 248 }
243 } 249 }
244 250
245 DCHECK_NE(kInvalidCollectorIndex, min_index); 251 DCHECK_NE(kInvalidCollectorIndex, min_index);
246 *upload_time_out = min_time; 252 *upload_time_out = min_time;
247 *collector_index_out = min_index; 253 *collector_index_out = min_index;
248 } 254 }
249 255
250 base::TimeDelta DomainReliabilityScheduler::GetUploadRetryInterval(
251 unsigned failures) {
252 if (failures == 0)
253 return base::TimeDelta::FromSeconds(0);
254 else {
255 // Don't back off more than 64x the original delay.
256 if (failures > 7)
257 failures = 7;
258 return params_.upload_retry_interval * (1 << (failures - 1));
259 }
260 }
261
262 } // namespace domain_reliability 256 } // namespace domain_reliability
OLDNEW
« no previous file with comments | « components/domain_reliability/scheduler.h ('k') | components/domain_reliability/scheduler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698