[Code Style] Use prototypes in persistence bundles

WTD-1482
This commit is contained in:
Victor Woeltjen
2015-08-14 15:20:46 -07:00
parent edca2a9f03
commit 3e8ea972c2
5 changed files with 371 additions and 545 deletions

View File

@ -38,71 +38,17 @@ define(
*
* @memberof platform/persistence/cache
* @constructor
* @param {string[]} CACHE_SPACES persistence space names which
* @param {string[]} cacheSpaces persistence space names which
* should be cached
* @param {PersistenceService} persistenceService the service which
* implements object persistence, whose inputs/outputs
* should be cached.
* @implements {PersistenceService}
*/
function CachingPersistenceDecorator(CACHE_SPACES, persistenceService) {
var spaces = CACHE_SPACES || [], // List of spaces to cache
function CachingPersistenceDecorator(cacheSpaces, persistenceService) {
var spaces = cacheSpaces || [], // List of spaces to cache
cache = {}; // Where objects will be stored
// Update the cached instance of an object to a new value
function replaceValue(valueHolder, newValue) {
var v = valueHolder.value;
// If it's a JS object, we want to replace contents, so that
// everybody gets the same instance.
if (typeof v === 'object' && v !== null) {
// Only update contents if these are different instances
if (v !== newValue) {
// Clear prior contents
Object.keys(v).forEach(function (k) {
delete v[k];
});
// Shallow-copy contents
Object.keys(newValue).forEach(function (k) {
v[k] = newValue[k];
});
}
} else {
// Otherwise, just store the new value
valueHolder.value = newValue;
}
}
// Place value in the cache for space, if there is one.
function addToCache(space, key, value) {
if (cache[space]) {
if (cache[space][key]) {
replaceValue(cache[space][key], value);
} else {
cache[space][key] = { value: value };
}
}
}
// Create a function for putting value into a cache;
// useful for then-chaining.
function putCache(space, key) {
return function (value) {
addToCache(space, key, value);
return value;
};
}
// Wrap as a thenable; used instead of $q.when because that
// will resolve on a future tick, which can cause latency
// issues (which this decorator is intended to address.)
function fastPromise(value) {
return {
then: function (callback) {
return fastPromise(callback(value));
}
};
}
// Arrayify list of spaces to cache, if necessary.
spaces = Array.isArray(spaces) ? spaces : [ spaces ];
@ -111,103 +57,107 @@ define(
cache[space] = {};
});
// Provide PersistenceService interface; mostly delegate to the
// decorated service, intervene and cache where appropriate.
this.spaces = spaces;
this.cache = cache;
this.persistenceService = persistenceService;
}
// Wrap as a thenable; used instead of $q.when because that
// will resolve on a future tick, which can cause latency
// issues (which this decorator is intended to address.)
function fastPromise(value) {
return {
/**
* List all persistence spaces that are supported by the
* decorated service.
* @memberof CachingPersistenceDecorator#
* @returns {Promise.<string[]>} spaces supported
* @memberof platform/persistence/cache.CachingPersistenceDecorator#
*/
listSpaces: function () {
return persistenceService.listSpaces();
},
/**
* List all objects in a specific space.
* @memberof CachingPersistenceDecorator#
* @param {string} space the space in which to list objects
* @returns {Promise.<string[]>} keys for objects in this space
* @memberof platform/persistence/cache.CachingPersistenceDecorator#
*/
listObjects: function (space) {
return persistenceService.listObjects(space);
},
/**
* Create an object in a specific space. This will
* be cached to expedite subsequent retrieval.
* @memberof CachingPersistenceDecorator#
* @param {string} space the space in which to create the object
* @param {string} key the key associate with the object for
* subsequent lookup
* @param {object} value a JSONifiable object to store
* @returns {Promise.<boolean>} an indicator of the success or
* failure of this request
* @memberof platform/persistence/cache.CachingPersistenceDecorator#
*/
createObject: function (space, key, value) {
addToCache(space, key, value);
return persistenceService.createObject(space, key, value);
},
/**
* Read an object from a specific space. This will read from a
* cache if the object is available.
* @memberof CachingPersistenceDecorator#
* @param {string} space the space in which to create the object
* @param {string} key the key which identifies the object
* @returns {Promise.<object>} a promise for the object; may
* resolve to undefined (if the object does not exist
* in this space)
* @memberof platform/persistence/cache.CachingPersistenceDecorator#
*/
readObject: function (space, key) {
return (cache[space] && cache[space][key]) ?
fastPromise(cache[space][key].value) :
persistenceService.readObject(space, key)
.then(putCache(space, key));
},
/**
* Update an object in a specific space. This will
* be cached to expedite subsequent retrieval.
* @memberof CachingPersistenceDecorator#
* @param {string} space the space in which to create the object
* @param {string} key the key associate with the object for
* subsequent lookup
* @param {object} value a JSONifiable object to store
* @returns {Promise.<boolean>} an indicator of the success or
* failure of this request
* @memberof platform/persistence/cache.CachingPersistenceDecorator#
*/
updateObject: function (space, key, value) {
return persistenceService.updateObject(space, key, value)
.then(function (result) {
addToCache(space, key, value);
return result;
});
},
/**
* Delete an object in a specific space. This will
* additionally be cleared from the cache.
* @memberof CachingPersistenceDecorator#
* @param {string} space the space in which to create the object
* @param {string} key the key associate with the object for
* subsequent lookup
* @param {object} value a JSONifiable object to delete
* @returns {Promise.<boolean>} an indicator of the success or
* failure of this request
* @memberof platform/persistence/cache.CachingPersistenceDecorator#
*/
deleteObject: function (space, key, value) {
if (cache[space]) {
delete cache[space][key];
}
return persistenceService.deleteObject(space, key, value);
then: function (callback) {
return fastPromise(callback(value));
}
};
}
// Update the cached instance of an object to a new value
function replaceValue(valueHolder, newValue) {
var v = valueHolder.value;
// If it's a JS object, we want to replace contents, so that
// everybody gets the same instance.
if (typeof v === 'object' && v !== null) {
// Only update contents if these are different instances
if (v !== newValue) {
// Clear prior contents
Object.keys(v).forEach(function (k) {
delete v[k];
});
// Shallow-copy contents
Object.keys(newValue).forEach(function (k) {
v[k] = newValue[k];
});
}
} else {
// Otherwise, just store the new value
valueHolder.value = newValue;
}
}
// Place value in the cache for space, if there is one.
CachingPersistenceDecorator.prototype.addToCache = function (space, key, value) {
var cache = this.cache;
if (cache[space]) {
if (cache[space][key]) {
replaceValue(cache[space][key], value);
} else {
cache[space][key] = { value: value };
}
}
};
// Create a function for putting value into a cache;
// useful for then-chaining.
CachingPersistenceDecorator.prototype.putCache = function (space, key) {
var self = this;
return function (value) {
self.addToCache(space, key, value);
return value;
};
};
CachingPersistenceDecorator.prototype.listSpaces = function () {
return this.persistenceService.listSpaces();
};
CachingPersistenceDecorator.prototype.listObjects = function (space) {
return this.persistenceService.listObjects(space);
};
CachingPersistenceDecorator.prototype.createObject = function (space, key, value) {
this.addToCache(space, key, value);
return this.persistenceService.createObject(space, key, value);
};
CachingPersistenceDecorator.prototype.readObject = function (space, key) {
var cache = this.cache;
return (cache[space] && cache[space][key]) ?
fastPromise(cache[space][key].value) :
this.persistenceService.readObject(space, key)
.then(this.putCache(space, key));
};
CachingPersistenceDecorator.prototype.updateObject = function (space, key, value) {
var self = this;
return this.persistenceService.updateObject(space, key, value)
.then(function (result) {
self.addToCache(space, key, value);
return result;
});
};
CachingPersistenceDecorator.prototype.deleteObject = function (space, key, value) {
if (this.cache[space]) {
delete this.cache[space][key];
}
return this.persistenceService.deleteObject(space, key, value);
};
return CachingPersistenceDecorator;
}
);