diff --git a/platform/core/bundle.json b/platform/core/bundle.json index 952daf5570..330ac1c2b9 100644 --- a/platform/core/bundle.json +++ b/platform/core/bundle.json @@ -66,6 +66,7 @@ "depends": [ "persistenceService", "$q", + "now", "PERSISTENCE_SPACE", "ADDITIONAL_PERSISTENCE_SPACES" ] diff --git a/platform/core/src/models/PersistedModelProvider.js b/platform/core/src/models/PersistedModelProvider.js index a10f818179..c5e2927a96 100644 --- a/platform/core/src/models/PersistedModelProvider.js +++ b/platform/core/src/models/PersistedModelProvider.js @@ -39,14 +39,16 @@ define( * @param {PersistenceService} persistenceService the service in which * domain object models are persisted. * @param $q Angular's $q service, for working with promises + * @param {function} now a function which provides the current time * @param {string} space the name of the persistence space(s) * from which models should be retrieved. * @param {string} spaces additional persistence spaces to use */ - function PersistedModelProvider(persistenceService, $q, space, spaces) { + function PersistedModelProvider(persistenceService, $q, now, space, spaces) { this.persistenceService = persistenceService; this.$q = $q; this.spaces = [space].concat(spaces || []); + this.now = now; } // Take the most recently modified model, for cases where @@ -61,7 +63,9 @@ define( PersistedModelProvider.prototype.getModels = function (ids) { var persistenceService = this.persistenceService, $q = this.$q, - spaces = this.spaces; + spaces = this.spaces, + space = this.space, + now = this.now; // Load a single object model from any persistence spaces function loadModel(id) { @@ -72,11 +76,24 @@ define( }); } + // Ensure that models read from persistence have some + // sensible timestamp indicating they've been persisted. + function addPersistedTimestamp(model) { + if (model && (model.persisted === undefined)) { + model.persisted = model.modified !== undefined ? + model.modified : now(); + } + + return model; + } + // Package the result as id->model function packageResult(models) { var result = {}; ids.forEach(function (id, index) { - result[id] = models[index]; + if (models[index]) { + result[id] = addPersistedTimestamp(models[index]); + } }); return result; } diff --git a/platform/core/test/models/PersistedModelProviderSpec.js b/platform/core/test/models/PersistedModelProviderSpec.js index 8dcb58a400..81769834bf 100644 --- a/platform/core/test/models/PersistedModelProviderSpec.js +++ b/platform/core/test/models/PersistedModelProviderSpec.js @@ -35,6 +35,7 @@ define( SPACE = "space0", spaces = [ "space1" ], modTimes, + mockNow, provider; function mockPromise(value) { @@ -55,19 +56,33 @@ define( beforeEach(function () { modTimes = {}; mockQ = { when: mockPromise, all: mockAll }; - mockPersistenceService = { - readObject: function (space, id) { + mockPersistenceService = jasmine.createSpyObj( + 'persistenceService', + [ + 'createObject', + 'readObject', + 'updateObject', + 'deleteObject', + 'listSpaces', + 'listObjects' + ] + ); + mockNow = jasmine.createSpy("now"); + + mockPersistenceService.readObject + .andCallFake(function (space, id) { return mockPromise({ space: space, id: id, - modified: (modTimes[space] || {})[id] + modified: (modTimes[space] || {})[id], + persisted: 0 }); - } - }; + }); provider = new PersistedModelProvider( mockPersistenceService, mockQ, + mockNow, SPACE, spaces ); @@ -81,12 +96,13 @@ define( }); expect(models).toEqual({ - a: { space: SPACE, id: "a" }, - x: { space: SPACE, id: "x" }, - zz: { space: SPACE, id: "zz" } + a: { space: SPACE, id: "a", persisted: 0 }, + x: { space: SPACE, id: "x", persisted: 0 }, + zz: { space: SPACE, id: "zz", persisted: 0 } }); }); + it("reads object models from multiple spaces", function () { var models; @@ -99,9 +115,36 @@ define( }); expect(models).toEqual({ - a: { space: SPACE, id: "a" }, - x: { space: 'space1', id: "x", modified: 12321 }, - zz: { space: SPACE, id: "zz" } + a: { space: SPACE, id: "a", persisted: 0 }, + x: { space: 'space1', id: "x", modified: 12321, persisted: 0 }, + zz: { space: SPACE, id: "zz", persisted: 0 } + }); + }); + + + it("ensures that persisted timestamps are present", function () { + var mockCallback = jasmine.createSpy("callback"), + testModels = { + a: { modified: 123, persisted: 1984, name: "A" }, + b: { persisted: 1977, name: "B" }, + c: { modified: 42, name: "C" }, + d: { name: "D" } + }; + + mockPersistenceService.readObject.andCallFake( + function (space, id) { + return mockPromise(testModels[id]); + } + ); + mockNow.andReturn(12321); + + provider.getModels(Object.keys(testModels)).then(mockCallback); + + expect(mockCallback).toHaveBeenCalledWith({ + a: { modified: 123, persisted: 1984, name: "A" }, + b: { persisted: 1977, name: "B" }, + c: { modified: 42, persisted: 42, name: "C" }, + d: { persisted: 12321, name: "D" } }); });