mirror of
https://github.com/nasa/openmct.git
synced 2024-12-22 22:42:24 +00:00
remove WorkerService (#4484)
* Use bare bones search worker using native Worker * Remove worker service * remove unused workers pulled into search bundle Co-authored-by: Jamie V <jamie.j.vigliotta@nasa.gov> Co-authored-by: Andrew Henry <akhenry@gmail.com>
This commit is contained in:
parent
84e82d3bda
commit
e1e2cf9be8
@ -1 +0,0 @@
|
|||||||
Contains services which manage execution and flow control (e.g. for concurrency.)
|
|
@ -1,46 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*
|
|
||||||
* Open MCT includes source code licensed under additional open source
|
|
||||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
|
||||||
* this source code distribution or the Licensing information page available
|
|
||||||
* at runtime from the About dialog for additional information.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
define([
|
|
||||||
"./src/WorkerService"
|
|
||||||
], function (
|
|
||||||
WorkerService
|
|
||||||
) {
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: "platform/execution",
|
|
||||||
definition: {
|
|
||||||
"extensions": {
|
|
||||||
"services": [
|
|
||||||
{
|
|
||||||
"key": "workerService",
|
|
||||||
"implementation": WorkerService,
|
|
||||||
"depends": [
|
|
||||||
"$window",
|
|
||||||
"workers[]"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
@ -1,92 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*
|
|
||||||
* Open MCT includes source code licensed under additional open source
|
|
||||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
|
||||||
* this source code distribution or the Licensing information page available
|
|
||||||
* at runtime from the About dialog for additional information.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This bundle contains services for managing the flow of execution,
|
|
||||||
* such as support for running web workers on background threads.
|
|
||||||
* @namespace platform/execution
|
|
||||||
*/
|
|
||||||
define(
|
|
||||||
[],
|
|
||||||
function () {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles the execution of WebWorkers.
|
|
||||||
* @memberof platform/execution
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
function WorkerService($window, workers) {
|
|
||||||
var workerUrls = {},
|
|
||||||
sharedWorkers = {};
|
|
||||||
|
|
||||||
function addWorker(worker) {
|
|
||||||
var key = worker.key;
|
|
||||||
if (!workerUrls[key]) {
|
|
||||||
if (worker.scriptUrl) {
|
|
||||||
workerUrls[key] = [
|
|
||||||
worker.bundle.path,
|
|
||||||
worker.bundle.sources,
|
|
||||||
worker.scriptUrl
|
|
||||||
].join("/");
|
|
||||||
} else if (worker.scriptText) {
|
|
||||||
var blob = new Blob(
|
|
||||||
[worker.scriptText],
|
|
||||||
{type: 'application/javascript'}
|
|
||||||
);
|
|
||||||
workerUrls[key] = URL.createObjectURL(blob);
|
|
||||||
}
|
|
||||||
|
|
||||||
sharedWorkers[key] = worker.shared;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(workers || []).forEach(addWorker);
|
|
||||||
this.workerUrls = workerUrls;
|
|
||||||
this.sharedWorkers = sharedWorkers;
|
|
||||||
this.Worker = $window.Worker;
|
|
||||||
this.SharedWorker = $window.SharedWorker;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start running a new web worker. This will run a worker
|
|
||||||
* that has been registered under the `workers` category
|
|
||||||
* of extension.
|
|
||||||
*
|
|
||||||
* This will return either a Worker or a SharedWorker,
|
|
||||||
* depending on whether a `shared` flag has been specified
|
|
||||||
* on the the extension definition for the referenced worker.
|
|
||||||
*
|
|
||||||
* @param {string} key symbolic identifier for the worker
|
|
||||||
* @returns {Worker | SharedWorker} the running Worker
|
|
||||||
*/
|
|
||||||
WorkerService.prototype.run = function (key) {
|
|
||||||
var scriptUrl = this.workerUrls[key],
|
|
||||||
Worker = this.sharedWorkers[key]
|
|
||||||
? this.SharedWorker : this.Worker;
|
|
||||||
|
|
||||||
return scriptUrl && Worker && new Worker(scriptUrl);
|
|
||||||
};
|
|
||||||
|
|
||||||
return WorkerService;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
@ -1,105 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*
|
|
||||||
* Open MCT includes source code licensed under additional open source
|
|
||||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
|
||||||
* this source code distribution or the Licensing information page available
|
|
||||||
* at runtime from the About dialog for additional information.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
define(
|
|
||||||
["../src/WorkerService"],
|
|
||||||
function (WorkerService) {
|
|
||||||
|
|
||||||
describe("The worker service", function () {
|
|
||||||
var mockWindow,
|
|
||||||
testWorkers,
|
|
||||||
mockWorker,
|
|
||||||
mockSharedWorker,
|
|
||||||
service;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
mockWindow = jasmine.createSpyObj(
|
|
||||||
'$window',
|
|
||||||
['Worker', 'SharedWorker']
|
|
||||||
);
|
|
||||||
testWorkers = [
|
|
||||||
{
|
|
||||||
key: 'abc',
|
|
||||||
scriptUrl: 'c.js',
|
|
||||||
bundle: {
|
|
||||||
path: 'a',
|
|
||||||
sources: 'b'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'xyz',
|
|
||||||
scriptUrl: 'z.js',
|
|
||||||
bundle: {
|
|
||||||
path: 'x',
|
|
||||||
sources: 'y'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'xyz',
|
|
||||||
scriptUrl: 'bad.js',
|
|
||||||
bundle: {
|
|
||||||
path: 'bad',
|
|
||||||
sources: 'bad'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'a-shared-worker',
|
|
||||||
shared: true,
|
|
||||||
scriptUrl: 'c.js',
|
|
||||||
bundle: {
|
|
||||||
path: 'a',
|
|
||||||
sources: 'b'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
mockWorker = {};
|
|
||||||
mockSharedWorker = {};
|
|
||||||
|
|
||||||
mockWindow.Worker.and.returnValue(mockWorker);
|
|
||||||
mockWindow.SharedWorker.and.returnValue(mockSharedWorker);
|
|
||||||
|
|
||||||
service = new WorkerService(mockWindow, testWorkers);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("instantiates workers at registered paths", function () {
|
|
||||||
expect(service.run('abc')).toBe(mockWorker);
|
|
||||||
expect(mockWindow.Worker).toHaveBeenCalledWith('a/b/c.js');
|
|
||||||
});
|
|
||||||
|
|
||||||
it("prefers the first worker when multiple keys are found", function () {
|
|
||||||
expect(service.run('xyz')).toBe(mockWorker);
|
|
||||||
expect(mockWindow.Worker).toHaveBeenCalledWith('x/y/z.js');
|
|
||||||
});
|
|
||||||
|
|
||||||
it("allows workers to be shared", function () {
|
|
||||||
expect(service.run('a-shared-worker')).toBe(mockSharedWorker);
|
|
||||||
expect(mockWindow.SharedWorker)
|
|
||||||
.toHaveBeenCalledWith('a/b/c.js');
|
|
||||||
});
|
|
||||||
|
|
||||||
it("returns undefined for unknown workers", function () {
|
|
||||||
expect(service.run('def')).toBeUndefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
@ -27,9 +27,7 @@ define([
|
|||||||
"./src/services/SearchAggregator",
|
"./src/services/SearchAggregator",
|
||||||
"./res/templates/search-item.html",
|
"./res/templates/search-item.html",
|
||||||
"./res/templates/search.html",
|
"./res/templates/search.html",
|
||||||
"./res/templates/search-menu.html",
|
"./res/templates/search-menu.html"
|
||||||
"raw-loader!./src/services/GenericSearchWorker.js",
|
|
||||||
"raw-loader!./src/services/BareBonesSearchWorker.js"
|
|
||||||
], function (
|
], function (
|
||||||
SearchController,
|
SearchController,
|
||||||
SearchMenuController,
|
SearchMenuController,
|
||||||
@ -37,9 +35,7 @@ define([
|
|||||||
SearchAggregator,
|
SearchAggregator,
|
||||||
searchItemTemplate,
|
searchItemTemplate,
|
||||||
searchTemplate,
|
searchTemplate,
|
||||||
searchMenuTemplate,
|
searchMenuTemplate
|
||||||
searchWorkerText,
|
|
||||||
BareBonesSearchWorkerText
|
|
||||||
) {
|
) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -55,45 +51,6 @@ define([
|
|||||||
"ROOT"
|
"ROOT"
|
||||||
],
|
],
|
||||||
"priority": "fallback"
|
"priority": "fallback"
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "USE_LEGACY_INDEXER",
|
|
||||||
"value": false,
|
|
||||||
"priority": 2
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"controllers": [
|
|
||||||
{
|
|
||||||
"key": "SearchController",
|
|
||||||
"implementation": SearchController,
|
|
||||||
"depends": [
|
|
||||||
"$scope",
|
|
||||||
"searchService"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "SearchMenuController",
|
|
||||||
"implementation": SearchMenuController,
|
|
||||||
"depends": [
|
|
||||||
"$scope",
|
|
||||||
"types[]"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"representations": [
|
|
||||||
{
|
|
||||||
"key": "search-item",
|
|
||||||
"template": searchItemTemplate
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"templates": [
|
|
||||||
{
|
|
||||||
"key": "search",
|
|
||||||
"template": searchTemplate
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "search-menu",
|
|
||||||
"template": searchMenuTemplate
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"components": [
|
"components": [
|
||||||
@ -105,10 +62,8 @@ define([
|
|||||||
"$q",
|
"$q",
|
||||||
"$log",
|
"$log",
|
||||||
"objectService",
|
"objectService",
|
||||||
"workerService",
|
|
||||||
"topic",
|
"topic",
|
||||||
"GENERIC_SEARCH_ROOTS",
|
"GENERIC_SEARCH_ROOTS",
|
||||||
"USE_LEGACY_INDEXER",
|
|
||||||
"openmct"
|
"openmct"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -121,16 +76,6 @@ define([
|
|||||||
"objectService"
|
"objectService"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
|
||||||
"workers": [
|
|
||||||
{
|
|
||||||
"key": "bareBonesSearchWorker",
|
|
||||||
"scriptText": BareBonesSearchWorkerText
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "genericSearchWorker",
|
|
||||||
"scriptText": searchWorkerText
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,10 +25,12 @@
|
|||||||
*/
|
*/
|
||||||
define([
|
define([
|
||||||
'objectUtils',
|
'objectUtils',
|
||||||
'lodash'
|
'lodash',
|
||||||
|
'raw-loader!./BareBonesSearchWorker.js'
|
||||||
], function (
|
], function (
|
||||||
objectUtils,
|
objectUtils,
|
||||||
_
|
_,
|
||||||
|
BareBonesSearchWorkerText
|
||||||
) {
|
) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,12 +41,13 @@ define([
|
|||||||
* @param $q Angular's $q, for promise consolidation.
|
* @param $q Angular's $q, for promise consolidation.
|
||||||
* @param $log Anglar's $log, for logging.
|
* @param $log Anglar's $log, for logging.
|
||||||
* @param {ObjectService} objectService the object service.
|
* @param {ObjectService} objectService the object service.
|
||||||
* @param {WorkerService} workerService the workerService.
|
|
||||||
* @param {TopicService} topic the topic service.
|
* @param {TopicService} topic the topic service.
|
||||||
* @param {Array} ROOTS An array of object Ids to begin indexing.
|
* @param {Array} ROOTS An array of object Ids to begin indexing.
|
||||||
*/
|
*/
|
||||||
function GenericSearchProvider($q, $log, objectService, workerService, topic, ROOTS, USE_LEGACY_INDEXER, openmct) {
|
|
||||||
var provider = this;
|
function GenericSearchProvider($q, $log, objectService, topic, ROOTS, openmct) {
|
||||||
|
let provider = this;
|
||||||
|
|
||||||
this.$q = $q;
|
this.$q = $q;
|
||||||
this.$log = $log;
|
this.$log = $log;
|
||||||
this.objectService = objectService;
|
this.objectService = objectService;
|
||||||
@ -57,9 +60,7 @@ define([
|
|||||||
|
|
||||||
this.pendingQueries = {};
|
this.pendingQueries = {};
|
||||||
|
|
||||||
this.USE_LEGACY_INDEXER = USE_LEGACY_INDEXER;
|
this.worker = this.startWorker();
|
||||||
|
|
||||||
this.worker = this.startWorker(workerService);
|
|
||||||
this.indexOnMutation(topic);
|
this.indexOnMutation(topic);
|
||||||
|
|
||||||
ROOTS.forEach(function indexRoot(rootId) {
|
ROOTS.forEach(function indexRoot(rootId) {
|
||||||
@ -97,24 +98,23 @@ define([
|
|||||||
* Creates a search worker and attaches handlers.
|
* Creates a search worker and attaches handlers.
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param workerService
|
|
||||||
* @returns worker the created search worker.
|
* @returns worker the created search worker.
|
||||||
*/
|
*/
|
||||||
GenericSearchProvider.prototype.startWorker = function (workerService) {
|
GenericSearchProvider.prototype.startWorker = function () {
|
||||||
var provider = this,
|
let provider = this;
|
||||||
worker;
|
|
||||||
|
|
||||||
if (this.USE_LEGACY_INDEXER) {
|
const blob = new Blob(
|
||||||
worker = workerService.run('genericSearchWorker');
|
[BareBonesSearchWorkerText],
|
||||||
} else {
|
{type: 'application/javascript'}
|
||||||
worker = workerService.run('bareBonesSearchWorker');
|
);
|
||||||
}
|
const objectUrl = URL.createObjectURL(blob);
|
||||||
|
const searchWorker = new Worker(objectUrl);
|
||||||
|
|
||||||
worker.addEventListener('message', function (messageEvent) {
|
searchWorker.addEventListener('message', function (messageEvent) {
|
||||||
provider.onWorkerMessage(messageEvent);
|
provider.onWorkerMessage(messageEvent);
|
||||||
});
|
});
|
||||||
|
|
||||||
return worker;
|
return searchWorker;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,162 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*
|
|
||||||
* Open MCT includes source code licensed under additional open source
|
|
||||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
|
||||||
* this source code distribution or the Licensing information page available
|
|
||||||
* at runtime from the About dialog for additional information.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module defining GenericSearchWorker. Created by shale on 07/21/2015.
|
|
||||||
*/
|
|
||||||
(function () {
|
|
||||||
|
|
||||||
// An array of objects composed of domain object IDs and models
|
|
||||||
// {id: domainObject's ID, model: domainObject's model}
|
|
||||||
var indexedItems = [],
|
|
||||||
TERM_SPLITTER = /[ _*]/;
|
|
||||||
|
|
||||||
function indexItem(id, model) {
|
|
||||||
var vector = {
|
|
||||||
name: model.name
|
|
||||||
};
|
|
||||||
vector.cleanName = model.name.trim();
|
|
||||||
vector.lowerCaseName = vector.cleanName.toLocaleLowerCase();
|
|
||||||
vector.terms = vector.lowerCaseName.split(TERM_SPLITTER);
|
|
||||||
|
|
||||||
indexedItems.push({
|
|
||||||
id: id,
|
|
||||||
vector: vector,
|
|
||||||
model: model,
|
|
||||||
type: model.type
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper function for search()
|
|
||||||
function convertToTerms(input) {
|
|
||||||
var query = {
|
|
||||||
exactInput: input
|
|
||||||
};
|
|
||||||
query.inputClean = input.trim();
|
|
||||||
query.inputLowerCase = query.inputClean.toLocaleLowerCase();
|
|
||||||
query.terms = query.inputLowerCase.split(TERM_SPLITTER);
|
|
||||||
query.exactTerms = query.inputClean.split(TERM_SPLITTER);
|
|
||||||
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets search results from the indexedItems based on provided search
|
|
||||||
* input. Returns matching results from indexedItems
|
|
||||||
*
|
|
||||||
* @param data An object which contains:
|
|
||||||
* * input: The original string which we are searching with
|
|
||||||
* * maxResults: The maximum number of search results desired
|
|
||||||
* * queryId: an id identifying this query, will be returned.
|
|
||||||
*/
|
|
||||||
function search(data) {
|
|
||||||
// This results dictionary will have domain object ID keys which
|
|
||||||
// point to the value the domain object's score.
|
|
||||||
var results,
|
|
||||||
input = data.input,
|
|
||||||
query = convertToTerms(input),
|
|
||||||
message = {
|
|
||||||
request: 'search',
|
|
||||||
results: {},
|
|
||||||
total: 0,
|
|
||||||
queryId: data.queryId
|
|
||||||
},
|
|
||||||
matches = {};
|
|
||||||
|
|
||||||
if (!query.inputClean) {
|
|
||||||
// No search terms, no results;
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Two phases: find matches, then score matches.
|
|
||||||
// Idea being that match finding should be fast, so that future scoring
|
|
||||||
// operations process fewer objects.
|
|
||||||
|
|
||||||
query.terms.forEach(function findMatchingItems(term) {
|
|
||||||
indexedItems
|
|
||||||
.filter(function matchesItem(item) {
|
|
||||||
return item.vector.lowerCaseName.indexOf(term) !== -1;
|
|
||||||
})
|
|
||||||
.forEach(function trackMatch(matchedItem) {
|
|
||||||
if (!matches[matchedItem.id]) {
|
|
||||||
matches[matchedItem.id] = {
|
|
||||||
matchCount: 0,
|
|
||||||
item: matchedItem
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
matches[matchedItem.id].matchCount += 1;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Then, score matching items.
|
|
||||||
results = Object
|
|
||||||
.keys(matches)
|
|
||||||
.map(function asMatches(matchId) {
|
|
||||||
return matches[matchId];
|
|
||||||
})
|
|
||||||
.map(function prioritizeExactMatches(match) {
|
|
||||||
if (match.item.vector.name === query.exactInput) {
|
|
||||||
match.matchCount += 100;
|
|
||||||
} else if (match.item.vector.lowerCaseName
|
|
||||||
=== query.inputLowerCase) {
|
|
||||||
match.matchCount += 50;
|
|
||||||
}
|
|
||||||
|
|
||||||
return match;
|
|
||||||
})
|
|
||||||
.map(function prioritizeCompleteTermMatches(match) {
|
|
||||||
match.item.vector.terms.forEach(function (term) {
|
|
||||||
if (query.terms.indexOf(term) !== -1) {
|
|
||||||
match.matchCount += 0.5;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return match;
|
|
||||||
})
|
|
||||||
.sort(function compare(a, b) {
|
|
||||||
if (a.matchCount > b.matchCount) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (a.matchCount < b.matchCount) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
message.total = results.length;
|
|
||||||
message.results = results
|
|
||||||
.slice(0, data.maxResults);
|
|
||||||
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.onmessage = function (event) {
|
|
||||||
if (event.data.request === 'index') {
|
|
||||||
indexItem(event.data.id, event.data.model);
|
|
||||||
} else if (event.data.request === 'search') {
|
|
||||||
self.postMessage(search(event.data));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}());
|
|
126
platform/search/test/services/BareBonesSearchWorkerSpec.js
Normal file
126
platform/search/test/services/BareBonesSearchWorkerSpec.js
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* 'License'); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SearchSpec. Created by shale on 07/31/2015.
|
||||||
|
*/
|
||||||
|
define([
|
||||||
|
"raw-loader!../../src/services/BareBonesSearchWorker.js"
|
||||||
|
], function (
|
||||||
|
BareBonesSearchWorkerText
|
||||||
|
) {
|
||||||
|
describe('BareBonesSearchWorker', function () {
|
||||||
|
let blob;
|
||||||
|
let objectUrl;
|
||||||
|
let worker;
|
||||||
|
let objectX;
|
||||||
|
let objectY;
|
||||||
|
let objectZ;
|
||||||
|
let itemsToIndex;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
blob = new Blob(
|
||||||
|
[BareBonesSearchWorkerText],
|
||||||
|
{type: 'application/javascript'}
|
||||||
|
);
|
||||||
|
objectUrl = URL.createObjectURL(blob);
|
||||||
|
worker = new Worker(objectUrl);
|
||||||
|
|
||||||
|
objectX = {
|
||||||
|
id: 'x',
|
||||||
|
model: {name: 'object xx'}
|
||||||
|
};
|
||||||
|
objectY = {
|
||||||
|
id: 'y',
|
||||||
|
model: {name: 'object yy'}
|
||||||
|
};
|
||||||
|
objectZ = {
|
||||||
|
id: 'z',
|
||||||
|
model: {name: 'object zz'}
|
||||||
|
};
|
||||||
|
itemsToIndex = [
|
||||||
|
objectX,
|
||||||
|
objectY,
|
||||||
|
objectZ
|
||||||
|
];
|
||||||
|
|
||||||
|
itemsToIndex.forEach(function (item) {
|
||||||
|
worker.postMessage({
|
||||||
|
request: 'index',
|
||||||
|
id: item.id,
|
||||||
|
model: item.model
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function () {
|
||||||
|
blob = undefined;
|
||||||
|
objectUrl = undefined;
|
||||||
|
worker.terminate();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns search results for partial term matches', function (done) {
|
||||||
|
worker.addEventListener('message', function (message) {
|
||||||
|
let data = message.data;
|
||||||
|
|
||||||
|
expect(data.request).toBe('search');
|
||||||
|
expect(data.total).toBe(3);
|
||||||
|
expect(data.queryId).toBe(123);
|
||||||
|
expect(data.results.length).toBe(3);
|
||||||
|
expect(data.results[0].id).toBe('x');
|
||||||
|
expect(data.results[0].name).toEqual(objectX.model.name);
|
||||||
|
expect(data.results[1].id).toBe('y');
|
||||||
|
expect(data.results[1].name).toEqual(objectY.model.name);
|
||||||
|
expect(data.results[2].id).toBe('z');
|
||||||
|
expect(data.results[2].name).toEqual(objectZ.model.name);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
worker.postMessage({
|
||||||
|
request: 'search',
|
||||||
|
input: 'obj',
|
||||||
|
maxResults: 100,
|
||||||
|
queryId: 123
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can find partial term matches', function (done) {
|
||||||
|
worker.addEventListener('message', function (message) {
|
||||||
|
let data = message.data;
|
||||||
|
|
||||||
|
expect(data.queryId).toBe(345);
|
||||||
|
expect(data.results.length).toBe(1);
|
||||||
|
expect(data.results[0].id).toBe('x');
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
worker.postMessage({
|
||||||
|
request: 'search',
|
||||||
|
input: 'x',
|
||||||
|
maxResults: 100,
|
||||||
|
queryId: 345
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -1,209 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
|
||||||
* 'License'); you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*
|
|
||||||
* Open MCT includes source code licensed under additional open source
|
|
||||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
|
||||||
* this source code distribution or the Licensing information page available
|
|
||||||
* at runtime from the About dialog for additional information.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SearchSpec. Created by shale on 07/31/2015.
|
|
||||||
*/
|
|
||||||
define([
|
|
||||||
"raw-loader!../../src/services/GenericSearchWorker.js"
|
|
||||||
], function (
|
|
||||||
GenericSearchWorkerText
|
|
||||||
) {
|
|
||||||
|
|
||||||
var WORKER_FILE = URL.createObjectURL(new Blob(
|
|
||||||
[GenericSearchWorkerText],
|
|
||||||
{type: 'application/javascript'}
|
|
||||||
));
|
|
||||||
|
|
||||||
describe('GenericSearchWorker', function () {
|
|
||||||
// If this test fails, make sure this path is correct
|
|
||||||
var worker,
|
|
||||||
objectX,
|
|
||||||
objectY,
|
|
||||||
objectZ,
|
|
||||||
itemsToIndex;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
worker = new Worker(WORKER_FILE);
|
|
||||||
|
|
||||||
objectX = {
|
|
||||||
id: 'x',
|
|
||||||
model: {name: 'object xx'}
|
|
||||||
};
|
|
||||||
objectY = {
|
|
||||||
id: 'y',
|
|
||||||
model: {name: 'object yy'}
|
|
||||||
};
|
|
||||||
objectZ = {
|
|
||||||
id: 'z',
|
|
||||||
model: {name: 'object zz'}
|
|
||||||
};
|
|
||||||
itemsToIndex = [
|
|
||||||
objectX,
|
|
||||||
objectY,
|
|
||||||
objectZ
|
|
||||||
];
|
|
||||||
|
|
||||||
itemsToIndex.forEach(function (item) {
|
|
||||||
worker.postMessage({
|
|
||||||
request: 'index',
|
|
||||||
id: item.id,
|
|
||||||
model: item.model
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(function () {
|
|
||||||
worker.terminate();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns search results for partial term matches', function (done) {
|
|
||||||
worker.addEventListener('message', function (message) {
|
|
||||||
var data = message.data;
|
|
||||||
expect(data.request).toBe('search');
|
|
||||||
expect(data.total).toBe(3);
|
|
||||||
expect(data.queryId).toBe(123);
|
|
||||||
expect(data.results.length).toBe(3);
|
|
||||||
expect(data.results[0].item.id).toBe('x');
|
|
||||||
expect(data.results[0].item.model).toEqual(objectX.model);
|
|
||||||
expect(data.results[0].matchCount).toBe(1);
|
|
||||||
expect(data.results[1].item.id).toBe('y');
|
|
||||||
expect(data.results[1].item.model).toEqual(objectY.model);
|
|
||||||
expect(data.results[1].matchCount).toBe(1);
|
|
||||||
expect(data.results[2].item.id).toBe('z');
|
|
||||||
expect(data.results[2].item.model).toEqual(objectZ.model);
|
|
||||||
expect(data.results[2].matchCount).toBe(1);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
worker.postMessage({
|
|
||||||
request: 'search',
|
|
||||||
input: 'obj',
|
|
||||||
maxResults: 100,
|
|
||||||
queryId: 123
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('scores exact term matches higher', function (done) {
|
|
||||||
worker.addEventListener('message', function (message) {
|
|
||||||
expect(message.data.queryId).toBe(234);
|
|
||||||
expect(message.data.results.length).toBe(3);
|
|
||||||
expect(message.data.results[0].item.id).toBe('x');
|
|
||||||
expect(message.data.results[0].matchCount).toBe(1.5);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
worker.postMessage({
|
|
||||||
request: 'search',
|
|
||||||
input: 'object',
|
|
||||||
maxResults: 100,
|
|
||||||
queryId: 234
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can find partial term matches', function (done) {
|
|
||||||
worker.addEventListener('message', function (message) {
|
|
||||||
expect(message.data.queryId).toBe(345);
|
|
||||||
expect(message.data.results.length).toBe(1);
|
|
||||||
expect(message.data.results[0].item.id).toBe('x');
|
|
||||||
expect(message.data.results[0].matchCount).toBe(1);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
worker.postMessage({
|
|
||||||
request: 'search',
|
|
||||||
input: 'x',
|
|
||||||
maxResults: 100,
|
|
||||||
queryId: 345
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('matches individual terms', function (done) {
|
|
||||||
worker.addEventListener('message', function (message) {
|
|
||||||
var data = message.data;
|
|
||||||
|
|
||||||
expect(data.queryId).toBe(456);
|
|
||||||
expect(data.results.length).toBe(3);
|
|
||||||
expect(data.results[0].item.id).toBe('x');
|
|
||||||
expect(data.results[0].matchCount).toBe(1);
|
|
||||||
expect(data.results[1].item.id).toBe('y');
|
|
||||||
expect(data.results[1].matchCount).toBe(1);
|
|
||||||
expect(data.results[2].item.id).toBe('z');
|
|
||||||
expect(data.results[1].matchCount).toBe(1);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
worker.postMessage({
|
|
||||||
request: 'search',
|
|
||||||
input: 'x y z',
|
|
||||||
maxResults: 100,
|
|
||||||
queryId: 456
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('scores exact matches highest', function (done) {
|
|
||||||
worker.addEventListener('message', function (message) {
|
|
||||||
var data = message.data;
|
|
||||||
|
|
||||||
expect(data.queryId).toBe(567);
|
|
||||||
expect(data.results.length).toBe(3);
|
|
||||||
expect(data.results[0].item.id).toBe('x');
|
|
||||||
expect(data.results[0].matchCount).toBe(103);
|
|
||||||
expect(data.results[1].matchCount).toBe(1.5);
|
|
||||||
expect(data.results[2].matchCount).toBe(1.5);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
worker.postMessage({
|
|
||||||
request: 'search',
|
|
||||||
input: 'object xx',
|
|
||||||
maxResults: 100,
|
|
||||||
queryId: 567
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('scores multiple term match above single match', function () {
|
|
||||||
worker.addEventListener('message', function (message) {
|
|
||||||
var data = message.data;
|
|
||||||
|
|
||||||
expect(data.queryId).toBe(678);
|
|
||||||
expect(data.results.length).toBe(3);
|
|
||||||
expect(data.results[0].item.id).toBe('x');
|
|
||||||
expect(data.results[0].matchCount).toBe(2);
|
|
||||||
expect(data.results[1].matchCount).toBe(1);
|
|
||||||
expect(data.results[2].matchCount).toBe(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
worker.postMessage({
|
|
||||||
request: 'search',
|
|
||||||
input: 'obj x',
|
|
||||||
maxResults: 100,
|
|
||||||
queryId: 678
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -33,7 +33,6 @@ const DEFAULTS = [
|
|||||||
'platform/commonUI/mobile',
|
'platform/commonUI/mobile',
|
||||||
'platform/commonUI/notification',
|
'platform/commonUI/notification',
|
||||||
'platform/containment',
|
'platform/containment',
|
||||||
'platform/execution',
|
|
||||||
'platform/exporters',
|
'platform/exporters',
|
||||||
'platform/telemetry',
|
'platform/telemetry',
|
||||||
'platform/forms',
|
'platform/forms',
|
||||||
@ -72,7 +71,6 @@ define([
|
|||||||
'../platform/containment/bundle',
|
'../platform/containment/bundle',
|
||||||
'../platform/core/bundle',
|
'../platform/core/bundle',
|
||||||
'../platform/entanglement/bundle',
|
'../platform/entanglement/bundle',
|
||||||
'../platform/execution/bundle',
|
|
||||||
'../platform/exporters/bundle',
|
'../platform/exporters/bundle',
|
||||||
'../platform/features/static-markup/bundle',
|
'../platform/features/static-markup/bundle',
|
||||||
'../platform/forms/bundle',
|
'../platform/forms/bundle',
|
||||||
|
Loading…
Reference in New Issue
Block a user