mirror of
https://github.com/nasa/openmct.git
synced 2025-06-25 10:44:21 +00:00
Compare commits
6 Commits
remove-dep
...
pouchdb-pr
Author | SHA1 | Date | |
---|---|---|---|
2301d43b45 | |||
50016db052 | |||
629ec8950b | |||
bca4eaf9c2 | |||
15ddd43cf0 | |||
0c90b46d6e |
@ -81,7 +81,8 @@
|
||||
openmct.legacyRegistry.enable.bind(openmct.legacyRegistry)
|
||||
);
|
||||
|
||||
openmct.install(openmct.plugins.LocalStorage());
|
||||
// openmct.install(openmct.plugins.LocalStorage());
|
||||
openmct.install(openmct.plugins.PouchDB());
|
||||
openmct.install(openmct.plugins.Espresso());
|
||||
openmct.install(openmct.plugins.MyItems());
|
||||
openmct.install(openmct.plugins.Generator());
|
||||
|
@ -62,6 +62,7 @@
|
||||
"node-sass": "^4.14.1",
|
||||
"painterro": "^1.0.35",
|
||||
"printj": "^1.2.1",
|
||||
"pouchdb": "^7.2.2",
|
||||
"raw-loader": "^0.5.1",
|
||||
"request": "^2.69.0",
|
||||
"split": "^1.0.0",
|
||||
|
222
src/plugins/persistence/pouchdb/PouchObjectProvider.js
Normal file
222
src/plugins/persistence/pouchdb/PouchObjectProvider.js
Normal file
@ -0,0 +1,222 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2020, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
import CouchDocument from "../couch/CouchDocument";
|
||||
import CouchObjectQueue from "../couch/CouchObjectQueue";
|
||||
import PouchDB from 'pouchdb';
|
||||
|
||||
const REV = "_rev";
|
||||
const ID = "_id";
|
||||
const HEARTBEAT = 50000;
|
||||
|
||||
export default class CouchObjectProvider {
|
||||
// options {
|
||||
// url: couchdb url,
|
||||
// disableObserve: disable auto feed from couchdb to keep objects in sync,
|
||||
// filter: selector to find objects to sync in couchdb
|
||||
// }
|
||||
constructor(openmct, options, namespace) {
|
||||
options = this._normalize(options);
|
||||
this.openmct = openmct;
|
||||
this.url = options.url;
|
||||
this.remoteCouch = options.remoteCouch;
|
||||
this.namespace = namespace;
|
||||
this.objectQueue = {};
|
||||
this.observers = {};
|
||||
|
||||
this.pouchdb = new PouchDB(options.name);
|
||||
this.observeChanges();
|
||||
|
||||
let replicateOptions = {live: true};
|
||||
this.pouchdb.replicate.to(this.remoteCouch, replicateOptions, this.logError);
|
||||
this.pouchdb.replicate.from(this.remoteCouch, replicateOptions, this.logError);
|
||||
}
|
||||
|
||||
//backwards compatibility, options used to be a url. Now it's an object
|
||||
_normalize(options) {
|
||||
if (typeof options === 'string') {
|
||||
return {
|
||||
url: options
|
||||
};
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
observeChanges() {
|
||||
this.pouchdb.changes({
|
||||
since: 'now',
|
||||
live: true
|
||||
}).on('change', this.updateObject.bind(this));
|
||||
}
|
||||
|
||||
observe(identifier, callback) {
|
||||
const keyString = this.openmct.objects.makeKeyString(identifier);
|
||||
this.observers[keyString] = this.observers[keyString] || [];
|
||||
this.observers[keyString].push(callback);
|
||||
|
||||
return () => {
|
||||
this.observers[keyString] = this.observers[keyString].filter(observer => observer !== callback);
|
||||
};
|
||||
}
|
||||
|
||||
logError(error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
async updateObject(response) {
|
||||
const object = {};
|
||||
object.identifier = {
|
||||
namespace: this.namespace,
|
||||
key: response.id
|
||||
};
|
||||
let keyString = this.openmct.objects.makeKeyString(object.identifier);
|
||||
let observersForObject = this.observers[keyString];
|
||||
|
||||
if (observersForObject) {
|
||||
observersForObject.forEach(async (observer) => {
|
||||
const updatedObject = await this.get(object.identifier);
|
||||
observer(updatedObject);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Check the response to a create/update/delete request;
|
||||
// track the rev if it's valid, otherwise return false to
|
||||
// indicate that the request failed.
|
||||
// persist any queued objects
|
||||
checkResponse(response, intermediateResponse) {
|
||||
let requestSuccess = false;
|
||||
const id = response ? response.id : undefined;
|
||||
let rev;
|
||||
if (response && response.ok) {
|
||||
rev = response.rev;
|
||||
requestSuccess = true;
|
||||
}
|
||||
|
||||
intermediateResponse.resolve(requestSuccess);
|
||||
|
||||
if (id) {
|
||||
if (!this.objectQueue[id]) {
|
||||
this.objectQueue[id] = new CouchObjectQueue(undefined, rev);
|
||||
}
|
||||
|
||||
this.objectQueue[id].updateRevision(rev);
|
||||
this.objectQueue[id].pending = false;
|
||||
if (this.objectQueue[id].hasNext()) {
|
||||
this.updateQueued(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getModel(response) {
|
||||
if (response && response.model) {
|
||||
let key = response[ID];
|
||||
let object = response.model;
|
||||
object.identifier = {
|
||||
namespace: this.namespace,
|
||||
key: key
|
||||
};
|
||||
if (!this.objectQueue[key]) {
|
||||
this.objectQueue[key] = new CouchObjectQueue(undefined, response[REV]);
|
||||
}
|
||||
|
||||
this.objectQueue[key].updateRevision(response[REV]);
|
||||
|
||||
return object;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
get(identifier, abortSignal) {
|
||||
return this.pouchdb.get(identifier.key).then(this.getModel.bind(this));
|
||||
}
|
||||
|
||||
abortGetChanges() {
|
||||
if (this.controller) {
|
||||
this.controller.abort();
|
||||
this.controller = undefined;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
getIntermediateResponse() {
|
||||
let intermediateResponse = {};
|
||||
intermediateResponse.promise = new Promise(function (resolve, reject) {
|
||||
intermediateResponse.resolve = resolve;
|
||||
intermediateResponse.reject = reject;
|
||||
});
|
||||
|
||||
return intermediateResponse;
|
||||
}
|
||||
|
||||
enqueueObject(key, model, intermediateResponse) {
|
||||
if (this.objectQueue[key]) {
|
||||
this.objectQueue[key].enqueue({
|
||||
model,
|
||||
intermediateResponse
|
||||
});
|
||||
} else {
|
||||
this.objectQueue[key] = new CouchObjectQueue({
|
||||
model,
|
||||
intermediateResponse
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
create(model) {
|
||||
let intermediateResponse = this.getIntermediateResponse();
|
||||
const key = model.identifier.key;
|
||||
this.enqueueObject(key, model, intermediateResponse);
|
||||
this.objectQueue[key].pending = true;
|
||||
const queued = this.objectQueue[key].dequeue();
|
||||
let document = new CouchDocument(key, queued.model);
|
||||
this.pouchdb.put(document).then((response) => {
|
||||
this.checkResponse(response, queued.intermediateResponse);
|
||||
});
|
||||
|
||||
return intermediateResponse.promise;
|
||||
}
|
||||
|
||||
updateQueued(key) {
|
||||
if (!this.objectQueue[key].pending) {
|
||||
this.objectQueue[key].pending = true;
|
||||
const queued = this.objectQueue[key].dequeue();
|
||||
let document = new CouchDocument(key, queued.model, this.objectQueue[key].rev);
|
||||
|
||||
this.pouchdb.put(document).then((response) => {
|
||||
this.checkResponse(response, queued.intermediateResponse);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
update(model) {
|
||||
let intermediateResponse = this.getIntermediateResponse();
|
||||
const key = model.identifier.key;
|
||||
this.enqueueObject(key, model, intermediateResponse);
|
||||
this.updateQueued(key);
|
||||
|
||||
return intermediateResponse.promise;
|
||||
}
|
||||
}
|
34
src/plugins/persistence/pouchdb/plugin.js
Normal file
34
src/plugins/persistence/pouchdb/plugin.js
Normal file
@ -0,0 +1,34 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2020, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
import PouchObjectProvider from './PouchObjectProvider';
|
||||
const NAMESPACE = '';
|
||||
const PERSISTENCE_SPACE = 'mct';
|
||||
|
||||
export default function PouchPlugin(options) {
|
||||
return function install(openmct) {
|
||||
options = options || {name: 'openmct', remoteCouch: 'http://127.0.0.1:5984/openmct'};
|
||||
|
||||
install.pouchProvider = new PouchObjectProvider(openmct, options, NAMESPACE);
|
||||
openmct.objects.addProvider(PERSISTENCE_SPACE, install.pouchProvider);
|
||||
};
|
||||
}
|
@ -65,7 +65,8 @@ define([
|
||||
'./interceptors/plugin',
|
||||
'./performanceIndicator/plugin',
|
||||
'./CouchDBSearchFolder/plugin',
|
||||
'./timeline/plugin'
|
||||
'./timeline/plugin',
|
||||
'./persistence/pouchdb/plugin'
|
||||
], function (
|
||||
_,
|
||||
UTCTimeSystem,
|
||||
@ -111,7 +112,8 @@ define([
|
||||
ObjectInterceptors,
|
||||
PerformanceIndicator,
|
||||
CouchDBSearchFolder,
|
||||
Timeline
|
||||
Timeline,
|
||||
PouchDB
|
||||
) {
|
||||
const bundleMap = {
|
||||
LocalStorage: 'platform/persistence/local',
|
||||
@ -212,6 +214,7 @@ define([
|
||||
plugins.PerformanceIndicator = PerformanceIndicator.default;
|
||||
plugins.CouchDBSearchFolder = CouchDBSearchFolder.default;
|
||||
plugins.Timeline = Timeline.default;
|
||||
plugins.PouchDB = PouchDB.default;
|
||||
|
||||
return plugins;
|
||||
});
|
||||
|
Reference in New Issue
Block a user