Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/offline_pages/background/request_picker.h" | 5 #include "components/offline_pages/background/pick_request_task.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/time/time.h" | |
| 10 #include "components/offline_pages/background/device_conditions.h" | |
| 11 #include "components/offline_pages/background/offliner_policy.h" | |
| 12 #include "components/offline_pages/background/request_coordinator_event_logger.h " | |
| 13 #include "components/offline_pages/background/request_notifier.h" | |
| 14 #include "components/offline_pages/background/request_queue_store.h" | |
| 9 #include "components/offline_pages/background/save_page_request.h" | 15 #include "components/offline_pages/background/save_page_request.h" |
| 10 | 16 |
| 11 namespace { | 17 namespace { |
| 12 template <typename T> | 18 template <typename T> |
| 13 int signum(T t) { | 19 int signum(T t) { |
| 14 return (T(0) < t) - (t < T(0)); | 20 return (T(0) < t) - (t < T(0)); |
| 15 } | 21 } |
| 16 | 22 |
| 17 #define CALL_MEMBER_FUNCTION(object, ptrToMember) ((object)->*(ptrToMember)) | 23 #define CALL_MEMBER_FUNCTION(object, ptrToMember) ((object)->*(ptrToMember)) |
| 18 } // namespace | 24 } // namespace |
| 19 | 25 |
| 20 namespace offline_pages { | 26 namespace offline_pages { |
| 21 | 27 |
| 22 RequestPicker::RequestPicker(RequestQueue* requestQueue, | 28 PickRequestTask::PickRequestTask(RequestQueueStore* store, |
| 23 OfflinerPolicy* policy, | 29 OfflinerPolicy* policy, |
| 24 RequestNotifier* notifier, | 30 RequestNotifier* notifier, |
| 25 RequestCoordinatorEventLogger* event_logger) | 31 RequestCoordinatorEventLogger* event_logger, |
| 26 : queue_(requestQueue), | 32 RequestPickedCallback picked_callback, |
| 33 RequestNotPickedCallback not_picked_callback, | |
| 34 DeviceConditions& device_conditions, | |
| 35 const std::set<int64_t>& disabled_requests) | |
| 36 : store_(store), | |
| 27 policy_(policy), | 37 policy_(policy), |
| 28 notifier_(notifier), | 38 notifier_(notifier), |
| 29 event_logger_(event_logger), | 39 event_logger_(event_logger), |
| 30 fewer_retries_better_(false), | 40 picked_callback_(picked_callback), |
| 31 earlier_requests_better_(false), | 41 not_picked_callback_(not_picked_callback), |
| 32 weak_ptr_factory_(this) {} | 42 disabled_requests_(disabled_requests), |
| 33 | 43 weak_ptr_factory_(this) { |
| 34 RequestPicker::~RequestPicker() {} | 44 device_conditions_.reset(new DeviceConditions(device_conditions)); |
| 35 | |
| 36 // Entry point for the async operation to choose the next request. | |
| 37 void RequestPicker::ChooseNextRequest( | |
| 38 RequestCoordinator::RequestPickedCallback picked_callback, | |
| 39 RequestCoordinator::RequestNotPickedCallback not_picked_callback, | |
| 40 DeviceConditions* device_conditions, | |
| 41 const std::set<int64_t>& disabled_requests) { | |
| 42 picked_callback_ = picked_callback; | |
| 43 not_picked_callback_ = not_picked_callback; | |
| 44 fewer_retries_better_ = policy_->ShouldPreferUntriedRequests(); | |
| 45 earlier_requests_better_ = policy_->ShouldPreferEarlierRequests(); | |
| 46 current_conditions_.reset(new DeviceConditions(*device_conditions)); | |
| 47 // Get all requests from queue (there is no filtering mechanism). | |
| 48 queue_->GetRequests(base::Bind(&RequestPicker::GetRequestResultCallback, | |
| 49 weak_ptr_factory_.GetWeakPtr(), | |
| 50 disabled_requests)); | |
| 51 } | 45 } |
| 52 | 46 |
| 53 // When we get contents from the queue, use them to pick the next | 47 PickRequestTask::~PickRequestTask() {} |
| 54 // request to operate on (if any). | 48 |
| 55 void RequestPicker::GetRequestResultCallback( | 49 void PickRequestTask::Run() { |
| 56 const std::set<int64_t>& disabled_requests, | 50 // Get all the requests from the queue, we will classify them in the callback. |
| 57 RequestQueue::GetRequestsResult, | 51 store_->GetRequests(base::Bind(&PickRequestTask::ChooseAndPrune, |
| 52 weak_ptr_factory_.GetWeakPtr())); | |
| 53 } | |
| 54 | |
| 55 void PickRequestTask::ChooseAndPrune( | |
| 56 bool success, | |
| 58 std::vector<std::unique_ptr<SavePageRequest>> requests) { | 57 std::vector<std::unique_ptr<SavePageRequest>> requests) { |
| 59 // If there is nothing to do, return right away. | 58 // If there is nothing to do, return right away. |
| 60 if (requests.size() == 0) { | 59 if (requests.size() == 0) { |
| 61 not_picked_callback_.Run(false); | 60 not_picked_callback_.Run(false); |
|
fgorski
2016/11/09 17:58:07
Early call to TaskComplete() is in order here (bef
Pete Williamson
2016/11/09 23:53:55
Done, and checked the code for more cases (I did n
| |
| 62 return; | 61 return; |
| 63 } | 62 } |
| 64 | 63 |
| 65 // Get the expired requests to be removed from the queue, and the valid ones | 64 // Get the expired requests to be removed from the queue, and the valid ones |
| 66 // from which to pick the next request. | 65 // from which to pick the next request. |
| 67 std::vector<std::unique_ptr<SavePageRequest>> valid_requests; | 66 std::vector<std::unique_ptr<SavePageRequest>> valid_requests; |
| 68 std::vector<std::unique_ptr<SavePageRequest>> expired_requests; | 67 std::vector<std::unique_ptr<SavePageRequest>> expired_requests; |
| 69 SplitRequests(std::move(requests), &valid_requests, &expired_requests); | 68 SplitRequests(std::move(requests), &valid_requests, &expired_requests); |
| 70 std::vector<int64_t> expired_request_ids; | 69 std::vector<int64_t> expired_request_ids; |
|
fgorski
2016/11/09 17:58:07
looks like this should be a type of the third para
Pete Williamson
2016/11/09 23:53:55
Changed (but I actually replaced the second parame
fgorski
2016/11/10 19:15:50
You are technically correct. :)
| |
| 71 for (const auto& request : expired_requests) | 70 for (const auto& request : expired_requests) |
| 72 expired_request_ids.push_back(request->request_id()); | 71 expired_request_ids.push_back(request->request_id()); |
|
dougarnett
2016/11/09 18:23:51
this *_ids vector not actually used?
Pete Williamson
2016/11/09 23:53:55
Good catch, removed (it got copied into the Remove
| |
| 73 | 72 |
| 74 queue_->RemoveRequests(expired_request_ids, | 73 // Continue processing by choosing a request. |
| 75 base::Bind(&RequestPicker::OnRequestExpired, | 74 ChooseRequestAndCallback(std::move(valid_requests)); |
| 76 weak_ptr_factory_.GetWeakPtr())); | |
| 77 | 75 |
| 76 // Continue Async Processing. | |
|
fgorski
2016/11/09 17:58:07
Add early return here if expired_request_ids is em
Pete Williamson
2016/11/09 23:53:55
Done.
| |
| 77 RemoveStaleRequests(std::move(expired_requests)); | |
| 78 } | |
| 79 | |
| 80 void PickRequestTask::ChooseRequestAndCallback( | |
| 81 std::vector<std::unique_ptr<SavePageRequest>> valid_requests) { | |
| 78 // Pick the most deserving request for our conditions. | 82 // Pick the most deserving request for our conditions. |
| 79 const SavePageRequest* picked_request = nullptr; | 83 const SavePageRequest* picked_request = nullptr; |
| 80 | 84 |
| 81 RequestCompareFunction comparator = nullptr; | 85 RequestCompareFunction comparator = nullptr; |
| 82 | 86 |
| 83 // Choose which comparison function to use based on policy. | 87 // Choose which comparison function to use based on policy. |
| 84 if (policy_->RetryCountIsMoreImportantThanRecency()) | 88 if (policy_->RetryCountIsMoreImportantThanRecency()) |
| 85 comparator = &RequestPicker::RetryCountFirstCompareFunction; | 89 comparator = &PickRequestTask::RetryCountFirstCompareFunction; |
| 86 else | 90 else |
| 87 comparator = &RequestPicker::RecencyFirstCompareFunction; | 91 comparator = &PickRequestTask::RecencyFirstCompareFunction; |
| 88 | 92 |
| 89 // Iterate once through the requests, keeping track of best candidate. | 93 // Iterate once through the requests, keeping track of best candidate. |
| 90 bool non_user_requested_tasks_remaining = false; | 94 bool non_user_requested_tasks_remaining = false; |
| 91 for (unsigned i = 0; i < valid_requests.size(); ++i) { | 95 for (unsigned i = 0; i < valid_requests.size(); ++i) { |
| 92 // If the request is on the disabled list, skip it. | 96 // If the request is on the disabled list, skip it. |
| 93 auto search = disabled_requests.find(valid_requests[i]->request_id()); | 97 auto search = disabled_requests_.find(valid_requests[i]->request_id()); |
| 94 if (search != disabled_requests.end()) { | 98 if (search != disabled_requests_.end()) { |
|
fgorski
2016/11/09 17:58:06
nit: drop {}
Pete Williamson
2016/11/09 23:53:55
Done.
| |
| 95 continue; | 99 continue; |
| 96 } | 100 } |
| 97 if (!valid_requests[i]->user_requested()) | 101 if (!valid_requests[i]->user_requested()) |
| 98 non_user_requested_tasks_remaining = true; | 102 non_user_requested_tasks_remaining = true; |
| 99 if (!RequestConditionsSatisfied(valid_requests[i].get())) | 103 if (!RequestConditionsSatisfied(valid_requests[i].get())) |
|
fgorski
2016/11/09 17:58:06
I am missing a comment here explaining why we firs
dougarnett
2016/11/09 18:39:56
Btw, that non_user_requested_tasks_remaining bool
Pete Williamson
2016/11/09 23:53:55
TODO added.
Pete Williamson
2016/11/09 23:53:55
Done.
| |
| 100 continue; | 104 continue; |
| 101 if (IsNewRequestBetter(picked_request, valid_requests[i].get(), comparator)) | 105 if (IsNewRequestBetter(picked_request, valid_requests[i].get(), comparator)) |
| 102 picked_request = valid_requests[i].get(); | 106 picked_request = valid_requests[i].get(); |
| 103 } | 107 } |
| 104 | 108 |
| 105 // If we have a best request to try next, get the request coodinator to | 109 // If we have a best request to try next, get the request coodinator to |
| 106 // start it. Otherwise return that we have no candidates. | 110 // start it. Otherwise return that we have no candidates. |
| 107 if (picked_request != nullptr) { | 111 if (picked_request != nullptr) { |
|
fgorski
2016/11/09 17:58:07
nit: braces not necessary for both clauses.
Pete Williamson
2016/11/09 23:53:55
Done.
| |
| 108 picked_callback_.Run(*picked_request); | 112 picked_callback_.Run(*picked_request); |
| 109 } else { | 113 } else { |
| 110 not_picked_callback_.Run(non_user_requested_tasks_remaining); | 114 not_picked_callback_.Run(non_user_requested_tasks_remaining); |
| 111 } | 115 } |
| 112 } | 116 } |
| 113 | 117 |
| 118 // Continue the async part of the processing by deleting the expired requests. | |
| 119 // TODO(petewil): Does that really need to be done on the task queue? Hard to | |
|
fgorski
2016/11/09 17:58:07
this comment/todo probably needs revisiting after
Pete Williamson
2016/11/09 23:53:55
The comment is current. It is basically explainin
fgorski
2016/11/10 19:15:50
OK. Reread this and it can stay this way.
| |
| 120 // see how we need to wait for it before starting the next task. OTOH, we'd hate | |
| 121 // to do a second slow DB operation to get entries a second time, and waiting | |
| 122 // until this is done will make sure other gets don't see these old entries. | |
| 123 // Consider moving this to a fresh task type to clean the queue. | |
| 124 void PickRequestTask::RemoveStaleRequests( | |
| 125 std::vector<std::unique_ptr<SavePageRequest>> stale_requests) { | |
| 126 std::vector<int64_t> stale_request_ids; | |
|
fgorski
2016/11/09 17:58:07
and these 3 lines is exactly why my comment about
Pete Williamson
2016/11/09 23:53:55
Done.
| |
| 127 for (const auto& request : stale_requests) | |
| 128 stale_request_ids.push_back(request->request_id()); | |
| 129 | |
| 130 store_->RemoveRequests(stale_request_ids, | |
| 131 base::Bind(&PickRequestTask::OnRequestsExpired, | |
| 132 weak_ptr_factory_.GetWeakPtr())); | |
| 133 } | |
| 134 | |
| 135 void PickRequestTask::OnRequestsExpired( | |
| 136 std::unique_ptr<UpdateRequestsResult> result) { | |
| 137 RequestNotifier::BackgroundSavePageResult save_page_result( | |
| 138 RequestNotifier::BackgroundSavePageResult::EXPIRED); | |
| 139 for (const auto& request : result->updated_items) { | |
| 140 event_logger_->RecordDroppedSavePageRequest( | |
| 141 request.client_id().name_space, save_page_result, request.request_id()); | |
| 142 notifier_->NotifyCompleted(request, save_page_result); | |
| 143 } | |
| 144 | |
| 145 // The task is now done, return control to the task queue. | |
| 146 TaskComplete(); | |
| 147 } | |
| 148 | |
| 149 void PickRequestTask::SplitRequests( | |
| 150 std::vector<std::unique_ptr<SavePageRequest>> requests, | |
| 151 std::vector<std::unique_ptr<SavePageRequest>>* valid_requests, | |
| 152 std::vector<std::unique_ptr<SavePageRequest>>* expired_requests) { | |
|
fgorski
2016/11/09 17:58:07
this one should be std::vector<int64_t>
Pete Williamson
2016/11/09 23:53:55
Done.
| |
| 153 for (auto& request : requests) { | |
| 154 if (base::Time::Now() - request->creation_time() >= | |
| 155 base::TimeDelta::FromSeconds(kRequestExpirationTimeInSeconds)) { | |
| 156 expired_requests->push_back(std::move(request)); | |
| 157 } else { | |
| 158 valid_requests->push_back(std::move(request)); | |
| 159 } | |
| 160 } | |
| 161 } | |
| 162 | |
| 114 // Filter out requests that don't meet the current conditions. For instance, if | 163 // Filter out requests that don't meet the current conditions. For instance, if |
| 115 // this is a predictive request, and we are not on WiFi, it should be ignored | 164 // this is a predictive request, and we are not on WiFi, it should be ignored |
| 116 // this round. | 165 // this round. |
| 117 bool RequestPicker::RequestConditionsSatisfied(const SavePageRequest* request) { | 166 bool PickRequestTask::RequestConditionsSatisfied( |
| 167 const SavePageRequest* request) { | |
| 118 // If the user did not request the page directly, make sure we are connected | 168 // If the user did not request the page directly, make sure we are connected |
| 119 // to power and have WiFi and sufficient battery remaining before we take this | 169 // to power and have WiFi and sufficient battery remaining before we take this |
| 120 // request. | 170 // request. |
| 121 | 171 if (!device_conditions_->IsPowerConnected() && |
| 122 if (!current_conditions_->IsPowerConnected() && | |
| 123 policy_->PowerRequired(request->user_requested())) { | 172 policy_->PowerRequired(request->user_requested())) { |
| 124 return false; | 173 return false; |
| 125 } | 174 } |
| 126 | 175 |
| 127 if (current_conditions_->GetNetConnectionType() != | 176 if (device_conditions_->GetNetConnectionType() != |
| 128 net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI && | 177 net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI && |
| 129 policy_->UnmeteredNetworkRequired(request->user_requested())) { | 178 policy_->UnmeteredNetworkRequired(request->user_requested())) { |
| 130 return false; | 179 return false; |
| 131 } | 180 } |
| 132 | 181 |
| 133 if (current_conditions_->GetBatteryPercentage() < | 182 if (device_conditions_->GetBatteryPercentage() < |
| 134 policy_->BatteryPercentageRequired(request->user_requested())) { | 183 policy_->BatteryPercentageRequired(request->user_requested())) { |
| 135 return false; | 184 return false; |
| 136 } | 185 } |
| 137 | 186 |
| 138 // If we have already started this page the max number of times, it is not | 187 // If we have already started this page the max number of times, it is not |
| 139 // eligible to try again. | 188 // eligible to try again. |
| 140 if (request->started_attempt_count() >= policy_->GetMaxStartedTries()) | 189 if (request->started_attempt_count() >= policy_->GetMaxStartedTries()) |
| 141 return false; | 190 return false; |
| 142 | 191 |
| 143 // If we have already completed trying this page the max number of times, it | 192 // If we have already completed trying this page the max number of times, it |
| 144 // is not eligible to try again. | 193 // is not eligible to try again. |
| 145 if (request->completed_attempt_count() >= policy_->GetMaxCompletedTries()) | 194 if (request->completed_attempt_count() >= policy_->GetMaxCompletedTries()) |
| 146 return false; | 195 return false; |
| 147 | 196 |
| 148 // If the request is paused, do not consider it. | 197 // If the request is paused, do not consider it. |
| 149 if (request->request_state() == SavePageRequest::RequestState::PAUSED) | 198 if (request->request_state() == SavePageRequest::RequestState::PAUSED) |
| 150 return false; | 199 return false; |
| 151 | 200 |
| 152 // If the request is expired, do not consider it. | 201 // If the request is expired, do not consider it. |
| 153 base::TimeDelta requestAge = base::Time::Now() - request->creation_time(); | 202 base::TimeDelta requestAge = base::Time::Now() - request->creation_time(); |
| 154 if (requestAge > | 203 if (requestAge > base::TimeDelta::FromSeconds( |
| 155 base::TimeDelta::FromSeconds( | 204 policy_->GetRequestExpirationTimeInSeconds())) |
| 156 policy_->GetRequestExpirationTimeInSeconds())) | |
| 157 return false; | 205 return false; |
| 158 | 206 |
| 159 // If this request is not active yet, return false. | 207 // If this request is not active yet, return false. |
| 160 // TODO(petewil): If the only reason we return nothing to do is that we have | 208 // TODO(petewil): If the only reason we return nothing to do is that we have |
| 161 // inactive requests, we still want to try again later after their activation | 209 // inactive requests, we still want to try again later after their activation |
| 162 // time elapses, we shouldn't take ourselves completely off the scheduler. | 210 // time elapses, we shouldn't take ourselves completely off the scheduler. |
| 163 if (request->activation_time() > base::Time::Now()) | 211 if (request->activation_time() > base::Time::Now()) |
| 164 return false; | 212 return false; |
| 165 | 213 |
| 166 return true; | 214 return true; |
| 167 } | 215 } |
| 168 | 216 |
| 169 // Look at policies to decide which requests to prefer. | 217 // Look at policies to decide which requests to prefer. |
| 170 bool RequestPicker::IsNewRequestBetter(const SavePageRequest* oldRequest, | 218 bool PickRequestTask::IsNewRequestBetter(const SavePageRequest* oldRequest, |
| 171 const SavePageRequest* newRequest, | 219 const SavePageRequest* newRequest, |
| 172 RequestCompareFunction comparator) { | 220 RequestCompareFunction comparator) { |
| 173 | |
| 174 // If there is no old request, the new one is better. | 221 // If there is no old request, the new one is better. |
| 175 if (oldRequest == nullptr) | 222 if (oldRequest == nullptr) |
| 176 return true; | 223 return true; |
| 177 | 224 |
| 178 // User requested pages get priority. | 225 // User requested pages get priority. |
| 179 if (newRequest->user_requested() && !oldRequest->user_requested()) | 226 if (newRequest->user_requested() && !oldRequest->user_requested()) |
| 180 return true; | 227 return true; |
| 181 | 228 |
| 182 // Otherwise, use the comparison function for the current policy, which | 229 // Otherwise, use the comparison function for the current policy, which |
| 183 // returns true if the older request is better. | 230 // returns true if the older request is better. |
| 184 return !(CALL_MEMBER_FUNCTION(this, comparator)(oldRequest, newRequest)); | 231 return !(CALL_MEMBER_FUNCTION(this, comparator)(oldRequest, newRequest)); |
| 185 } | 232 } |
| 186 | 233 |
| 187 // Compare the results, checking request count before recency. Returns true if | 234 // Compare the results, checking request count before recency. Returns true if |
| 188 // left hand side is better, false otherwise. | 235 // left hand side is better, false otherwise. |
| 189 bool RequestPicker::RetryCountFirstCompareFunction( | 236 bool PickRequestTask::RetryCountFirstCompareFunction( |
| 190 const SavePageRequest* left, const SavePageRequest* right) { | 237 const SavePageRequest* left, |
| 238 const SavePageRequest* right) { | |
| 191 // Check the attempt count. | 239 // Check the attempt count. |
| 192 int result = CompareRetryCount(left, right); | 240 int result = CompareRetryCount(left, right); |
| 193 | 241 |
| 194 if (result != 0) | 242 if (result != 0) |
| 195 return (result > 0); | 243 return (result > 0); |
| 196 | 244 |
| 197 // If we get here, the attempt counts were the same, so check recency. | 245 // If we get here, the attempt counts were the same, so check recency. |
| 198 result = CompareCreationTime(left, right); | 246 result = CompareCreationTime(left, right); |
| 199 | 247 |
| 200 return (result > 0); | 248 return (result > 0); |
| 201 } | 249 } |
| 202 | 250 |
| 203 // Compare the results, checking recency before request count. Returns true if | 251 // Compare the results, checking recency before request count. Returns true if |
| 204 // left hand side is better, false otherwise. | 252 // left hand side is better, false otherwise. |
| 205 bool RequestPicker::RecencyFirstCompareFunction( | 253 bool PickRequestTask::RecencyFirstCompareFunction( |
| 206 const SavePageRequest* left, const SavePageRequest* right) { | 254 const SavePageRequest* left, |
| 255 const SavePageRequest* right) { | |
| 207 // Check the recency. | 256 // Check the recency. |
| 208 int result = CompareCreationTime(left, right); | 257 int result = CompareCreationTime(left, right); |
| 209 | 258 |
| 210 if (result != 0) | 259 if (result != 0) |
| 211 return (result > 0); | 260 return (result > 0); |
| 212 | 261 |
| 213 // If we get here, the recency was the same, so check the attempt count. | 262 // If we get here, the recency was the same, so check the attempt count. |
| 214 result = CompareRetryCount(left, right); | 263 result = CompareRetryCount(left, right); |
| 215 | 264 |
| 216 return (result > 0); | 265 return (result > 0); |
| 217 } | 266 } |
| 218 | 267 |
| 219 // Compare left and right side, returning 1 if the left side is better | 268 // Compare left and right side, returning 1 if the left side is better |
| 220 // (preferred by policy), 0 if the same, and -1 if the right side is better. | 269 // (preferred by policy), 0 if the same, and -1 if the right side is better. |
| 221 int RequestPicker::CompareRetryCount( | 270 int PickRequestTask::CompareRetryCount(const SavePageRequest* left, |
| 222 const SavePageRequest* left, const SavePageRequest* right) { | 271 const SavePageRequest* right) { |
| 223 // Check the attempt count. | 272 // Check the attempt count. |
| 224 int result = signum(left->completed_attempt_count() - | 273 int result = signum(left->completed_attempt_count() - |
| 225 right->completed_attempt_count()); | 274 right->completed_attempt_count()); |
| 226 | 275 |
| 227 // Flip the direction of comparison if policy prefers fewer retries. | 276 // Flip the direction of comparison if policy prefers fewer retries. |
| 228 if (fewer_retries_better_) | 277 if (policy_->ShouldPreferUntriedRequests()) |
| 229 result *= -1; | 278 result *= -1; |
| 230 | 279 |
| 231 return result; | 280 return result; |
| 232 } | 281 } |
| 233 | 282 |
| 234 // Compare left and right side, returning 1 if the left side is better | 283 // Compare left and right side, returning 1 if the left side is better |
| 235 // (preferred by policy), 0 if the same, and -1 if the right side is better. | 284 // (preferred by policy), 0 if the same, and -1 if the right side is better. |
| 236 int RequestPicker::CompareCreationTime( | 285 int PickRequestTask::CompareCreationTime(const SavePageRequest* left, |
| 237 const SavePageRequest* left, const SavePageRequest* right) { | 286 const SavePageRequest* right) { |
| 238 // Check the recency. | 287 // Check the recency. |
| 239 base::TimeDelta difference = left->creation_time() - right->creation_time(); | 288 base::TimeDelta difference = left->creation_time() - right->creation_time(); |
| 240 int result = signum(difference.InMilliseconds()); | 289 int result = signum(difference.InMilliseconds()); |
| 241 | 290 |
| 242 // Flip the direction of comparison if policy prefers fewer retries. | 291 // Flip the direction of comparison if policy prefers fewer retries. |
| 243 if (earlier_requests_better_) | 292 if (policy_->ShouldPreferEarlierRequests()) |
| 244 result *= -1; | 293 result *= -1; |
| 245 | 294 |
| 246 return result; | 295 return result; |
| 247 } | 296 } |
| 248 | 297 |
| 249 void RequestPicker::SplitRequests( | |
| 250 std::vector<std::unique_ptr<SavePageRequest>> requests, | |
| 251 std::vector<std::unique_ptr<SavePageRequest>>* valid_requests, | |
| 252 std::vector<std::unique_ptr<SavePageRequest>>* expired_requests) { | |
| 253 for (auto& request : requests) { | |
| 254 if (base::Time::Now() - request->creation_time() >= | |
| 255 base::TimeDelta::FromSeconds(kRequestExpirationTimeInSeconds)) { | |
| 256 expired_requests->push_back(std::move(request)); | |
| 257 } else { | |
| 258 valid_requests->push_back(std::move(request)); | |
| 259 } | |
| 260 } | |
| 261 } | |
| 262 | |
| 263 // Callback used after expired requests are deleted from the queue and notifies | |
| 264 // the coordinator. | |
| 265 void RequestPicker::OnRequestExpired( | |
| 266 std::unique_ptr<UpdateRequestsResult> result) { | |
| 267 const RequestCoordinator::BackgroundSavePageResult save_page_result( | |
| 268 RequestCoordinator::BackgroundSavePageResult::EXPIRED); | |
| 269 for (const auto& request : result->updated_items) { | |
| 270 event_logger_->RecordDroppedSavePageRequest( | |
| 271 request.client_id().name_space, save_page_result, request.request_id()); | |
| 272 notifier_->NotifyCompleted(request, save_page_result); | |
| 273 } | |
| 274 } | |
| 275 | |
| 276 } // namespace offline_pages | 298 } // namespace offline_pages |
| OLD | NEW |