Skip to content

Commit 868a9ac

Browse files
committed
Adds atomic transactions
1 parent dbcd5dd commit 868a9ac

File tree

2 files changed

+169
-0
lines changed

2 files changed

+169
-0
lines changed

test/atomic-transactions-test.js

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import { assert } from 'chai'
2+
import Alt from '../dist/alt-with-runtime'
3+
import atomicTransactions from '../utils/atomicTransactions'
4+
5+
const alt = new Alt()
6+
7+
const atom = atomicTransactions(alt)
8+
9+
const actions = alt.generateActions('fire')
10+
11+
const store1 = alt.createStore(atom({
12+
displayName: 'Store1',
13+
14+
bindListeners: {
15+
fire: actions.fire
16+
},
17+
18+
state: { x: 0 },
19+
20+
fire: function () {
21+
this.state.x = this.state.x + 1
22+
}
23+
}))
24+
25+
const store2 = alt.createStore(atom({
26+
displayName: 'Store2',
27+
28+
bindListeners: {
29+
fire: actions.fire
30+
},
31+
32+
state: { y: 0 },
33+
34+
fire: function () {
35+
this.state.y = this.state.y + 1
36+
37+
if (this.state.y === 2) {
38+
throw new Error('wtf')
39+
}
40+
}
41+
}))
42+
43+
class Store3 {
44+
constructor() {
45+
this.bindListeners({ fire: actions.fire })
46+
this.x = 0
47+
}
48+
49+
fire() {
50+
this.x = this.x + 1
51+
}
52+
}
53+
54+
const store3 = alt.createStore(atom(Store3), 'Store3')
55+
56+
class Store4 {
57+
constructor() {
58+
this.bindListeners({ fire: actions.fire })
59+
this.y = 0
60+
}
61+
62+
fire() {
63+
this.y = this.y + 1
64+
65+
if (this.y === 2) {
66+
throw new Error('wtf')
67+
}
68+
}
69+
}
70+
71+
const store4 = alt.createStore(atom(Store4))
72+
73+
export default {
74+
'atomicTransactions': {
75+
beforeEach() {
76+
alt.recycle()
77+
},
78+
79+
'do not update stores if there is an error'() {
80+
assert(store1.getState().x === 0)
81+
assert(store2.getState().y === 0)
82+
83+
actions.fire()
84+
85+
assert(store1.getState().x === 1)
86+
assert(store2.getState().y === 1)
87+
88+
actions.fire()
89+
90+
assert(store1.getState().x === 1)
91+
assert(store2.getState().y === 1)
92+
93+
actions.fire()
94+
95+
assert(store1.getState().x === 1)
96+
assert(store2.getState().y === 1)
97+
}
98+
},
99+
100+
'classes get the same treatment'() {
101+
assert(store3.getState().x === 0)
102+
assert(store4.getState().y === 0)
103+
104+
actions.fire()
105+
106+
assert(store3.getState().x === 1)
107+
assert(store4.getState().y === 1)
108+
109+
actions.fire()
110+
111+
assert(store3.getState().x === 1)
112+
assert(store4.getState().y === 1)
113+
114+
actions.fire()
115+
116+
assert(store3.getState().x === 1)
117+
assert(store4.getState().y === 1)
118+
},
119+
120+
'store names'() {
121+
assert(atom(class { }).displayName, 'AtomicClass')
122+
assert(atom(class Foo { }).displayName, 'Foo')
123+
},
124+
}

utils/atomicTransactions.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
var makeFinalStore = require('./makeFinalStore')
2+
3+
// babelHelpers
4+
/*eslint-disable */
5+
/* istanbul ignore next */
6+
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; };
7+
/*eslint-enable */
8+
9+
function makeAtomicClass(alt, StoreModel) {
10+
function AtomicClass() {
11+
StoreModel.call(this)
12+
13+
this.on('error', function () {
14+
alt.rollback()
15+
})
16+
}
17+
_inherits(AtomicClass, StoreModel)
18+
AtomicClass.displayName = StoreModel.displayName || StoreModel.name || 'AtomicClass'
19+
return AtomicClass
20+
}
21+
22+
function makeAtomicObject(alt, StoreModel) {
23+
StoreModel.lifecycle = StoreModel.lifecycle || {}
24+
StoreModel.lifecycle.error = function () {
25+
alt.rollback()
26+
}
27+
return StoreModel
28+
}
29+
30+
31+
function atomicTransactions(alt) {
32+
var finalStore = makeFinalStore(alt)
33+
34+
finalStore.listen(function () {
35+
alt.takeSnapshot()
36+
})
37+
38+
return function (StoreModel) {
39+
return typeof StoreModel === 'function'
40+
? makeAtomicClass(alt, StoreModel)
41+
: makeAtomicObject(alt, StoreModel)
42+
}
43+
}
44+
45+
module.exports = atomicTransactions

0 commit comments

Comments
 (0)