diff --git a/src/v1/session.js b/src/v1/session.js index b46645c75..89352de64 100644 --- a/src/v1/session.js +++ b/src/v1/session.js @@ -89,7 +89,7 @@ class Session { } _run(statement, parameters, statementRunner) { - const streamObserver = new StreamObserver(); + const streamObserver = new SessionStreamObserver(this); const connectionHolder = this._connectionHolderWithMode(this._mode); if (!this._hasTx) { connectionHolder.initializeConnection(); @@ -209,7 +209,6 @@ class Session { /** * Update value of the last bookmark. * @param {Bookmark} newBookmark the new bookmark. - * @private */ _updateBookmark(newBookmark) { if (newBookmark && !newBookmark.isEmpty()) { @@ -247,6 +246,23 @@ class Session { } } +/** + * @private + */ +class SessionStreamObserver extends StreamObserver { + + constructor(session) { + super(); + this._session = session; + } + + onCompleted(meta) { + super.onCompleted(meta); + const bookmark = new Bookmark(meta.bookmark); + this._session._updateBookmark(bookmark); + } +} + function _createTransactionExecutor(config) { const maxRetryTimeMs = (config && config.maxTransactionRetryTime) ? config.maxTransactionRetryTime : null; return new TransactionExecutor(maxRetryTimeMs); diff --git a/test/v1/bolt-v3.test.js b/test/v1/bolt-v3.test.js index d36931604..1f947ca84 100644 --- a/test/v1/bolt-v3.test.js +++ b/test/v1/bolt-v3.test.js @@ -256,6 +256,117 @@ describe('Bolt V3 API', () => { expect(() => session.writeTransaction(tx => tx.run('RETURN 1'), {metadata: invalidValue})).toThrow()); }); + it('should use bookmarks for auto commit transactions', done => { + if (!databaseSupportsBoltV3()) { + done(); + return; + } + + const initialBookmark = session.lastBookmark(); + + session.run('CREATE ()').then(() => { + const bookmark1 = session.lastBookmark(); + expect(bookmark1).not.toBeNull(); + expect(bookmark1).toBeDefined(); + expect(bookmark1).not.toEqual(initialBookmark); + + session.run('CREATE ()').then(() => { + const bookmark2 = session.lastBookmark(); + expect(bookmark2).not.toBeNull(); + expect(bookmark2).toBeDefined(); + expect(bookmark2).not.toEqual(initialBookmark); + expect(bookmark2).not.toEqual(bookmark1); + + session.run('CREATE ()').then(() => { + const bookmark3 = session.lastBookmark(); + expect(bookmark3).not.toBeNull(); + expect(bookmark3).toBeDefined(); + expect(bookmark3).not.toEqual(initialBookmark); + expect(bookmark3).not.toEqual(bookmark1); + expect(bookmark3).not.toEqual(bookmark2); + + done(); + }); + }); + }); + }); + + it('should use bookmarks for auto commit and explicit transactions', done => { + if (!databaseSupportsBoltV3()) { + done(); + return; + } + + const initialBookmark = session.lastBookmark(); + + const tx1 = session.beginTransaction(); + tx1.run('CREATE ()').then(() => { + tx1.commit().then(() => { + const bookmark1 = session.lastBookmark(); + expect(bookmark1).not.toBeNull(); + expect(bookmark1).toBeDefined(); + expect(bookmark1).not.toEqual(initialBookmark); + + session.run('CREATE ()').then(() => { + const bookmark2 = session.lastBookmark(); + expect(bookmark2).not.toBeNull(); + expect(bookmark2).toBeDefined(); + expect(bookmark2).not.toEqual(initialBookmark); + expect(bookmark2).not.toEqual(bookmark1); + + const tx2 = session.beginTransaction(); + tx2.run('CREATE ()').then(() => { + tx2.commit().then(() => { + const bookmark3 = session.lastBookmark(); + expect(bookmark3).not.toBeNull(); + expect(bookmark3).toBeDefined(); + expect(bookmark3).not.toEqual(initialBookmark); + expect(bookmark3).not.toEqual(bookmark1); + expect(bookmark3).not.toEqual(bookmark2); + + done(); + }); + }); + }); + }); + }); + }); + + it('should use bookmarks for auto commit transactions and transaction functions', done => { + if (!databaseSupportsBoltV3()) { + done(); + return; + } + + const initialBookmark = session.lastBookmark(); + + session.writeTransaction(tx => tx.run('CREATE ()')).then(() => { + const bookmark1 = session.lastBookmark(); + expect(bookmark1).not.toBeNull(); + expect(bookmark1).toBeDefined(); + expect(bookmark1).not.toEqual(initialBookmark); + + session.run('CREATE ()').then(() => { + const bookmark2 = session.lastBookmark(); + expect(bookmark2).not.toBeNull(); + expect(bookmark2).toBeDefined(); + expect(bookmark2).not.toEqual(initialBookmark); + expect(bookmark2).not.toEqual(bookmark1); + + session.writeTransaction(tx => tx.run('CREATE ()')).then(() => { + const bookmark3 = session.lastBookmark(); + expect(bookmark3).not.toBeNull(); + expect(bookmark3).toBeDefined(); + expect(bookmark3).not.toEqual(initialBookmark); + expect(bookmark3).not.toEqual(bookmark1); + expect(bookmark3).not.toEqual(bookmark2); + + done(); + }); + }); + }); + }); + function testTransactionMetadataWithTransactionFunctions(read, done) { if (!databaseSupportsBoltV3()) { done(); diff --git a/test/v1/session.test.js b/test/v1/session.test.js index a14fd23d0..ace637b55 100644 --- a/test/v1/session.test.js +++ b/test/v1/session.test.js @@ -583,7 +583,9 @@ describe('session', () => { return; } - const bookmarkBefore = session.lastBookmark(); + // new session without initial bookmark + session = driver.session(); + expect(session.lastBookmark()).toBeNull(); const tx = session.beginTransaction(); tx.run('RETURN 42 as answer').then(result => { @@ -592,11 +594,7 @@ describe('session', () => { expect(records[0].get('answer').toNumber()).toEqual(42); tx.commit().then(() => { - const bookmarkAfter = session.lastBookmark(); - expect(bookmarkAfter).toBeDefined(); - expect(bookmarkAfter).not.toBeNull(); - expect(bookmarkAfter).not.toEqual(bookmarkBefore); - + verifyBookmark(session.lastBookmark()); done(); }); }); @@ -631,12 +629,10 @@ describe('session', () => { tx.run('CREATE ()').then(() => { tx.commit().then(() => { const bookmarkBefore = session.lastBookmark(); - expect(bookmarkBefore).toBeDefined(); - expect(bookmarkBefore).not.toBeNull(); + verifyBookmark(bookmarkBefore); session.run('CREATE ()').then(() => { - const bookmarkAfter = session.lastBookmark(); - expect(bookmarkAfter).toEqual(bookmarkBefore); + verifyBookmark(session.lastBookmark()); done(); }); }); @@ -648,17 +644,16 @@ describe('session', () => { return; } - const bookmarkBefore = session.lastBookmark(); + // new session without initial bookmark + session = driver.session(); + expect(session.lastBookmark()).toBeNull(); + const resultPromise = session.readTransaction(tx => tx.run('RETURN 42 AS answer')); resultPromise.then(result => { expect(result.records.length).toEqual(1); expect(result.records[0].get('answer').toNumber()).toEqual(42); - - const bookmarkAfter = session.lastBookmark(); - verifyBookmark(bookmarkAfter); - expect(bookmarkAfter).not.toEqual(bookmarkBefore); - + verifyBookmark(session.lastBookmark()); done(); }); }); diff --git a/test/v1/transaction.test.js b/test/v1/transaction.test.js index 8335aeebe..8085f1ee6 100644 --- a/test/v1/transaction.test.js +++ b/test/v1/transaction.test.js @@ -233,8 +233,11 @@ describe('transaction', () => { return; } - const tx = session.beginTransaction(); + // new session without initial bookmark + session = driver.session(); expect(session.lastBookmark()).toBeNull(); + + const tx = session.beginTransaction(); tx.run("CREATE (:TXNode1)").then(() => { tx.run("CREATE (:TXNode2)").then(() => { tx.commit().then(() => { @@ -250,9 +253,11 @@ describe('transaction', () => { return; } + // new session without initial bookmark + session = driver.session(); expect(session.lastBookmark()).toBeNull(); - const tx1 = session.beginTransaction(); + const tx1 = session.beginTransaction(); tx1.run('CREATE ()').then(() => { tx1.commit().then(() => { expectValidLastBookmark(session); @@ -283,7 +288,10 @@ describe('transaction', () => { return; } + // new session without initial bookmark + session = driver.session(); expect(session.lastBookmark()).toBeNull(); + const tx1 = session.beginTransaction(); tx1.run('CREATE ()').then(() => {