[Core] Update capability interfaces

Update capability interfaces for persistence and mutation to
track timestamps of both changes and persistence calls.
Helps distinguish when refreshes should be allowed, which in
turn will be used to support Overwrite behavior when
Save conflicts are detected. WTD-1033.
This commit is contained in:
Victor Woeltjen 2015-03-20 15:20:27 -07:00
parent 1583c871fd
commit 66fd899650
3 changed files with 34 additions and 25 deletions

View File

@ -162,7 +162,8 @@
}, },
{ {
"key": "mutation", "key": "mutation",
"implementation": "capabilities/MutationCapability.js" "implementation": "capabilities/MutationCapability.js",
"depends": [ "now" ]
}, },
{ {
"key": "delegation", "key": "delegation",

View File

@ -50,7 +50,7 @@ define(
* which will expose this capability * which will expose this capability
* @constructor * @constructor
*/ */
function MutationCapability(domainObject) { function MutationCapability(now, domainObject) {
function mutate(mutator, timestamp) { function mutate(mutator, timestamp) {
// Get the object's model and clone it, so the // Get the object's model and clone it, so the
@ -74,7 +74,7 @@ define(
copyValues(model, result); copyValues(model, result);
} }
model.modified = (typeof timestamp === 'number') ? model.modified = (typeof timestamp === 'number') ?
timestamp : Date.now(); timestamp : now();
} }
// Report the result of the mutation // Report the result of the mutation

View File

@ -27,19 +27,29 @@ define(
// Update a domain object's model upon refresh // Update a domain object's model upon refresh
function updateModel(model) { function updateModel(model) {
modified = model.modified; var modified = model.modified;
return domainObject.useCapability("mutation", function () { return domainObject.useCapability("mutation", function () {
return model; return model;
}); }, modified);
} }
// For refresh; update a domain object model, only if there // For refresh; update a domain object model, only if there
// are no unsaved changes. // are no unsaved changes.
function maybeUpdateModel(model) { function updatePersistenceTimestamp() {
// Only update the model if there are no pending changes var modified = domainObject.getModel().modified;
if (domainObject.getModel().modified === modified) { domainObject.useCapability("mutation", function (model) {
updateModel(model); model.persisted = modified;
} }, modified);
}
// Utility function for creating promise-like objects which
// resolve synchronously when possible
function fastPromise(value) {
return (value || {}).then ? value : {
then: function (callback) {
return fastPromise(callback(value));
}
};
} }
return { return {
@ -50,18 +60,13 @@ define(
* if persistence is successful, and rejected * if persistence is successful, and rejected
* if not. * if not.
*/ */
persist: function (hard) { persist: function () {
updatePersistenceTimestamp();
return persistenceService.updateObject( return persistenceService.updateObject(
SPACE, SPACE,
domainObject.getId(), domainObject.getId(),
domainObject.getModel(), domainObject.getModel()
{ check: !hard } );
).then(function (value) {
if (value) {
modified = domainObject.getModel().modified;
}
return value;
});
}, },
/** /**
* Update this domain object to match the latest from * Update this domain object to match the latest from
@ -69,12 +74,15 @@ define(
* @returns {Promise} a promise which will be resolved * @returns {Promise} a promise which will be resolved
* when the update is complete * when the update is complete
*/ */
refresh: function (hard) { refresh: function () {
return persistenceService.readObject( var model = domainObject.getModel();
SPACE, // Only update if we don't have unsaved changes
domainObject.getId(), return (model.modified === model.persisted) ?
{ cache: false } // Disallow cached reads persistenceService.readObject(
).then(hard ? updateModel : maybeUpdateModel); SPACE,
domainObject.getId()
).then(updateModel) :
fastPromise(false);
}, },
/** /**
* Get the space in which this domain object is persisted; * Get the space in which this domain object is persisted;