diff --git a/src/v1/result-summary.js b/src/v1/result-summary.js index 02936058b..e65a64e60 100644 --- a/src/v1/result-summary.js +++ b/src/v1/result-summary.js @@ -37,6 +37,8 @@ class ResultSummary { this.plan = metadata.plan || metadata.profile ? new Plan(metadata.plan || metadata.profile) : false; this.profile = metadata.profile ? new ProfiledPlan(metadata.profile) : false; this.notifications = this._buildNotifications(metadata.notifications); + this.resultConsumedAfter = metadata.result_consumed_after; + this.resultAvailableAfter = metadata.result_available_after; } _buildNotifications(notifications) { diff --git a/src/v1/result.js b/src/v1/result.js index 46da0ede3..285328747 100644 --- a/src/v1/result.js +++ b/src/v1/result.js @@ -35,12 +35,14 @@ class Result { * @param {StreamObserver} streamObserver * @param {mixed} statement - Cypher statement to execute * @param {Object} parameters - Map with parameters to use in statement + * @param metaSupplier function, when called provides metadata */ - constructor(streamObserver, statement, parameters) { + constructor(streamObserver, statement, parameters, metaSupplier) { this._streamObserver = streamObserver; this._p = null; this._statement = statement; this._parameters = parameters || {}; + this._metaSupplier = metaSupplier || function(){return {};}; } /** @@ -102,7 +104,15 @@ class Result { */ subscribe(observer) { let onCompletedOriginal = observer.onCompleted; + let self = this; let onCompletedWrapper = (metadata) => { + + let additionalMeta = self._metaSupplier(); + for(var key in additionalMeta) { + if (additionalMeta.hasOwnProperty(key)) { + metadata[key] = additionalMeta[key]; + } + } let sum = new ResultSummary(this._statement, this._parameters, metadata); onCompletedOriginal.call(observer, sum); }; diff --git a/src/v1/session.js b/src/v1/session.js index 9f56c88e3..47c933926 100644 --- a/src/v1/session.js +++ b/src/v1/session.js @@ -20,6 +20,7 @@ import StreamObserver from './internal/stream-observer'; import Result from './result'; import Transaction from './transaction'; +import {Integer, int} from "./integer"; import {newError} from "./error"; /** @@ -53,7 +54,7 @@ class Session { parameters = statement.parameters || {}; statement = statement.text; } - let streamObserver = new StreamObserver(); + let streamObserver = new _RunObserver(); if (!this._hasTx) { this._conn.run(statement, parameters, streamObserver); this._conn.pullAll(streamObserver); @@ -63,7 +64,7 @@ class Session { + "session with an open transaction; either run from within the " + "transaction or use a different session.")); } - return new Result( streamObserver, statement, parameters ); + return new Result( streamObserver, statement, parameters, () => streamObserver.meta() ); } /** @@ -103,4 +104,25 @@ class Session { } } +/** Internal stream observer used for transactional results*/ +class _RunObserver extends StreamObserver { + constructor() { + super(); + this._meta = {}; + } + + onCompleted(meta) { + super.onCompleted(meta); + for(var key in meta){ + if(meta.hasOwnProperty(key)){ + this._meta[key]=meta[key]; + } + } + } + + meta() { + return this._meta; + } +} + export default Session; diff --git a/test/v1/session.test.js b/test/v1/session.test.js index e601a0b8a..4b669c119 100644 --- a/test/v1/session.test.js +++ b/test/v1/session.test.js @@ -23,10 +23,13 @@ var Session = require("../../lib/v1/session"); describe('session', function () { - var driver, session; + var driver, session, server; beforeEach(function (done) { driver = neo4j.driver("bolt://localhost", neo4j.auth.basic("neo4j", "neo4j")); + driver.onCompleted = function (meta) { + server = meta['server']; + }; session = driver.session(); session.run("MATCH (n) DETACH DELETE n").then(done); @@ -158,6 +161,28 @@ describe('session', function () { }); }); + it('should expose execution time information when using 3.1 and onwards', function (done) { + + //lazy way of checking the version number + //if server has been set we know it is at least + //3.1 (todo actually parse the version string) + if (!server) { + done(); + return; + } + // Given + var statement = "UNWIND range(1,10000) AS n RETURN n AS number"; + // When & Then + + session.run(statement) + .then(function (result) { + var sum = result.summary; + expect(sum.resultAvailableAfter.toInt()).toBeGreaterThan(0); + expect(sum.resultConsumedAfter.toInt()).toBeGreaterThan(0); + done(); + }); + }); + it('should expose empty parameter map on call with no parameters', function (done) { // Given var statement = "CREATE (n:Label {prop:'string'}) RETURN n"; @@ -305,7 +330,6 @@ describe('session', function () { done(); }) }); - });