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

Side by Side Diff: ui/file_manager/file_manager/background/js/task_queue.js

Issue 789603004: Add a TaskQueue. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add an interface for TaskQueue.Task. Created 6 years 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
(Empty)
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
3 // found in the LICENSE file.
4
5 // Namespace
6 var importer = importer || {};
7
8 /**
9 * A queue of tasks. Tasks (subclasses of TaskQueue.Task) can be pushed onto
10 * the queue. The queue becomes active whenever it is not empty, and it will
11 * begin executing tasks one at a time. As each task runs, it can send update
12 * notifications which are relayed back to clients via callbacks. When the
13 * queue runs of of tasks, it goes back into an idle state. Clients can set
14 * callbacks which will be triggered whenever the queue transitions between the
15 * active and idle states.
16 *
17 * @constructor
hirono 2014/12/15 00:20:07 Please add @struct also.
Ben Kwa 2014/12/15 16:53:00 Done.
18 */
19 importer.TaskQueue = function() {
20 /** @private {!Array<!importer.TaskQueue.Task>} */
21 this.tasks_ = [];
22
23 /** @private {!Array<!function(string, !importer.TaskQueue.Task)>} */
24 this.updateCallbacks_ = [];
25
26 /** @private {?function()} */
27 this.activeCallback_ = null;
28
29 /** @private {?function()} */
30 this.idleCallback_ = null;
31
32 /** @private {boolean} */
33 this.active_ = false;
34 };
35
36 /**
37 * @enum {string}
38 */
39 importer.TaskQueue.UpdateType = {
40 PROGRESS: 'PROGRESS',
41 SUCCESS: 'SUCCESS',
42 ERROR: 'ERROR'
43 };
44
45 /**
46 * @param {!importer.TaskQueue.Task} task
47 */
48 importer.TaskQueue.prototype.queueTask = function(task) {
49 // TODO(kenobi): Use an AsyncGroup
50 Promise.resolve().then(function() {
51 task.setOwner(this);
52 this.tasks_.push(task);
53 // If more than one task is queued, then the queue is already running.
54 if (this.tasks_.length === 1) {
55 this.runPending_();
56 }
57 }.bind(this));
58 };
59
60 /**
61 * Sets a callback to be triggered when a task updates.
62 * @param {function(string, !importer.TaskQueue.Task)} callback
63 */
64 importer.TaskQueue.prototype.addUpdateCallback = function(callback) {
65 this.updateCallbacks_.push(callback);
66 };
67
68 /**
69 * Sets a callback that is triggered each time the queue goes from an idle
70 * (i.e. empty with no running tasks) to an active (i.e. having a running task)
71 * state.
72 * @param {function()} callback
73 */
74 importer.TaskQueue.prototype.setActiveCallback = function(callback) {
75 this.activeCallback_ = callback;
76 };
77
78 /**
79 * Sets a callback that is triggered each time the queue goes from an active to
80 * an idle state. Also see #onActive.
81 * @param {function()} callback
82 */
83 importer.TaskQueue.prototype.setIdleCallback = function(callback) {
84 this.idleCallback_ = callback;
85 };
86
87 /**
88 * Sends out notifications when a task updates. This is meant to be called by
89 * the running tasks owned by this queue.
90 * @param {!importer.TaskQueue.UpdateType} updateType
91 * @param {!importer.TaskQueue.Task} task
92 */
93 importer.TaskQueue.prototype.taskUpdate = function(updateType, task) {
94 this.updateCallbacks_.forEach(function(callback) {
95 callback.call(null, updateType, task);
96 });
97 };
98
99 /**
100 * Sends out notifications when a task stops. Stopping could be due to
101 * successful completion, cancellation, or errors. This is meant to be called
102 * by the running tasks owned by this queue.
103 * @param {!importer.TaskQueue.UpdateType} reason
104 * @param {!importer.TaskQueue.Task} task
105 */
106 importer.TaskQueue.prototype.taskDone = function(reason, task) {
107 // Remove the completed task from the queue.
108 this.tasks_.shift();
hirono 2014/12/15 00:20:07 Do you assume this.tasks_[0] === task ? If so, how
Ben Kwa 2014/12/15 16:53:00 Nice observation. Thanks! Done.
109 // Send updates to clients.
110 this.taskUpdate(reason, task);
111 // Run the next thing in the queue.
112 this.runPending_();
113 };
114
115 /**
116 * Wakes the task queue up and runs the next pending task, or makes the queue go
117 * back to sleep if no tasks are pending.
118 * @private
119 */
120 importer.TaskQueue.prototype.runPending_ = function() {
121 if (this.tasks_.length === 0) {
122 // All done - go back to idle.
123 this.active_ = false;
124 if (this.idleCallback_)
125 this.idleCallback_();
126 return;
127 }
128
129 if (!this.active_) {
130 // If the queue is currently idle, transition to active state.
131 this.active_ = true;
132 if (this.activeCallback_)
133 this.activeCallback_();
134 }
135
136 var nextTask = this.tasks_[0];
137 nextTask.run();
138 };
139
140 /**
141 * Interface for any Task that is to run on the TaskQueue.
142 * @interface
143 */
144 importer.TaskQueue.Task = function() {};
145
146 /**
147 * Sets the TaskQueue that will own this task. The TaskQueue must call this
148 * prior to enqueuing a Task.
149 * @param {!importer.TaskQueue} owner
150 */
151 importer.TaskQueue.Task.prototype.setOwner;
152
153 /**
154 * Performs the actual work of the Task. Child classes should implement this.
155 */
156 importer.TaskQueue.Task.prototype.run;
157
158 /**
159 * Base class for importer tasks.
160 * @constructor
161 * @implements {importer.TaskQueue.Task}
162 *
163 * @param {string} taskId
164 */
165 importer.TaskQueue.BaseTask = function(taskId) {
166 /** @private {string} */
167 this.taskId_ = taskId;
168 /** @private {importer.TaskQueue} */
169 this.owner_ = null;
170 };
171
172 /**
173 * Sets the TaskQueue that will own this task. The TaskQueue must call this
174 * prior to enqueuing a Task.
175 * @param {!importer.TaskQueue} owner
176 */
177 importer.TaskQueue.BaseTask.prototype.setOwner = function(owner) {
178 this.owner_ = owner;
179 };
180
181 /** @override */
182 importer.TaskQueue.BaseTask.prototype.run = function() {};
183
184 /**
185 * Sends progress notifications. Task subclasses should call this to report
186 * progress.
187 * @protected
188 */
189 importer.TaskQueue.BaseTask.prototype.notifyProgress = function() {
190 this.owner_.taskUpdate(importer.TaskQueue.UpdateType.PROGRESS, this);
191 };
192
193 /**
194 * Sends success notifications. Task subclasses should call this to indicate
195 * when they successfully complete. Calling this results in the Task instance
196 * being dequeued.
197 * @protected
198 */
199 importer.TaskQueue.BaseTask.prototype.notifySuccess = function() {
200 this.owner_.taskDone(importer.TaskQueue.UpdateType.SUCCESS, this);
201 };
202
203 /**
204 * Sends error notifications. Task subclasses should call this to indicate when
205 * an error occurs. Tasks are assumed to stop execution once they call
206 * notifyError (i.e. they will be dequeued).
207 * @protected
208 */
209 importer.TaskQueue.BaseTask.prototype.notifyError = function() {
210 this.owner_.taskDone(importer.TaskQueue.UpdateType.ERROR, this);
211 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698