Skip to content

Commit

Permalink
Adds atomic transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
goatslacker committed Apr 15, 2015
1 parent dbcd5dd commit 868a9ac
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 0 deletions.
124 changes: 124 additions & 0 deletions test/atomic-transactions-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { assert } from 'chai'
import Alt from '../dist/alt-with-runtime'
import atomicTransactions from '../utils/atomicTransactions'

const alt = new Alt()

const atom = atomicTransactions(alt)

const actions = alt.generateActions('fire')

const store1 = alt.createStore(atom({
displayName: 'Store1',

bindListeners: {
fire: actions.fire
},

state: { x: 0 },

fire: function () {
this.state.x = this.state.x + 1
}
}))

const store2 = alt.createStore(atom({
displayName: 'Store2',

bindListeners: {
fire: actions.fire
},

state: { y: 0 },

fire: function () {
this.state.y = this.state.y + 1

if (this.state.y === 2) {
throw new Error('wtf')
}
}
}))

class Store3 {
constructor() {
this.bindListeners({ fire: actions.fire })
this.x = 0
}

fire() {
this.x = this.x + 1
}
}

const store3 = alt.createStore(atom(Store3), 'Store3')

class Store4 {
constructor() {
this.bindListeners({ fire: actions.fire })
this.y = 0
}

fire() {
this.y = this.y + 1

if (this.y === 2) {
throw new Error('wtf')
}
}
}

const store4 = alt.createStore(atom(Store4))

export default {
'atomicTransactions': {
beforeEach() {
alt.recycle()
},

'do not update stores if there is an error'() {
assert(store1.getState().x === 0)
assert(store2.getState().y === 0)

actions.fire()

assert(store1.getState().x === 1)
assert(store2.getState().y === 1)

actions.fire()

assert(store1.getState().x === 1)
assert(store2.getState().y === 1)

actions.fire()

assert(store1.getState().x === 1)
assert(store2.getState().y === 1)
}
},

'classes get the same treatment'() {
assert(store3.getState().x === 0)
assert(store4.getState().y === 0)

actions.fire()

assert(store3.getState().x === 1)
assert(store4.getState().y === 1)

actions.fire()

assert(store3.getState().x === 1)
assert(store4.getState().y === 1)

actions.fire()

assert(store3.getState().x === 1)
assert(store4.getState().y === 1)
},

'store names'() {
assert(atom(class { }).displayName, 'AtomicClass')
assert(atom(class Foo { }).displayName, 'Foo')
},
}
45 changes: 45 additions & 0 deletions utils/atomicTransactions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
var makeFinalStore = require('./makeFinalStore')

// babelHelpers
/*eslint-disable */
/* istanbul ignore next */
var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; };
/*eslint-enable */

function makeAtomicClass(alt, StoreModel) {
function AtomicClass() {
StoreModel.call(this)

this.on('error', function () {
alt.rollback()
})
}
_inherits(AtomicClass, StoreModel)
AtomicClass.displayName = StoreModel.displayName || StoreModel.name || 'AtomicClass'
return AtomicClass
}

function makeAtomicObject(alt, StoreModel) {
StoreModel.lifecycle = StoreModel.lifecycle || {}
StoreModel.lifecycle.error = function () {
alt.rollback()
}
return StoreModel
}


function atomicTransactions(alt) {
var finalStore = makeFinalStore(alt)

finalStore.listen(function () {
alt.takeSnapshot()
})

return function (StoreModel) {
return typeof StoreModel === 'function'
? makeAtomicClass(alt, StoreModel)
: makeAtomicObject(alt, StoreModel)
}
}

module.exports = atomicTransactions

0 comments on commit 868a9ac

Please sign in to comment.