[Persistence] Add tests, in-line doc to persistence cache

Add tests and in-line documentation for the caching persistence
decorator, transitioned to support performance of taxonomy provided
by the WARP Server Adapter, WTD-644.
This commit is contained in:
Victor Woeltjen 2015-01-07 10:12:58 -08:00
parent 75a0cbe43d
commit 65a0a92133
2 changed files with 125 additions and 0 deletions

View File

@ -65,26 +65,81 @@ define(
// Provide PersistenceService interface; mostly delegate to the
// decorated service, intervene and cache where appropriate.
return {
/**
* List all persistence spaces that are supported by the
* decorated service.
* @memberof CachingPersistenceDecorator#
* @returns {Promise.<string[]>} spaces supported
*/
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
*/
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
*/
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)
*/
readObject: function (space, key) {
return (cache[space] && cache[space][key]) ?
fastPromise(clone(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
*/
updateObject: function (space, key, value) {
addToCache(space, key, value);
return persistenceService.updateObject(space, key, value);
},
/**
* 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
*/
deleteObject: function (space, key, value) {
if (cache[space]) {
delete cache[space][key];

View File

@ -5,8 +5,78 @@ define(
function (CachingPersistenceDecorator) {
"use strict";
var PERSISTENCE_METHODS = [
"listSpaces",
"listObjects",
"createObject",
"readObject",
"updateObject",
"deleteObject"
];
describe("The caching persistence decorator", function () {
var testSpace,
mockPersistence,
mockCallback,
decorator;
function mockPromise(value) {
return {
then: function (callback) {
return mockPromise(callback(value));
}
};
}
beforeEach(function () {
testSpace = "TEST";
mockPersistence = jasmine.createSpyObj(
"persistenceService",
PERSISTENCE_METHODS
);
mockCallback = jasmine.createSpy("callback");
PERSISTENCE_METHODS.forEach(function (m) {
mockPersistence[m].andReturn(mockPromise({
method: m
}));
});
decorator = new CachingPersistenceDecorator(
testSpace,
mockPersistence
);
});
it("delegates all methods", function () {
PERSISTENCE_METHODS.forEach(function (m) {
// Reset the callback
mockCallback = jasmine.createSpy("callback");
// Invoke the method; avoid using a key that will be cached
decorator[m](testSpace, "testKey" + m, "testValue")
.then(mockCallback);
// Should have gotten that method's plain response
expect(mockCallback).toHaveBeenCalledWith({ method: m });
});
});
it("does not repeat reads of cached objects", function () {
// Perform two reads
decorator.readObject(testSpace, "someKey", "someValue")
.then(mockCallback);
decorator.readObject(testSpace, "someKey", "someValue")
.then(mockCallback);
// Should have only delegated once
expect(mockPersistence.readObject.calls.length).toEqual(1);
// But both promises should have resolved
expect(mockCallback.calls.length).toEqual(2);
});
});
}
);