Skip to content

Commit d5af7b9

Browse files
author
Zhen Li
authored
Merge pull request #172 from oskarhane/1.1-expose-server-info
Expose server info in result summary from sessions and transactions
2 parents ed77f79 + 9a818ce commit d5af7b9

10 files changed

+259
-9
lines changed

src/v1/driver.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ class Driver {
6767
*/
6868
_createConnection(url, release) {
6969
let sessionId = this._sessionIdGenerator++;
70-
let streamObserver = new _ConnectionStreamObserver(this);
7170
let conn = connect(url, this._config);
71+
let streamObserver = new _ConnectionStreamObserver(this, conn);
7272
conn.initialize(this._userAgent, this._token, streamObserver);
7373
conn._id = sessionId;
7474
conn._release = () => release(url, conn);
@@ -172,9 +172,10 @@ class Driver {
172172

173173
/** Internal stream observer used for connection state */
174174
class _ConnectionStreamObserver extends StreamObserver {
175-
constructor(driver) {
175+
constructor(driver, conn) {
176176
super();
177177
this._driver = driver;
178+
this._conn = conn;
178179
this._hasFailed = false;
179180
}
180181

@@ -192,6 +193,9 @@ class _ConnectionStreamObserver extends StreamObserver {
192193
if (this._driver.onCompleted) {
193194
this._driver.onCompleted(message);
194195
}
196+
if (this._conn && message && message.server) {
197+
this._conn.setServerVersion(message.server);
198+
}
195199
}
196200
}
197201

src/v1/internal/connector.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ class Connection {
193193
* to the next pending observer.
194194
*/
195195
this.url = url;
196+
this.server = {address: url};
196197
this._pendingObservers = [];
197198
this._currentObserver = undefined;
198199
this._ch = channel;
@@ -453,6 +454,10 @@ class Connection {
453454
_packable(value) {
454455
return this._packer.packable(value, (err) => this._handleFatalError(err));
455456
}
457+
458+
setServerVersion(version) {
459+
this.server.version = version;
460+
}
456461
}
457462

458463
/**
@@ -464,6 +469,10 @@ class Connection {
464469
*/
465470
function connect( url, config = {}) {
466471
let Ch = config.channel || Channel;
472+
const host = parseHost(url);
473+
const port = parsePort(url) || 7687;
474+
const completeUrl = host + ':' + port;
475+
467476
return new Connection( new Ch({
468477
host: parseHost(url),
469478
port: parsePort(url) || 7687,
@@ -473,7 +482,7 @@ function connect( url, config = {}) {
473482
trust : config.trust || (hasFeature("trust_all_certificates") ? "TRUST_ALL_CERTIFICATES" : "TRUST_CUSTOM_CA_SIGNED_CERTIFICATES"),
474483
trustedCertificates : config.trustedCertificates || [],
475484
knownHosts : config.knownHosts
476-
}), url);
485+
}), completeUrl);
477486
}
478487

479488
export {

src/v1/result-summary.js

+19
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class ResultSummary {
4040
this.plan = metadata.plan || metadata.profile ? new Plan(metadata.plan || metadata.profile) : false;
4141
this.profile = metadata.profile ? new ProfiledPlan(metadata.profile) : false;
4242
this.notifications = this._buildNotifications(metadata.notifications);
43+
this.server = new ServerInfo(metadata.server);
4344
this.resultConsumedAfter = metadata.result_consumed_after;
4445
this.resultAvailableAfter = metadata.result_available_after;
4546
}
@@ -254,6 +255,24 @@ class Notification {
254255
}
255256
}
256257

258+
/**
259+
* Class for exposing server info from a result.
260+
* @access public
261+
*/
262+
class ServerInfo {
263+
/**
264+
* Create a ServerInfo instance
265+
* @constructor
266+
* @param {Object} serverMeta - Object with serverMeta data
267+
*/
268+
constructor(serverMeta) {
269+
if (serverMeta) {
270+
this.address = serverMeta.address;
271+
this.version = serverMeta.version;
272+
}
273+
}
274+
}
275+
257276
const statementType = {
258277
READ_ONLY: 'r',
259278
READ_WRITE: 'rw',

src/v1/session.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,8 @@ class _RunObserver extends StreamObserver {
136136
}
137137

138138
meta() {
139-
return this._meta;
139+
const serverMeta = {server: this._conn.server};
140+
return Object.assign({}, this._meta, serverMeta);
140141
}
141142
}
142143

src/v1/transaction.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,11 @@ class _TransactionStreamObserver extends StreamObserver {
134134
this._tx._onBookmark(bookmark);
135135
}
136136
}
137+
138+
serverMeta() {
139+
const serverMeta = {server: this._conn.server};
140+
return serverMeta;
141+
}
137142
}
138143

139144
/** internal state machine of the transaction*/
@@ -155,7 +160,7 @@ let _states = {
155160
conn.sync();
156161
}).catch(observer.onError);
157162

158-
return new Result( observer, statement, parameters );
163+
return new Result( observer, statement, parameters, () => observer.serverMeta() );
159164
}
160165
},
161166

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
!: AUTO RESET
2+
!: AUTO PULL_ALL
3+
4+
C: INIT "neo4j-javascript/0.0.0-dev" {"credentials": "neo4j", "scheme": "basic", "principal": "neo4j"}
5+
S: SUCCESS {"server": "TheReadServerV1"}
6+
C: RUN "MATCH (n) RETURN n.name" {}
7+
PULL_ALL
8+
S: SUCCESS {"fields": ["n.name"]}
9+
RECORD ["Bob"]
10+
RECORD ["Alice"]
11+
RECORD ["Tina"]
12+
SUCCESS {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
!: AUTO RESET
2+
!: AUTO PULL_ALL
3+
4+
C: INIT "neo4j-javascript/0.0.0-dev" {"credentials": "neo4j", "scheme": "basic", "principal": "neo4j"}
5+
S: SUCCESS {"server": "TheWriteServerV1"}
6+
C: RUN "CREATE (n {name:'Bob'})" {}
7+
PULL_ALL
8+
S: SUCCESS {}
9+
SUCCESS {}

test/v1/routing.driver.boltkit.it.js

+113-4
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,7 @@ describe('routing driver ', function () {
640640
});
641641
});
642642
});
643+
643644
it('should re-use connections', function (done) {
644645
if (!boltkit.BoltKitSupport) {
645646
done();
@@ -674,10 +675,118 @@ describe('routing driver ', function () {
674675
});
675676
});
676677

677-
function newDriver(url) {
678-
// BoltKit currently does not support encryption, create driver with encryption turned off
679-
return neo4j.driver(url, neo4j.auth.basic("neo4j", "neo4j"), {
680-
encrypted: "ENCRYPTION_OFF"
678+
it('should expose server info in cluster', function (done) {
679+
if (!boltkit.BoltKitSupport) {
680+
done();
681+
return;
682+
}
683+
684+
// Given
685+
const kit = new boltkit.BoltKit();
686+
const routingServer = kit.start('./test/resources/boltkit/acquire_endpoints.script', 9001);
687+
const writeServer = kit.start('./test/resources/boltkit/write_server_with_version.script', 9007);
688+
const readServer = kit.start('./test/resources/boltkit/read_server_with_version.script', 9005);
689+
690+
kit.run(function () {
691+
const driver = newDriver("bolt+routing://127.0.0.1:9001");
692+
// When
693+
const readSession = driver.session(neo4j.session.READ);
694+
readSession.run('MATCH (n) RETURN n.name').then(readResult => {
695+
const writeSession = driver.session(neo4j.session.WRITE);
696+
writeSession.run("CREATE (n {name:'Bob'})").then(writeResult => {
697+
const readServerInfo = readResult.summary.server;
698+
const writeServerInfo = writeResult.summary.server;
699+
700+
readSession.close();
701+
writeSession.close();
702+
driver.close();
703+
704+
routingServer.exit(routingServerExitCode => {
705+
writeServer.exit(writeServerExitCode => {
706+
readServer.exit(readServerExitCode => {
707+
708+
expect(readServerInfo.address).toBe('127.0.0.1:9005');
709+
expect(readServerInfo.version).toBe('TheReadServerV1');
710+
711+
expect(writeServerInfo.address).toBe('127.0.0.1:9007');
712+
expect(writeServerInfo.version).toBe('TheWriteServerV1');
713+
714+
expect(routingServerExitCode).toEqual(0);
715+
expect(writeServerExitCode).toEqual(0);
716+
expect(readServerExitCode).toEqual(0);
717+
718+
done();
719+
});
720+
});
721+
});
722+
})
681723
});
724+
});
725+
});
726+
727+
it('should expose server info in cluster using observer', function (done) {
728+
if (!boltkit.BoltKitSupport) {
729+
done();
730+
return;
731+
}
732+
733+
// Given
734+
const kit = new boltkit.BoltKit();
735+
const routingServer = kit.start('./test/resources/boltkit/acquire_endpoints.script', 9001);
736+
const writeServer = kit.start('./test/resources/boltkit/write_server_with_version.script', 9007);
737+
const readServer = kit.start('./test/resources/boltkit/read_server_with_version.script', 9005);
738+
739+
kit.run(function () {
740+
const driver = newDriver("bolt+routing://127.0.0.1:9001");
741+
// When
742+
const readSession = driver.session(neo4j.session.READ);
743+
readSession.run('MATCH (n) RETURN n.name').subscribe({
744+
onNext: () => {
745+
},
746+
onError: () => {
747+
},
748+
onCompleted: readSummary => {
749+
const writeSession = driver.session(neo4j.session.WRITE);
750+
writeSession.run("CREATE (n {name:'Bob'})").subscribe({
751+
onNext: () => {
752+
},
753+
onError: () => {
754+
},
755+
onCompleted: writeSummary => {
756+
readSession.close();
757+
writeSession.close();
758+
driver.close();
759+
760+
routingServer.exit(function (routingServerExitCode) {
761+
writeServer.exit(function (writeServerExitCode) {
762+
readServer.exit(function (readServerExitCode) {
763+
764+
expect(readSummary.server.address).toBe('127.0.0.1:9005');
765+
expect(readSummary.server.version).toBe('TheReadServerV1');
766+
767+
expect(writeSummary.server.address).toBe('127.0.0.1:9007');
768+
expect(writeSummary.server.version).toBe('TheWriteServerV1');
769+
770+
expect(routingServerExitCode).toEqual(0);
771+
expect(writeServerExitCode).toEqual(0);
772+
expect(readServerExitCode).toEqual(0);
773+
774+
done();
775+
});
776+
});
777+
});
778+
}
779+
})
780+
}
781+
});
782+
});
783+
});
784+
785+
function newDriver(url) {
786+
// BoltKit currently does not support encryption, create driver with encryption turned off
787+
return neo4j.driver(url, neo4j.auth.basic("neo4j", "neo4j"), {
788+
encrypted: "ENCRYPTION_OFF"
789+
});
682790
}
791+
683792
});

test/v1/session.test.js

+23
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,29 @@ describe('session', function () {
164164
});
165165
});
166166

167+
it('should expose server info on successful query', function (done) {
168+
//lazy way of checking the version number
169+
//if server has been set we know it is at least
170+
//3.1 (todo actually parse the version string)
171+
if (!server) {
172+
done();
173+
return;
174+
}
175+
176+
// Given
177+
var statement = 'RETURN 1';
178+
179+
// When & Then
180+
session.run(statement)
181+
.then(function (result) {
182+
var sum = result.summary;
183+
expect(sum.server).toBeDefined();
184+
expect(sum.server.address).toEqual('localhost:7687');
185+
expect(sum.server.version).toBeDefined();
186+
done();
187+
});
188+
});
189+
167190
it('should expose execution time information when using 3.1 and onwards', function (done) {
168191

169192
//lazy way of checking the version number

test/v1/transaction.test.js

+59
Original file line numberDiff line numberDiff line change
@@ -296,8 +296,67 @@ describe('transaction', function() {
296296
});
297297
});
298298

299+
it('should expose server info on successful query', function (done) {
300+
if (neo4jVersionOlderThan31(done)) {
301+
return;
302+
}
303+
304+
// Given
305+
const statement = 'RETURN 1';
306+
307+
// When & Then
308+
const tx = session.beginTransaction();
309+
tx.run(statement)
310+
.then(result => {
311+
const sum = result.summary;
312+
expect(sum.server).toBeDefined();
313+
expect(sum.server.address).toEqual('localhost:7687');
314+
expect(sum.server.version).toBeDefined();
315+
});
316+
tx.commit().then(done);
317+
});
318+
319+
it('should expose server info on successful query using observer', function (done) {
320+
if (neo4jVersionOlderThan31(done)) {
321+
return;
322+
}
323+
324+
// Given
325+
const statement = 'RETURN 1';
326+
327+
// When & Then
328+
const tx = session.beginTransaction();
329+
tx.run(statement)
330+
.subscribe({
331+
onNext: record => {
332+
},
333+
onError: error => {
334+
},
335+
onCompleted: summary => {
336+
const server = summary.server;
337+
338+
expect(server).toBeDefined();
339+
expect(server.address).toEqual('localhost:7687');
340+
expect(server.version).toBeDefined();
341+
342+
done();
343+
}
344+
});
345+
});
346+
299347
function expectSyntaxError(error) {
300348
const code = error.fields[0].code;
301349
expect(code).toBe('Neo.ClientError.Statement.SyntaxError');
302350
}
351+
352+
function neo4jVersionOlderThan31(done) {
353+
//lazy way of checking the version number
354+
//if server has been set we know it is at least
355+
//3.1 (todo actually parse the version string)
356+
if (!server) {
357+
done();
358+
return true;
359+
}
360+
return false;
361+
}
303362
});

0 commit comments

Comments
 (0)