diff --git a/platform/persistence/queue/src/PersistenceFailureController.js b/platform/persistence/queue/src/PersistenceFailureController.js index 54c957b618..8586854857 100644 --- a/platform/persistence/queue/src/PersistenceFailureController.js +++ b/platform/persistence/queue/src/PersistenceFailureController.js @@ -33,25 +33,25 @@ define( * @memberof platform/persistence/queue */ function PersistenceFailureController() { - return { - /** - * Format a timestamp for display in the dialog. - * @memberof platform/persistence/queue.PersistenceFailureController# - */ - formatTimestamp: function (timestamp) { - return moment.utc(timestamp) - .format(Constants.TIMESTAMP_FORMAT); - }, - /** - * Format a user name for display in the dialog. - * @memberof platform/persistence/queue.PersistenceFailureController# - */ - formatUsername: function (username) { - return username || Constants.UNKNOWN_USER; - } - }; } + /** + * Format a timestamp for display in the dialog. + * @memberof platform/persistence/queue.PersistenceFailureController# + */ + PersistenceFailureController.prototype.formatTimestamp = function (timestamp) { + return moment.utc(timestamp) + .format(Constants.TIMESTAMP_FORMAT); + }; + + /** + * Format a user name for display in the dialog. + * @memberof platform/persistence/queue.PersistenceFailureController# + */ + PersistenceFailureController.prototype.formatUsername = function (username) { + return username || Constants.UNKNOWN_USER; + }; + return PersistenceFailureController; } ); diff --git a/platform/persistence/queue/src/PersistenceFailureHandler.js b/platform/persistence/queue/src/PersistenceFailureHandler.js index 45f4360662..8920ee5543 100644 --- a/platform/persistence/queue/src/PersistenceFailureHandler.js +++ b/platform/persistence/queue/src/PersistenceFailureHandler.js @@ -34,6 +34,24 @@ define( * @memberof platform/persistence/queue */ function PersistenceFailureHandler($q, dialogService) { + this.$q = $q; + this.dialogService = dialogService; + } + + /** + * Handle persistence failures by providing the user with a + * dialog summarizing these failures, and giving the option + * to overwrite/cancel as appropriate. + * @param {Array} failures persistence failures, as prepared + * by PersistenceQueueHandler + * @memberof platform/persistence/queue.PersistenceFailureHandler# + */ + PersistenceFailureHandler.prototype.handle = function handleFailures(failures) { + // Prepare dialog for display + var dialogModel = new PersistenceFailureDialog(failures), + revisionErrors = dialogModel.model.revised, + $q = this.$q; + // Refresh revision information for the domain object associated // with this persistence failure function refresh(failure) { @@ -100,39 +118,20 @@ define( return $q.all(failures.map(discard)); } - // Handle failures in persistence - function handleFailures(failures) { - // Prepare dialog for display - var dialogModel = new PersistenceFailureDialog(failures), - revisionErrors = dialogModel.model.revised; - - // Handle user input (did they choose to overwrite?) - function handleChoice(key) { - // If so, try again - if (key === PersistenceFailureConstants.OVERWRITE_KEY) { - return retry(revisionErrors); - } else { - return discardAll(revisionErrors); - } + // Handle user input (did they choose to overwrite?) + function handleChoice(key) { + // If so, try again + if (key === PersistenceFailureConstants.OVERWRITE_KEY) { + return retry(revisionErrors); + } else { + return discardAll(revisionErrors); } - - // Prompt for user input, the overwrite if they said so. - return dialogService.getUserChoice(dialogModel) - .then(handleChoice, handleChoice); } - return { - /** - * Handle persistence failures by providing the user with a - * dialog summarizing these failures, and giving the option - * to overwrite/cancel as appropriate. - * @param {Array} failures persistence failures, as prepared - * by PersistenceQueueHandler - * @memberof platform/persistence/queue.PersistenceFailureHandler# - */ - handle: handleFailures - }; - } + // Prompt for user input, the overwrite if they said so. + return this.dialogService.getUserChoice(dialogModel) + .then(handleChoice, handleChoice); + }; return PersistenceFailureHandler; } diff --git a/platform/persistence/queue/src/PersistenceQueueHandler.js b/platform/persistence/queue/src/PersistenceQueueHandler.js index 2965edfc80..4d630ce208 100644 --- a/platform/persistence/queue/src/PersistenceQueueHandler.js +++ b/platform/persistence/queue/src/PersistenceQueueHandler.js @@ -38,6 +38,25 @@ define( * @memberof platform/persistence/queue */ function PersistenceQueueHandler($q, failureHandler) { + this.$q = $q; + this.failureHandler = failureHandler; + } + + /** + * Invoke the persist method on the provided persistence + * capabilities. + * @param {Object.} persistences + * capabilities to invoke, in id->capability pairs. + * @param {Object.} domainObjects + * associated domain objects, in id->object pairs. + * @param {PersistenceQueue} queue the persistence queue, + * to requeue as necessary + * @memberof platform/persistence/queue.PersistenceQueueHandler# + */ + PersistenceQueueHandler.prototype.persist = function (persistences, domainObjects, queue) { + var ids = Object.keys(persistences), + $q = this.$q, + failureHandler = this.failureHandler; // Handle a group of persistence invocations function persistGroup(ids, persistences, domainObjects, queue) { @@ -81,33 +100,16 @@ define( // Handle any failures from the full operation function handleFailure(value) { return failures.length > 0 ? - failureHandler.handle(failures) : - value; + failureHandler.handle(failures) : + value; } // Try to persist everything, then handle any failures return $q.all(ids.map(tryPersist)).then(handleFailure); } - - return { - /** - * Invoke the persist method on the provided persistence - * capabilities. - * @param {Object.} persistences - * capabilities to invoke, in id->capability pairs. - * @param {Object.} domainObjects - * associated domain objects, in id->object pairs. - * @param {PersistenceQueue} queue the persistence queue, - * to requeue as necessary - * @memberof platform/persistence/queue.PersistenceQueueHandler# - */ - persist: function (persistences, domainObjects, queue) { - var ids = Object.keys(persistences); - return persistGroup(ids, persistences, domainObjects, queue); - } - }; - } + return persistGroup(ids, persistences, domainObjects, queue); + }; return PersistenceQueueHandler; } diff --git a/platform/persistence/queue/src/PersistenceQueueImpl.js b/platform/persistence/queue/src/PersistenceQueueImpl.js index d0c77ee057..fa68ca864c 100644 --- a/platform/persistence/queue/src/PersistenceQueueImpl.js +++ b/platform/persistence/queue/src/PersistenceQueueImpl.js @@ -44,18 +44,32 @@ define( * @constructor * @memberof platform/persistence/queue */ - function PersistenceQueueImpl($q, $timeout, handler, DELAY) { - var self, - persistences = {}, - objects = {}, - lastObservedSize = 0, - pendingTimeout, - flushPromise, - activeDefer = $q.defer(); + function PersistenceQueueImpl($q, $timeout, handler, delay) { + + this.persistences = {}; + this.objects = {}; + this.lastObservedSize = 0; + this.activeDefer = $q.defer(); + + // If no delay is provided, use a default + this.delay = delay || 0; + this.handler = handler; + this.$timeout = $timeout; + this.$q = $q; + } + + // Schedule a flushing of the queue (that is, plan to flush + // all objects in the queue) + PersistenceQueueImpl.prototype.scheduleFlush = function () { + var self = this, + $timeout = this.$timeout, + $q = this.$q, + handler = this.handler; // Check if the queue's size has stopped increasing) function quiescent() { - return Object.keys(persistences).length === lastObservedSize; + return Object.keys(self.persistences).length + === self.lastObservedSize; } // Persist all queued objects @@ -64,74 +78,71 @@ define( // this will be replaced with a promise for the next round // of persistence calls, so we want to make sure we clear // the correct one when this flush completes. - var flushingDefer = activeDefer; + var flushingDefer = self.activeDefer; // Clear the active promise for a queue flush function clearFlushPromise(value) { - flushPromise = undefined; + self.flushPromise = undefined; flushingDefer.resolve(value); return value; } // Persist all queued objects - flushPromise = handler.persist(persistences, objects, self) - .then(clearFlushPromise, clearFlushPromise); + self.flushPromise = handler.persist( + self.persistences, + self.objects, + self + ).then(clearFlushPromise, clearFlushPromise); // Reset queue, etc. - persistences = {}; - objects = {}; - lastObservedSize = 0; - pendingTimeout = undefined; - activeDefer = $q.defer(); + self.persistences = {}; + self.objects = {}; + self.lastObservedSize = 0; + self.pendingTimeout = undefined; + self.activeDefer = $q.defer(); } - // Schedule a flushing of the queue (that is, plan to flush - // all objects in the queue) - function scheduleFlush() { - function maybeFlush() { - // Timeout fired, so clear it - pendingTimeout = undefined; - // Only flush when we've stopped receiving updates - (quiescent() ? flush : scheduleFlush)(); - // Update lastObservedSize to detect quiescence - lastObservedSize = Object.keys(persistences).length; - } - - // If we are already flushing the queue... - if (flushPromise) { - // Wait until that's over before considering a flush - flushPromise.then(maybeFlush); + function maybeFlush() { + // Timeout fired, so clear it + self.pendingTimeout = undefined; + // Only flush when we've stopped receiving updates + if (quiescent()) { + flush(); } else { - // Otherwise, schedule a flush on a timeout (to give - // a window for other updates to get aggregated) - pendingTimeout = pendingTimeout || - $timeout(maybeFlush, DELAY, false); + self.scheduleFlush(); } - - return activeDefer.promise; + // Update lastObservedSize to detect quiescence + self.lastObservedSize = Object.keys(self.persistences).length; } - // If no delay is provided, use a default - DELAY = DELAY || 0; + // If we are already flushing the queue... + if (self.flushPromise) { + // Wait until that's over before considering a flush + self.flushPromise.then(maybeFlush); + } else { + // Otherwise, schedule a flush on a timeout (to give + // a window for other updates to get aggregated) + self.pendingTimeout = self.pendingTimeout || + $timeout(maybeFlush, self.delay, false); + } - self = { - /** - * Queue persistence of a domain object. - * @param {DomainObject} domainObject the domain object - * @param {PersistenceCapability} persistence the object's - * undecorated persistence capability - * @memberof platform/persistence/queue.PersistenceQueueImpl# - */ - put: function (domainObject, persistence) { - var id = domainObject.getId(); - persistences[id] = persistence; - objects[id] = domainObject; - return scheduleFlush(); - } - }; + return self.activeDefer.promise; + }; - return self; - } + + /** + * Queue persistence of a domain object. + * @param {DomainObject} domainObject the domain object + * @param {PersistenceCapability} persistence the object's + * undecorated persistence capability + * @returns {Promise} a promise which will resolve upon persistence + */ + PersistenceQueueImpl.prototype.put = function (domainObject, persistence) { + var id = domainObject.getId(); + this.persistences[id] = persistence; + this.objects[id] = domainObject; + return this.scheduleFlush(); + }; return PersistenceQueueImpl; } diff --git a/platform/persistence/queue/src/QueuingPersistenceCapabilityDecorator.js b/platform/persistence/queue/src/QueuingPersistenceCapabilityDecorator.js index fddaebfead..a86fe60515 100644 --- a/platform/persistence/queue/src/QueuingPersistenceCapabilityDecorator.js +++ b/platform/persistence/queue/src/QueuingPersistenceCapabilityDecorator.js @@ -40,11 +40,21 @@ define( * * @memberof platform/persistence/queue * @constructor + * @implements {CapabilityService} + * @param {platform/persistence/queue.PersistenceQueue} persistenceQueue + * @param {CapabilityService} the decorated capability service */ function QueuingPersistenceCapabilityDecorator( persistenceQueue, capabilityService ) { + this.persistenceQueue = persistenceQueue; + this.capabilityService = capabilityService; + } + + QueuingPersistenceCapabilityDecorator.prototype.getCapabilities = function (model) { + var capabilityService = this.capabilityService, + persistenceQueue = this.persistenceQueue; function decoratePersistence(capabilities) { var originalPersistence = capabilities.persistence; @@ -53,8 +63,8 @@ define( // Get/instantiate the original var original = (typeof originalPersistence === 'function') ? - originalPersistence(domainObject) : - originalPersistence; + originalPersistence(domainObject) : + originalPersistence; // Provide a decorated version return new QueuingPersistenceCapability( @@ -67,35 +77,10 @@ define( return capabilities; } - function getCapabilities(model) { - return decoratePersistence( - capabilityService.getCapabilities(model) - ); - } - - return { - /** - * Get all capabilities associated with a given domain - * object. - * - * This returns a promise for an object containing key-value - * pairs, where keys are capability names and values are - * either: - * - * * Capability instances - * * Capability constructors (which take a domain object - * as their argument.) - * - * - * @param {*} model the object model - * @returns {Object.} all - * capabilities known to be valid for this model, as - * key-value pairs - * @memberof platform/persistence/queue.QueuingPersistenceCapabilityDecorator# - */ - getCapabilities: getCapabilities - }; - } + return decoratePersistence( + capabilityService.getCapabilities(model) + ); + }; return QueuingPersistenceCapabilityDecorator; }