Merge "selenium: invoke jobs to enforce eventual consistency"
[lhc/web/wiklou.git] / resources / src / mediawiki.widgets / MediaSearch / mw.widgets.APIResultsQueue.js
1 /*!
2 * MediaWiki Widgets - APIResultsQueue class.
3 *
4 * @copyright 2011-2016 VisualEditor Team and others; see http://ve.mit-license.org
5 */
6 ( function () {
7
8 /**
9 * API Results Queue object.
10 *
11 * @class
12 * @mixins OO.EventEmitter
13 *
14 * @constructor
15 * @param {Object} [config] Configuration options
16 * @cfg {number} limit The default number of results to fetch
17 * @cfg {number} threshold The default number of extra results
18 * that the queue should always strive to have on top of the
19 * individual requests for items.
20 */
21 mw.widgets.APIResultsQueue = function MwWidgetsAPIResultsQueue( config ) {
22 config = config || {};
23
24 this.fileRepoPromise = null;
25 this.providers = [];
26 this.providerPromises = [];
27 this.queue = [];
28
29 this.params = {};
30
31 this.limit = config.limit || 20;
32 this.setThreshold( config.threshold || 10 );
33
34 // Mixin constructors
35 OO.EventEmitter.call( this );
36 };
37
38 /* Setup */
39 OO.mixinClass( mw.widgets.APIResultsQueue, OO.EventEmitter );
40
41 /* Methods */
42
43 /**
44 * Set up the queue and its resources.
45 * This should be overridden if there are any setup steps to perform.
46 *
47 * @return {jQuery.Promise} Promise that resolves when the resources
48 * are set up. Note: The promise must have an .abort() functionality.
49 */
50 mw.widgets.APIResultsQueue.prototype.setup = function () {
51 return $.Deferred().resolve().promise( { abort: $.noop } );
52 };
53
54 /**
55 * Get items from the queue
56 *
57 * @param {number} [howMany] How many items to retrieve. Defaults to the
58 * default limit supplied on initialization.
59 * @return {jQuery.Promise} Promise that resolves into an array of items.
60 */
61 mw.widgets.APIResultsQueue.prototype.get = function ( howMany ) {
62 var fetchingPromise = null,
63 me = this;
64
65 howMany = howMany || this.limit;
66
67 // Check if the queue has enough items
68 if ( this.queue.length < howMany + this.threshold ) {
69 // Call for more results
70 fetchingPromise = this.queryProviders( howMany + this.threshold )
71 .then( function ( items ) {
72 // Add to the queue
73 me.queue = me.queue.concat.apply( me.queue, items );
74 } );
75 }
76
77 return $.when( fetchingPromise )
78 .then( function () {
79 return me.queue.splice( 0, howMany );
80 } );
81
82 };
83
84 /**
85 * Get results from all providers
86 *
87 * @param {number} [howMany] How many items to retrieve. Defaults to the
88 * default limit supplied on initialization.
89 * @return {jQuery.Promise} Promise that is resolved into an array
90 * of fetched items. Note: The promise must have an .abort() functionality.
91 */
92 mw.widgets.APIResultsQueue.prototype.queryProviders = function ( howMany ) {
93 var i, len,
94 queue = this;
95
96 // Make sure there are resources set up
97 return this.setup()
98 .then( function () {
99 // Abort previous requests
100 for ( i = 0, len = queue.providerPromises.length; i < len; i++ ) {
101 queue.providerPromises[ i ].abort();
102 }
103 queue.providerPromises = [];
104 // Set up the query to all providers
105 for ( i = 0, len = queue.providers.length; i < len; i++ ) {
106 if ( !queue.providers[ i ].isDepleted() ) {
107 queue.providerPromises.push(
108 queue.providers[ i ].getResults( howMany )
109 );
110 }
111 }
112
113 return $.when.apply( $, queue.providerPromises )
114 .then( Array.prototype.concat.bind( [] ) );
115 } );
116 };
117
118 /**
119 * Set the search query for all the providers.
120 *
121 * This also makes sure to abort any previous promises.
122 *
123 * @param {Object} params API search parameters
124 */
125 mw.widgets.APIResultsQueue.prototype.setParams = function ( params ) {
126 var i, len;
127 if ( !OO.compare( params, this.params, true ) ) {
128 this.reset();
129 this.params = $.extend( this.params, params );
130 // Reset queue
131 this.queue = [];
132 // Reset promises
133 for ( i = 0, len = this.providerPromises.length; i < len; i++ ) {
134 this.providerPromises[ i ].abort();
135 }
136 // Change queries
137 for ( i = 0, len = this.providers.length; i < len; i++ ) {
138 this.providers[ i ].setUserParams( this.params );
139 }
140 }
141 };
142
143 /**
144 * Reset the queue and all its providers
145 */
146 mw.widgets.APIResultsQueue.prototype.reset = function () {
147 var i, len;
148 // Reset queue
149 this.queue = [];
150 // Reset promises
151 for ( i = 0, len = this.providerPromises.length; i < len; i++ ) {
152 this.providerPromises[ i ].abort();
153 }
154 // Change queries
155 for ( i = 0, len = this.providers.length; i < len; i++ ) {
156 this.providers[ i ].reset();
157 }
158 };
159
160 /**
161 * Get the data parameters sent to the API
162 *
163 * @return {Object} params API search parameters
164 */
165 mw.widgets.APIResultsQueue.prototype.getParams = function () {
166 return this.params;
167 };
168
169 /**
170 * Set the providers
171 *
172 * @param {mw.widgets.APIResultsProvider[]} providers An array of providers
173 */
174 mw.widgets.APIResultsQueue.prototype.setProviders = function ( providers ) {
175 this.providers = providers;
176 };
177
178 /**
179 * Add a provider to the group
180 *
181 * @param {mw.widgets.APIResultsProvider} provider A provider object
182 */
183 mw.widgets.APIResultsQueue.prototype.addProvider = function ( provider ) {
184 this.providers.push( provider );
185 };
186
187 /**
188 * Set the providers
189 *
190 * @return {mw.widgets.APIResultsProvider[]} providers An array of providers
191 */
192 mw.widgets.APIResultsQueue.prototype.getProviders = function () {
193 return this.providers;
194 };
195
196 /**
197 * Get the queue size
198 *
199 * @return {number} Queue size
200 */
201 mw.widgets.APIResultsQueue.prototype.getQueueSize = function () {
202 return this.queue.length;
203 };
204
205 /**
206 * Set queue threshold
207 *
208 * @param {number} threshold Queue threshold, below which we will
209 * request more items
210 */
211 mw.widgets.APIResultsQueue.prototype.setThreshold = function ( threshold ) {
212 this.threshold = threshold;
213 };
214
215 /**
216 * Get queue threshold
217 *
218 * @return {number} threshold Queue threshold, below which we will
219 * request more items
220 */
221 mw.widgets.APIResultsQueue.prototype.getThreshold = function () {
222 return this.threshold;
223 };
224 }() );