[Persistence] Refactor out Transaction

https://github.com/nasa/openmct/pull/874#issuecomment-233068178
This commit is contained in:
Victor Woeltjen 2016-07-25 16:45:32 -07:00
parent 766e94ed62
commit 6c4419fb72
3 changed files with 82 additions and 66 deletions

View File

@ -0,0 +1,63 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define([], function () {
function Transaction($log) {
this.$log = $log;
this.callbacks = [];
}
Transaction.prototype.add = function (commit, cancel) {
var callback = { commit: commit, cancel: cancel };
this.callbacks.push(callback);
return function () {
this.callbacks = this.callbacks.filter(function (c) {
return c !== callback;
});
}.bind(this);
};
Transaction.prototype.size = function () {
return this.callbacks.length;
};
['commit', 'cancel'].forEach(function (method) {
Transaction.prototype[method] = function () {
var promises = [];
var callback;
while (this.callbacks.length > 0) {
callback = this.callbacks.shift();
try {
promises.push(callback[method]());
} catch (e) {
this.$log
.error("Error trying to " + method + " transaction.");
}
}
return Promise.all(promises);
};
});
return Transaction;
});

View File

@ -21,8 +21,8 @@
*****************************************************************************/ *****************************************************************************/
/*global define*/ /*global define*/
define( define(
[], ['./Transaction'],
function () { function (Transaction) {
/** /**
* Implements an application-wide transaction state. Once a * Implements an application-wide transaction state. Once a
* transaction is started, calls to * transaction is started, calls to
@ -37,10 +37,7 @@ define(
function TransactionService($q, $log) { function TransactionService($q, $log) {
this.$q = $q; this.$q = $q;
this.$log = $log; this.$log = $log;
this.transaction = false; this.transaction = undefined;
this.onCommits = [];
this.onCancels = [];
} }
/** /**
@ -54,14 +51,14 @@ define(
//Log error because this is a programming error if it occurs. //Log error because this is a programming error if it occurs.
this.$log.error("Transaction already in progress"); this.$log.error("Transaction already in progress");
} }
this.transaction = true; this.transaction = new Transaction(this.$log);
}; };
/** /**
* @returns {boolean} If true, indicates that a transaction is in progress * @returns {boolean} If true, indicates that a transaction is in progress
*/ */
TransactionService.prototype.isActive = function () { TransactionService.prototype.isActive = function () {
return this.transaction; return !!this.transaction;
}; };
/** /**
@ -73,23 +70,11 @@ define(
*/ */
TransactionService.prototype.addToTransaction = function (onCommit, onCancel) { TransactionService.prototype.addToTransaction = function (onCommit, onCancel) {
if (this.transaction) { if (this.transaction) {
this.onCommits.push(onCommit); return this.transaction.add(onCommit, onCancel);
if (onCancel) {
this.onCancels.push(onCancel);
}
} else { } else {
//Log error because this is a programming error if it occurs. //Log error because this is a programming error if it occurs.
this.$log.error("No transaction in progress"); this.$log.error("No transaction in progress");
} }
return function () {
this.onCommits = this.onCommits.filter(function (callback) {
return callback !== onCommit;
});
this.onCancels = this.onCancels.filter(function (callback) {
return callback !== onCancel;
});
}.bind(this);
}; };
/** /**
@ -100,24 +85,9 @@ define(
* completed. Will reject if any commit operations fail * completed. Will reject if any commit operations fail
*/ */
TransactionService.prototype.commit = function () { TransactionService.prototype.commit = function () {
var self = this, var transaction = this.transaction;
promises = [], this.transaction = undefined;
onCommit; return transaction && transaction.commit();
while (this.onCommits.length > 0) { // ...using a while in case some onCommit adds to transaction
onCommit = this.onCommits.pop();
try { // ...also don't want to fail mid-loop...
promises.push(onCommit());
} catch (e) {
this.$log.error("Error committing transaction.");
}
}
return this.$q.all(promises).then(function () {
self.transaction = false;
self.onCommits = [];
self.onCancels = [];
});
}; };
/** /**
@ -129,28 +99,13 @@ define(
* @returns {*} * @returns {*}
*/ */
TransactionService.prototype.cancel = function () { TransactionService.prototype.cancel = function () {
var self = this, var transaction = this.transaction;
results = [], this.transaction = undefined;
onCancel; return transaction && transaction.cancel();
while (this.onCancels.length > 0) {
onCancel = this.onCancels.pop();
try {
results.push(onCancel());
} catch (error) {
this.$log.error("Error committing transaction.");
}
}
return this.$q.all(results).then(function () {
self.transaction = false;
self.onCommits = [];
self.onCancels = [];
});
}; };
TransactionService.prototype.size = function () { TransactionService.prototype.size = function () {
return this.onCommits.length; return this.transaction ? this.transaction.size() : 0;
}; };
return TransactionService; return TransactionService;

View File

@ -57,8 +57,7 @@ define(
transactionService.startTransaction(); transactionService.startTransaction();
transactionService.addToTransaction(onCommit, onCancel); transactionService.addToTransaction(onCommit, onCancel);
expect(transactionService.onCommits.length).toBe(1); expect(transactionService.size()).toBe(1);
expect(transactionService.onCancels.length).toBe(1);
}); });
it("size function returns size of commit and cancel queues", function () { it("size function returns size of commit and cancel queues", function () {
@ -85,7 +84,7 @@ define(
}); });
it("commit calls all queued commit functions", function () { it("commit calls all queued commit functions", function () {
expect(transactionService.onCommits.length).toBe(3); expect(transactionService.size()).toBe(3);
transactionService.commit(); transactionService.commit();
onCommits.forEach(function (spy) { onCommits.forEach(function (spy) {
expect(spy).toHaveBeenCalled(); expect(spy).toHaveBeenCalled();
@ -95,8 +94,8 @@ define(
it("commit resets active state and clears queues", function () { it("commit resets active state and clears queues", function () {
transactionService.commit(); transactionService.commit();
expect(transactionService.isActive()).toBe(false); expect(transactionService.isActive()).toBe(false);
expect(transactionService.onCommits.length).toBe(0); expect(transactionService.size()).toBe(0);
expect(transactionService.onCancels.length).toBe(0); expect(transactionService.size()).toBe(0);
}); });
}); });
@ -116,7 +115,7 @@ define(
}); });
it("cancel calls all queued cancel functions", function () { it("cancel calls all queued cancel functions", function () {
expect(transactionService.onCancels.length).toBe(3); expect(transactionService.size()).toBe(3);
transactionService.cancel(); transactionService.cancel();
onCancels.forEach(function (spy) { onCancels.forEach(function (spy) {
expect(spy).toHaveBeenCalled(); expect(spy).toHaveBeenCalled();
@ -126,8 +125,7 @@ define(
it("cancel resets active state and clears queues", function () { it("cancel resets active state and clears queues", function () {
transactionService.cancel(); transactionService.cancel();
expect(transactionService.isActive()).toBe(false); expect(transactionService.isActive()).toBe(false);
expect(transactionService.onCommits.length).toBe(0); expect(transactionService.size()).toBe(0);
expect(transactionService.onCancels.length).toBe(0);
}); });
}); });