Skip to content

Commit c94c2cd

Browse files
committed
Rollback transaction after run failure
Transaction can't continue after the very first run failure. This commit makes sure we send rollback to the server when such failure is detected.
1 parent fd1c85f commit c94c2cd

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

src/v1/transaction.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,13 @@ class Transaction {
9999
}
100100

101101
_onError() {
102-
this._onClose();
102+
// rollback explicitly if tx.run failed, rollback
103+
if (this._state == _states.ACTIVE) {
104+
this.rollback();
105+
} else {
106+
// else just do the cleanup
107+
this._onClose();
108+
}
103109
this._state = _states.FAILED;
104110
}
105111
}

test/v1/transaction.test.js

+64
Original file line numberDiff line numberDiff line change
@@ -236,4 +236,68 @@ describe('transaction', function() {
236236
done();
237237
});
238238
});
239+
240+
it('should rollback when very first run fails', done => {
241+
const tx1 = session.beginTransaction();
242+
tx1.run('RETURN foo')
243+
.catch(error => {
244+
expectSyntaxError(error);
245+
246+
const tx2 = session.beginTransaction();
247+
tx2.run('RETURN 1')
248+
.then(result => {
249+
expect(result.records[0].get(0).toNumber()).toEqual(1);
250+
tx2.commit()
251+
.then(() => done());
252+
});
253+
});
254+
});
255+
256+
it('should rollback when some run fails', done => {
257+
const tx1 = session.beginTransaction();
258+
tx1.run('CREATE (:Person)')
259+
.then(() => {
260+
tx1.run('RETURN foo')
261+
.catch(error => {
262+
expectSyntaxError(error);
263+
264+
const tx2 = session.beginTransaction();
265+
tx2.run('MATCH (n:Person) RETURN count(n)')
266+
.then(result => {
267+
expect(result.records[0].get(0).toNumber()).toEqual(0);
268+
tx2.commit()
269+
.then(() => done());
270+
});
271+
});
272+
});
273+
});
274+
275+
it('should fail to commit transaction that had run failures', done => {
276+
const tx1 = session.beginTransaction();
277+
tx1.run('CREATE (:Person)')
278+
.then(() => {
279+
tx1.run('RETURN foo')
280+
.catch(error => {
281+
expectSyntaxError(error);
282+
tx1.commit()
283+
.catch(error => {
284+
const errorMessage = error.error;
285+
const index = errorMessage.indexOf('Cannot commit statements in this transaction');
286+
expect(index).not.toBeLessThan(0);
287+
288+
const tx2 = session.beginTransaction();
289+
tx2.run('MATCH (n:Person) RETURN count(n)')
290+
.then(result => {
291+
expect(result.records[0].get(0).toNumber()).toEqual(0);
292+
done();
293+
});
294+
});
295+
});
296+
});
297+
});
298+
299+
function expectSyntaxError(error) {
300+
const code = error.fields[0].code;
301+
expect(code).toBe('Neo.ClientError.Statement.SyntaxError');
302+
}
239303
});

0 commit comments

Comments
 (0)