1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
8 * Worker for requests. Fetches requests from a queue and processes them
9 * synchronously, taking into account priorities. The highest priority is 0.
13 * List of requests waiting to be checked. If these items are available in
14 * cache, then they are processed immediately after starting the worker.
15 * However, if they have to be downloaded, then these requests are moved
16 * to pendingRequests_.
18 * @type {Array.<Request>}
21 this.newRequests_ = [];
24 * List of pending requests for images to be downloaded.
25 * @type {Array.<Request>}
28 this.pendingRequests_ = [];
31 * List of requests being processed.
32 * @type {Array.<Request>}
35 this.activeRequests_ = [];
38 * Hash array of requests being added to the queue, but not finalized yet.
45 * If the worker has been started.
49 this.started_ = false;
53 * Maximum download requests to be run in parallel.
57 Worker.MAXIMUM_IN_PARALLEL = 5;
60 * Adds a request to the internal priority queue and executes it when requests
61 * with higher priorities are finished. If the result is cached, then it is
62 * processed immediately once the worker is started.
64 * @param {Request} request Request object.
66 Worker.prototype.add = function(request) {
68 this.newRequests_.push(request);
69 this.requests_[request.getId()] = request;
73 // Enqueue the request, since already started.
74 this.pendingRequests_.push(request);
75 this.sortPendingRequests_();
81 * Removes a request from the worker (if exists).
82 * @param {string} requestId Unique ID of the request.
84 Worker.prototype.remove = function(requestId) {
85 var request = this.requests_[requestId];
89 // Remove from the internal queues with pending tasks.
90 var newIndex = this.pendingRequests_.indexOf(request);
92 this.newRequests_.splice(newIndex, 1);
93 var pendingIndex = this.pendingRequests_.indexOf(request);
94 if (pendingIndex != -1)
95 this.pendingRequests_.splice(pendingIndex, 1);
97 // Cancel the request.
99 delete this.requests_[requestId];
103 * Starts handling requests.
105 Worker.prototype.start = function() {
106 this.started_ = true;
108 // Process tasks added before worker has been started.
109 this.pendingRequests_ = this.newRequests_;
110 this.sortPendingRequests_();
111 this.newRequests_ = [];
113 // Start serving enqueued requests.
118 * Sorts pending requests by priorities.
121 Worker.prototype.sortPendingRequests_ = function() {
122 this.pendingRequests_.sort(function(a, b) {
123 return a.getPriority() - b.getPriority();
128 * Processes pending requests from the queue. There is no guarantee that
129 * all of the tasks will be processed at once.
133 Worker.prototype.continue_ = function() {
134 // Run only up to MAXIMUM_IN_PARALLEL in the same time.
135 while (this.pendingRequests_.length &&
136 this.activeRequests_.length < Worker.MAXIMUM_IN_PARALLEL) {
137 var request = this.pendingRequests_.shift();
138 this.activeRequests_.push(request);
140 // Try to load from cache. If doesn't exist, then download.
141 request.loadFromCacheAndProcess(
142 this.finish_.bind(this, request),
143 function(currentRequest) {
144 currentRequest.downloadAndProcess(
145 this.finish_.bind(this, currentRequest));
146 }.bind(this, request));
151 * Handles finished requests.
153 * @param {Request} request Finished request.
156 Worker.prototype.finish_ = function(request) {
157 var index = this.activeRequests_.indexOf(request);
159 console.warn('Request not found.');
160 this.activeRequests_.splice(index, 1);
161 delete this.requests_[request.getId()];
163 // Continue handling the most important requests (if started).