From c94c2cdc36360e65c76837609fe10ec82ef67cf5 Mon Sep 17 00:00:00 2001 From: lutovich Date: Thu, 15 Dec 2016 11:44:56 +0100 Subject: [PATCH] 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. --- src/v1/transaction.js | 8 ++++- test/v1/transaction.test.js | 64 +++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/v1/transaction.js b/src/v1/transaction.js index cb92c0d6a..466e455ad 100644 --- a/src/v1/transaction.js +++ b/src/v1/transaction.js @@ -99,7 +99,13 @@ class Transaction { } _onError() { - this._onClose(); + // rollback explicitly if tx.run failed, rollback + if (this._state == _states.ACTIVE) { + this.rollback(); + } else { + // else just do the cleanup + this._onClose(); + } this._state = _states.FAILED; } } diff --git a/test/v1/transaction.test.js b/test/v1/transaction.test.js index b2aa334f3..1e6aa3833 100644 --- a/test/v1/transaction.test.js +++ b/test/v1/transaction.test.js @@ -236,4 +236,68 @@ describe('transaction', function() { done(); }); }); + + it('should rollback when very first run fails', done => { + const tx1 = session.beginTransaction(); + tx1.run('RETURN foo') + .catch(error => { + expectSyntaxError(error); + + const tx2 = session.beginTransaction(); + tx2.run('RETURN 1') + .then(result => { + expect(result.records[0].get(0).toNumber()).toEqual(1); + tx2.commit() + .then(() => done()); + }); + }); + }); + + it('should rollback when some run fails', done => { + const tx1 = session.beginTransaction(); + tx1.run('CREATE (:Person)') + .then(() => { + tx1.run('RETURN foo') + .catch(error => { + expectSyntaxError(error); + + const tx2 = session.beginTransaction(); + tx2.run('MATCH (n:Person) RETURN count(n)') + .then(result => { + expect(result.records[0].get(0).toNumber()).toEqual(0); + tx2.commit() + .then(() => done()); + }); + }); + }); + }); + + it('should fail to commit transaction that had run failures', done => { + const tx1 = session.beginTransaction(); + tx1.run('CREATE (:Person)') + .then(() => { + tx1.run('RETURN foo') + .catch(error => { + expectSyntaxError(error); + tx1.commit() + .catch(error => { + const errorMessage = error.error; + const index = errorMessage.indexOf('Cannot commit statements in this transaction'); + expect(index).not.toBeLessThan(0); + + const tx2 = session.beginTransaction(); + tx2.run('MATCH (n:Person) RETURN count(n)') + .then(result => { + expect(result.records[0].get(0).toNumber()).toEqual(0); + done(); + }); + }); + }); + }); + }); + + function expectSyntaxError(error) { + const code = error.fields[0].code; + expect(code).toBe('Neo.ClientError.Statement.SyntaxError'); + } });