Compare commits

...

3 Commits

Author SHA1 Message Date
Victor Woeltjen
d1d875463a [Models] Broadcast events on persist/refresh 2016-11-07 15:35:38 -08:00
Victor Woeltjen
6738e6bc97 [Models] Evict models on persistence/refresh events 2016-11-07 15:29:04 -08:00
Victor Woeltjen
4ed2438c2a [Models] Convert caching decorator to provider
...such that non-cached providers will be preferred. Changed to
begin investigating various model consistency issues, including
2016-11-07 15:23:12 -08:00
5 changed files with 109 additions and 122 deletions

View File

@@ -28,7 +28,7 @@ define([
"./src/models/ModelAggregator",
"./src/models/ModelCacheService",
"./src/models/PersistedModelProvider",
"./src/models/CachingModelDecorator",
"./src/models/CachedModelProvider",
"./src/models/MissingModelDecorator",
"./src/types/TypeProvider",
"./src/actions/ActionProvider",
@@ -46,6 +46,7 @@ define([
"./src/capabilities/MutationCapability",
"./src/capabilities/DelegationCapability",
"./src/capabilities/InstantiationCapability",
"./src/runs/CachedModelEvictor",
"./src/runs/TransactingMutationListener",
"./src/services/Now",
"./src/services/Throttle",
@@ -61,7 +62,7 @@ define([
ModelAggregator,
ModelCacheService,
PersistedModelProvider,
CachingModelDecorator,
CachedModelProvider,
MissingModelDecorator,
TypeProvider,
ActionProvider,
@@ -79,6 +80,7 @@ define([
MutationCapability,
DelegationCapability,
InstantiationCapability,
CachedModelEvictor,
TransactingMutationListener,
Now,
Throttle,
@@ -183,8 +185,9 @@ define([
},
{
"provides": "modelService",
"type": "decorator",
"implementation": CachingModelDecorator,
"type": "provider",
"implementation": CachedModelProvider,
"priority": "fallback",
"depends": [
"cacheService"
]
@@ -333,7 +336,7 @@ define([
"key": "persistence",
"implementation": PersistenceCapability,
"depends": [
"cacheService",
"topic",
"persistenceService",
"identifierService",
"notificationService",

View File

@@ -42,7 +42,7 @@ define(
* @implements {Capability}
*/
function PersistenceCapability(
cacheService,
topic,
persistenceService,
identifierService,
notificationService,
@@ -53,7 +53,7 @@ define(
this.modified = domainObject.getModel().modified;
this.domainObject = domainObject;
this.cacheService = cacheService;
this.topic = topic;
this.identifierService = identifierService;
this.persistenceService = persistenceService;
this.notificationService = notificationService;
@@ -110,6 +110,7 @@ define(
*/
PersistenceCapability.prototype.persist = function () {
var self = this,
persistenceTopic = this.topic('persistence'),
domainObject = this.domainObject,
model = domainObject.getModel(),
modified = model.modified,
@@ -135,6 +136,9 @@ define(
domainObject.getModel()
]).then(function (result) {
return rejectIfFalsey(result, self.$q);
}).then(function (result) {
persistenceTopic.notify(domainObject);
return result;
}).catch(function (error) {
return notifyOnError(error, domainObject, self.notificationService, self.$q);
});
@@ -148,6 +152,7 @@ define(
*/
PersistenceCapability.prototype.refresh = function () {
var domainObject = this.domainObject;
var refreshTopic = this.topic('refresh');
// Update a domain object's model upon refresh
function updateModel(model) {
@@ -164,7 +169,10 @@ define(
return this.persistenceService.readObject(
this.getSpace(),
this.getKey()
).then(updateModel);
).then(updateModel).then(function (result) {
refreshTopic.notify(domainObject);
return result;
});
};
/**

View File

@@ -0,0 +1,45 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, 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(
[],
function () {
/**
* Provides cached domain object models, such as those
* introduced via the `instantiate` service.
* @memberof platform/core
* @constructor
* @param {ModelService} modelService this service to decorate
* @implements {ModelService}
*/
function CachedModelProvider(cacheService) {
this.cacheService = cacheService;
}
CachedModelProvider.prototype.getModels = function (ids) {
return Promise.resolve(this.cacheService.all());
};
return CachedModelProvider;
}
);

View File

@@ -1,114 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, 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(
[],
function () {
/**
* The caching model decorator maintains a cache of loaded domain
* object models, and ensures that duplicate models for the same
* object are not provided.
* @memberof platform/core
* @constructor
* @param {ModelService} modelService this service to decorate
* @implements {ModelService}
*/
function CachingModelDecorator(cacheService, modelService) {
this.cacheService = cacheService;
this.modelService = modelService;
}
// Fast-resolving promise
function fastPromise(value) {
return (value || {}).then ? value : {
then: function (callback) {
return fastPromise(callback(value));
}
};
}
CachingModelDecorator.prototype.getModels = function (ids) {
var cacheService = this.cacheService,
neededIds = ids.filter(function notCached(id) {
return !cacheService.has(id);
});
// Update the cached instance of a model to a new value.
// We update in-place to ensure there is only ever one instance
// of any given model exposed by the modelService as a whole.
function updateModel(id, model) {
var oldModel = cacheService.get(id);
// Same object instance is a possibility, so don't copy
if (oldModel === model) {
return model;
}
// If we'd previously cached an undefined value, or are now
// seeing undefined, replace the item in the cache entirely.
if (oldModel === undefined || model === undefined) {
cacheService.put(id, model);
return model;
}
// Otherwise, empty out the old model...
Object.keys(oldModel).forEach(function (k) {
delete oldModel[k];
});
// ...and replace it with the contents of the new model.
Object.keys(model).forEach(function (k) {
oldModel[k] = model[k];
});
return oldModel;
}
// Store the provided models in our cache
function cacheAll(models) {
Object.keys(models).forEach(function (id) {
var model = cacheService.has(id) ?
updateModel(id, models[id]) : models[id];
cacheService.put(id, model);
});
}
// Expose the cache (for promise chaining)
function giveCache() {
return cacheService.all();
}
// Look up if we have unknown IDs
if (neededIds.length > 0) {
return this.modelService.getModels(neededIds)
.then(cacheAll)
.then(giveCache);
}
// Otherwise, just expose the cache directly
return fastPromise(cacheService.all());
};
return CachingModelDecorator;
}
);

View File

@@ -0,0 +1,45 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web 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 Web 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.
*****************************************************************************/
/*global define*/
define([], function () {
/**
* Listens for mutation on domain objects and triggers persistence when
* it occurs.
* @param {Topic} topic the `topic` service; used to listen for mutation
* @memberof platform/core
*/
function CachedModelEvictor(topic, cacheService) {
this.cacheService = cacheService;
topic('persistence').listen(this.evict.bind(this));
topic('refresh').listen(this.evict.bind(this));
}
/**
* Evict a domain object from the cache.
*/
CachedModelEvictor.prototype.evict = function (domainObject) {
cacheService.remove(domainObject.getId());
};
return CachedModelEvictor;
});