Skip to content

Commit df351e5

Browse files
committed
Keep bookmark returned after auto-commit tx
Auto-commit transactions return bookmarks in Bolt V3. They were previously unused. This PR makes driver extract such bookmarks and expose them via Session#lastBookmark(). It then possible for explicit and auto-commit transactions within the same session to be chained with bookmarks.
1 parent 4513d12 commit df351e5

File tree

2 files changed

+129
-2
lines changed

2 files changed

+129
-2
lines changed

src/v1/session.js

+18-2
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ class Session {
8989
}
9090

9191
_run(statement, parameters, statementRunner) {
92-
const streamObserver = new StreamObserver();
92+
const streamObserver = new SessionStreamObserver(this);
9393
const connectionHolder = this._connectionHolderWithMode(this._mode);
9494
if (!this._hasTx) {
9595
connectionHolder.initializeConnection();
@@ -209,7 +209,6 @@ class Session {
209209
/**
210210
* Update value of the last bookmark.
211211
* @param {Bookmark} newBookmark the new bookmark.
212-
* @private
213212
*/
214213
_updateBookmark(newBookmark) {
215214
if (newBookmark && !newBookmark.isEmpty()) {
@@ -247,6 +246,23 @@ class Session {
247246
}
248247
}
249248

249+
/**
250+
* @private
251+
*/
252+
class SessionStreamObserver extends StreamObserver {
253+
254+
constructor(session) {
255+
super();
256+
this._session = session;
257+
}
258+
259+
onCompleted(meta) {
260+
super.onCompleted(meta);
261+
const bookmark = new Bookmark(meta.bookmark);
262+
this._session._updateBookmark(bookmark);
263+
}
264+
}
265+
250266
function _createTransactionExecutor(config) {
251267
const maxRetryTimeMs = (config && config.maxTransactionRetryTime) ? config.maxTransactionRetryTime : null;
252268
return new TransactionExecutor(maxRetryTimeMs);

test/v1/bolt-v3.test.js

+111
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,117 @@ describe('Bolt V3 API', () => {
256256
expect(() => session.writeTransaction(tx => tx.run('RETURN 1'), {metadata: invalidValue})).toThrow());
257257
});
258258

259+
it('should use bookmarks for auto commit transactions', done => {
260+
if (!databaseSupportsBoltV3()) {
261+
done();
262+
return;
263+
}
264+
265+
const initialBookmark = session.lastBookmark();
266+
267+
session.run('CREATE ()').then(() => {
268+
const bookmark1 = session.lastBookmark();
269+
expect(bookmark1).not.toBeNull();
270+
expect(bookmark1).toBeDefined();
271+
expect(bookmark1).not.toEqual(initialBookmark);
272+
273+
session.run('CREATE ()').then(() => {
274+
const bookmark2 = session.lastBookmark();
275+
expect(bookmark2).not.toBeNull();
276+
expect(bookmark2).toBeDefined();
277+
expect(bookmark2).not.toEqual(initialBookmark);
278+
expect(bookmark2).not.toEqual(bookmark1);
279+
280+
session.run('CREATE ()').then(() => {
281+
const bookmark3 = session.lastBookmark();
282+
expect(bookmark3).not.toBeNull();
283+
expect(bookmark3).toBeDefined();
284+
expect(bookmark3).not.toEqual(initialBookmark);
285+
expect(bookmark3).not.toEqual(bookmark1);
286+
expect(bookmark3).not.toEqual(bookmark2);
287+
288+
done();
289+
});
290+
});
291+
});
292+
});
293+
294+
it('should use bookmarks for auto commit and explicit transactions', done => {
295+
if (!databaseSupportsBoltV3()) {
296+
done();
297+
return;
298+
}
299+
300+
const initialBookmark = session.lastBookmark();
301+
302+
const tx1 = session.beginTransaction();
303+
tx1.run('CREATE ()').then(() => {
304+
tx1.commit().then(() => {
305+
const bookmark1 = session.lastBookmark();
306+
expect(bookmark1).not.toBeNull();
307+
expect(bookmark1).toBeDefined();
308+
expect(bookmark1).not.toEqual(initialBookmark);
309+
310+
session.run('CREATE ()').then(() => {
311+
const bookmark2 = session.lastBookmark();
312+
expect(bookmark2).not.toBeNull();
313+
expect(bookmark2).toBeDefined();
314+
expect(bookmark2).not.toEqual(initialBookmark);
315+
expect(bookmark2).not.toEqual(bookmark1);
316+
317+
const tx2 = session.beginTransaction();
318+
tx2.run('CREATE ()').then(() => {
319+
tx2.commit().then(() => {
320+
const bookmark3 = session.lastBookmark();
321+
expect(bookmark3).not.toBeNull();
322+
expect(bookmark3).toBeDefined();
323+
expect(bookmark3).not.toEqual(initialBookmark);
324+
expect(bookmark3).not.toEqual(bookmark1);
325+
expect(bookmark3).not.toEqual(bookmark2);
326+
327+
done();
328+
});
329+
});
330+
});
331+
});
332+
});
333+
});
334+
335+
it('should use bookmarks for auto commit transactions and transaction functions', done => {
336+
if (!databaseSupportsBoltV3()) {
337+
done();
338+
return;
339+
}
340+
341+
const initialBookmark = session.lastBookmark();
342+
343+
session.writeTransaction(tx => tx.run('CREATE ()')).then(() => {
344+
const bookmark1 = session.lastBookmark();
345+
expect(bookmark1).not.toBeNull();
346+
expect(bookmark1).toBeDefined();
347+
expect(bookmark1).not.toEqual(initialBookmark);
348+
349+
session.run('CREATE ()').then(() => {
350+
const bookmark2 = session.lastBookmark();
351+
expect(bookmark2).not.toBeNull();
352+
expect(bookmark2).toBeDefined();
353+
expect(bookmark2).not.toEqual(initialBookmark);
354+
expect(bookmark2).not.toEqual(bookmark1);
355+
356+
session.writeTransaction(tx => tx.run('CREATE ()')).then(() => {
357+
const bookmark3 = session.lastBookmark();
358+
expect(bookmark3).not.toBeNull();
359+
expect(bookmark3).toBeDefined();
360+
expect(bookmark3).not.toEqual(initialBookmark);
361+
expect(bookmark3).not.toEqual(bookmark1);
362+
expect(bookmark3).not.toEqual(bookmark2);
363+
364+
done();
365+
});
366+
});
367+
});
368+
});
369+
259370
function testTransactionMetadataWithTransactionFunctions(read, done) {
260371
if (!databaseSupportsBoltV3()) {
261372
done();

0 commit comments

Comments
 (0)