[Search] Update provider timeout

Added a timedOut property to the provider's
return object. Changed the generic search
worker to stop if it reaches timeout.
This commit is contained in:
slhale
2015-07-30 16:35:26 -07:00
parent 6e11941ae9
commit 3a3e98cc48
4 changed files with 51 additions and 22 deletions

View File

@@ -112,14 +112,17 @@ define(
} }
// Order by score first, so that when removing repeats we keep the higher scored ones // Order by score first, so that when removing repeats we keep the higher scored ones
orderByScore(results); orderByScore(results);
totalSum = filterDuplicates(results, totalSum); totalSum -= filterDuplicates(results, totalSum);
// We are done loading // We are done loading
loading = false; loading = false;
return { return {
hits: results, hits: results,
total: totalSum total: totalSum,
timedOut: resultObjects.some(function (obj) {
return obj.timedOut;
})
}; };
}); });
} }

View File

@@ -130,7 +130,8 @@ define(
return { return {
hits: searchResults, hits: searchResults,
total: rawResults.data.hits.total total: rawResults.data.hits.total,
timedOut: rawResults.data.timed_out
}; };
}); });
} }
@@ -180,7 +181,7 @@ define(
* Searches through the filetree for domain objects using a search * Searches through the filetree for domain objects using a search
* term. This is done through querying elasticsearch. Returns a * term. This is done through querying elasticsearch. Returns a
* promise for a result object that has the format * promise for a result object that has the format
* {hits: searchResult[], total: number} * {hits: searchResult[], total: number, timedOut: boolean}
* where a searchResult has the format * where a searchResult has the format
* {id: domainObject ID, object: domainObject, score: number} * {id: domainObject ID, object: domainObject, score: number}
* *

View File

@@ -71,12 +71,13 @@ define(
// Tell the worker to search for items it has that match this searchInput. // Tell the worker to search for items it has that match this searchInput.
// Takes the searchInput, as well as a max number of results (will return // Takes the searchInput, as well as a max number of results (will return
// less than that if there are fewer matches). // less than that if there are fewer matches).
function workerSearch(searchInput, maxResults, timestamp) { function workerSearch(searchInput, maxResults, timestamp, timeout) {
var message = { var message = {
request: 'search', request: 'search',
input: searchInput, input: searchInput,
maxNumber: maxResults, maxNumber: maxResults,
timestamp: timestamp timestamp: timestamp,
timeout: timeout
}; };
worker.postMessage(message); worker.postMessage(message);
} }
@@ -108,7 +109,8 @@ define(
pendingQueries[event.data.timestamp].resolve( pendingQueries[event.data.timestamp].resolve(
{ {
hits: searchResults, hits: searchResults,
total: event.data.total total: event.data.total,
timedOut: event.data.timedOut
} }
); );
}); });
@@ -163,7 +165,7 @@ define(
// For documentation, see query below. // For documentation, see query below.
function query(input, timestamp, maxResults/*, timeout*/) { function query(input, timestamp, maxResults, timeout) {
var terms = [], var terms = [],
searchResults = [], searchResults = [],
defer = $q.defer(); defer = $q.defer();
@@ -176,10 +178,14 @@ define(
// Else, we provide a default value. // Else, we provide a default value.
maxResults = DEFAULT_MAX_RESULTS; maxResults = DEFAULT_MAX_RESULTS;
} }
// Similarly, check if timeout was provided
if (!timeout) {
timeout = DEFAULT_TIMEOUT;
}
// Instead, assume that the items have already been indexed, and // Instead, assume that the items have already been indexed, and
// just send the query to the worker. // just send the query to the worker.
workerSearch(input, maxResults, timestamp); workerSearch(input, maxResults, timestamp, timeout);
return defer.promise; return defer.promise;
} }
@@ -198,7 +204,7 @@ define(
* the search term. This function is to be used as a fallback * the search term. This function is to be used as a fallback
* in the case where other search services are not avaliable. * in the case where other search services are not avaliable.
* Returns a promise for a result object that has the format * Returns a promise for a result object that has the format
* {hits: searchResult[], total: number} * {hits: searchResult[], total: number, timedOut: boolean}
* where a searchResult has the format * where a searchResult has the format
* {id: domainObject ID, object: domainObject, score: number} * {id: domainObject ID, object: domainObject, score: number}
* *

View File

@@ -132,37 +132,56 @@
var results = {}, var results = {},
input = data.input.toLocaleLowerCase(), input = data.input.toLocaleLowerCase(),
terms = convertToTerms(input), terms = convertToTerms(input),
total,
i, i,
score; id,
score,
message = {
request: 'search',
results: {},
total: 0,
timestamp: data.timestamp, // TODO: This may be no longer necissary
timedOut: false
};
// If the user input is empty, we want to have no search results. // If the user input is empty, we want to have no search results.
if (input !== '') { if (input !== '') {
for (i = 0; i < indexedItems.length; i += 1) { for (i = 0; i < indexedItems.length; i += 1) {
// If this is taking too long, then stop
if (Date.now() > data.timestamp + data.timeout) {
message.timedOut = true;
break;
}
score = scoreItem(indexedItems[i], input, terms); score = scoreItem(indexedItems[i], input, terms);
if (score > 0) { if (score > 0) {
results[indexedItems[i].id] = score; results[indexedItems[i].id] = score;
message.total += 1;
} }
} }
} }
// Store the total hits number
total = results.length;
// Truncate results if there are more than maxResults // Truncate results if there are more than maxResults
if (results.length > data.maxNumber) { if (message.total > data.maxResults) {
results = results.slice(0, data.maxNumber); i = 0;
for (id in results) {
message.results[id] = results[id];
i += 1;
if (i >= data.maxResults) {
break;
}
}
// TODO: This seems inefficient.
} else {
message.results = results;
} }
return { return message;
request: 'search',
results: results,
total: total,
timestamp: data.timestamp
};
// TODO: After a search is completed, do we need to // TODO: After a search is completed, do we need to
// clear out indexedItems? // clear out indexedItems?
// When do we need to clear out inedxedItems? // When do we need to clear out inedxedItems?
// TODO: This function is too long.
} }
self.onmessage = function (event) { self.onmessage = function (event) {