Skip to content

Commit 1794618

Browse files
committed
Add BoltProtocolV5x1 with notification filters
1 parent 27df20f commit 1794618

File tree

11 files changed

+1758
-14
lines changed

11 files changed

+1758
-14
lines changed
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/**
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
import BoltProtocolV5x0 from './bolt-protocol-v5x0'
20+
21+
import transformersFactories from './bolt-protocol-v5x1.transformer'
22+
import Transformer from './transformer'
23+
import RequestMessage from './request-message'
24+
import { LoginObserver, ResultStreamObserver } from './stream-observers'
25+
26+
import { internal } from 'neo4j-driver-core'
27+
28+
const {
29+
constants: { BOLT_PROTOCOL_V5_1, FETCH_ALL }
30+
} = internal
31+
32+
export default class BoltProtocol extends BoltProtocolV5x0 {
33+
get version () {
34+
return BOLT_PROTOCOL_V5_1
35+
}
36+
37+
get transformer () {
38+
if (this._transformer === undefined) {
39+
this._transformer = new Transformer(Object.values(transformersFactories).map(create => create(this._config, this._log)))
40+
}
41+
return this._transformer
42+
}
43+
44+
/**
45+
* Initialize a connection with the server
46+
*
47+
* @param {Object} param0 The params
48+
* @param {string} param0.userAgent The user agent
49+
* @param {any} param0.authToken The auth token
50+
* @param {function(error)} param0.onError On error callback
51+
* @param {function(onComplte)} param0.onComplete On complete callback
52+
* @param {?string[]} param0.notificationFilters the filtering for notifications.
53+
* @returns {LoginObserver} The Login observer
54+
*/
55+
initialize ({ userAgent, authToken, onError, onComplete, notificationFilters } = {}) {
56+
const observer = new LoginObserver({
57+
onError: error => this._onLoginError(error, onError),
58+
onCompleted: metadata => this._onLoginCompleted(metadata, onComplete)
59+
})
60+
61+
this.write(
62+
RequestMessage.hello(userAgent, authToken, this._serversideRouting, null, { notificationFilters }),
63+
observer,
64+
true
65+
)
66+
67+
return observer
68+
}
69+
70+
run (
71+
query,
72+
parameters,
73+
{
74+
bookmarks,
75+
txConfig,
76+
database,
77+
mode,
78+
impersonatedUser,
79+
notificationFilters,
80+
beforeKeys,
81+
afterKeys,
82+
beforeError,
83+
afterError,
84+
beforeComplete,
85+
afterComplete,
86+
flush = true,
87+
reactive = false,
88+
fetchSize = FETCH_ALL,
89+
highRecordWatermark = Number.MAX_VALUE,
90+
lowRecordWatermark = Number.MAX_VALUE
91+
} = {}
92+
) {
93+
const observer = new ResultStreamObserver({
94+
server: this._server,
95+
reactive: reactive,
96+
fetchSize: fetchSize,
97+
moreFunction: this._requestMore.bind(this),
98+
discardFunction: this._requestDiscard.bind(this),
99+
beforeKeys,
100+
afterKeys,
101+
beforeError,
102+
afterError,
103+
beforeComplete,
104+
afterComplete,
105+
highRecordWatermark,
106+
lowRecordWatermark
107+
})
108+
109+
const flushRun = reactive
110+
this.write(
111+
RequestMessage.runWithMetadata(query, parameters, {
112+
bookmarks,
113+
txConfig,
114+
database,
115+
mode,
116+
impersonatedUser,
117+
notificationFilters
118+
}),
119+
observer,
120+
flushRun && flush
121+
)
122+
123+
if (!reactive) {
124+
this.write(RequestMessage.pull({ n: fetchSize }), observer, flush)
125+
}
126+
127+
return observer
128+
}
129+
130+
beginTransaction ({
131+
bookmarks,
132+
txConfig,
133+
database,
134+
mode,
135+
impersonatedUser,
136+
notificationFilters,
137+
beforeError,
138+
afterError,
139+
beforeComplete,
140+
afterComplete
141+
} = {}) {
142+
const observer = new ResultStreamObserver({
143+
server: this._server,
144+
beforeError,
145+
afterError,
146+
beforeComplete,
147+
afterComplete
148+
})
149+
observer.prepareToHandleSingleResponse()
150+
151+
this.write(
152+
RequestMessage.begin({ bookmarks, txConfig, database, mode, impersonatedUser, notificationFilters }),
153+
observer,
154+
true
155+
)
156+
157+
return observer
158+
}
159+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
20+
import v5x0 from './bolt-protocol-v5x0.transformer'
21+
22+
export default {
23+
...v5x0
24+
}

packages/bolt-connection/src/bolt/request-message.js

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,16 +104,21 @@ export default class RequestMessage {
104104
* @param {string} userAgent the user agent.
105105
* @param {Object} authToken the authentication token.
106106
* @param {Object} optional server side routing, set to routing context to turn on server side routing (> 4.1)
107+
* @param {?string[]} patchs patches to be applied to the server (valid in 4.3 and 4.4)
108+
* @param {?string[]} notificationFilters the cypher notification filters
107109
* @return {RequestMessage} new HELLO message.
108110
*/
109-
static hello (userAgent, authToken, routing = null, patchs = null) {
111+
static hello (userAgent, authToken, routing = null, patchs = null, { notificationFilters } = {}) {
110112
const metadata = Object.assign({ user_agent: userAgent }, authToken)
111113
if (routing) {
112114
metadata.routing = routing
113115
}
114116
if (patchs) {
115117
metadata.patch_bolt = patchs
116118
}
119+
if (notificationFilters) {
120+
metadata.notifications = notificationFilters
121+
}
117122
return new RequestMessage(
118123
HELLO,
119124
[metadata],
@@ -128,10 +133,11 @@ export default class RequestMessage {
128133
* @param {string} database the database name.
129134
* @param {string} mode the access mode.
130135
* @param {string} impersonatedUser the impersonated user.
136+
* @param {?string[]} notificationFilters the notification filters
131137
* @return {RequestMessage} new BEGIN message.
132138
*/
133-
static begin ({ bookmarks, txConfig, database, mode, impersonatedUser } = {}) {
134-
const metadata = buildTxMetadata(bookmarks, txConfig, database, mode, impersonatedUser)
139+
static begin ({ bookmarks, txConfig, database, mode, impersonatedUser, notificationFilters } = {}) {
140+
const metadata = buildTxMetadata(bookmarks, txConfig, database, mode, impersonatedUser, notificationFilters)
135141
return new RequestMessage(
136142
BEGIN,
137143
[metadata],
@@ -164,14 +170,15 @@ export default class RequestMessage {
164170
* @param {string} database the database name.
165171
* @param {string} mode the access mode.
166172
* @param {string} impersonatedUser the impersonated user.
173+
* @param {?string[]} notificationFilters the notification filters
167174
* @return {RequestMessage} new RUN message with additional metadata.
168175
*/
169176
static runWithMetadata (
170177
query,
171178
parameters,
172-
{ bookmarks, txConfig, database, mode, impersonatedUser } = {}
179+
{ bookmarks, txConfig, database, mode, impersonatedUser, notificationFilters } = {}
173180
) {
174-
const metadata = buildTxMetadata(bookmarks, txConfig, database, mode, impersonatedUser)
181+
const metadata = buildTxMetadata(bookmarks, txConfig, database, mode, impersonatedUser, notificationFilters)
175182
return new RequestMessage(
176183
RUN,
177184
[query, parameters, metadata],
@@ -282,9 +289,10 @@ export default class RequestMessage {
282289
* @param {string} database the database name.
283290
* @param {string} mode the access mode.
284291
* @param {string} impersonatedUser the impersonated user mode.
292+
* @param {?string[]} notificationFilters the notification filters
285293
* @return {Object} a metadata object.
286294
*/
287-
function buildTxMetadata (bookmarks, txConfig, database, mode, impersonatedUser) {
295+
function buildTxMetadata (bookmarks, txConfig, database, mode, impersonatedUser, notificationFilters) {
288296
const metadata = {}
289297
if (!bookmarks.isEmpty()) {
290298
metadata.bookmarks = bookmarks.values()
@@ -301,6 +309,9 @@ function buildTxMetadata (bookmarks, txConfig, database, mode, impersonatedUser)
301309
if (impersonatedUser) {
302310
metadata.imp_user = assertString(impersonatedUser, 'impersonatedUser')
303311
}
312+
if (notificationFilters) {
313+
metadata.notifications = notificationFilters
314+
}
304315
if (mode === ACCESS_MODE_READ) {
305316
metadata.mode = READ_MODE
306317
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`#unit BoltProtocolV5x1 .packable() should pack not pack graph types (Node) 1`] = `"It is not allowed to pass nodes in query parameters, given: (c:a {a:\\"b\\"})"`;
4+
5+
exports[`#unit BoltProtocolV5x1 .packable() should pack not pack graph types (Path) 1`] = `"It is not allowed to pass paths in query parameters, given: [object Object]"`;
6+
7+
exports[`#unit BoltProtocolV5x1 .packable() should pack not pack graph types (Relationship) 1`] = `"It is not allowed to pass relationships in query parameters, given: (e)-[:a {b:\\"c\\"}]->(f)"`;
8+
9+
exports[`#unit BoltProtocolV5x1 .packable() should pack not pack graph types (UnboundRelationship) 1`] = `"It is not allowed to pass unbound relationships in query parameters, given: -[:a {b:\\"c\\"}]->"`;
10+
11+
exports[`#unit BoltProtocolV5x1 .unpack() should not unpack with wrong size (Date with less fields) 1`] = `"Wrong struct size for Date, expected 1 but was 0"`;
12+
13+
exports[`#unit BoltProtocolV5x1 .unpack() should not unpack with wrong size (Date with more fields) 1`] = `"Wrong struct size for Date, expected 1 but was 2"`;
14+
15+
exports[`#unit BoltProtocolV5x1 .unpack() should not unpack with wrong size (DateTimeWithZoneId with less fields) 1`] = `"Wrong struct size for DateTimeWithZoneId, expected 3 but was 2"`;
16+
17+
exports[`#unit BoltProtocolV5x1 .unpack() should not unpack with wrong size (DateTimeWithZoneId with more fields) 1`] = `"Wrong struct size for DateTimeWithZoneId, expected 3 but was 4"`;
18+
19+
exports[`#unit BoltProtocolV5x1 .unpack() should not unpack with wrong size (DateTimeWithZoneOffset with less fields) 1`] = `"Wrong struct size for DateTimeWithZoneOffset, expected 3 but was 2"`;
20+
21+
exports[`#unit BoltProtocolV5x1 .unpack() should not unpack with wrong size (DateTimeWithZoneOffset with more fields) 1`] = `"Wrong struct size for DateTimeWithZoneOffset, expected 3 but was 4"`;
22+
23+
exports[`#unit BoltProtocolV5x1 .unpack() should not unpack with wrong size (Duration with less fields) 1`] = `"Wrong struct size for Duration, expected 4 but was 3"`;
24+
25+
exports[`#unit BoltProtocolV5x1 .unpack() should not unpack with wrong size (Duration with more fields) 1`] = `"Wrong struct size for Duration, expected 4 but was 5"`;
26+
27+
exports[`#unit BoltProtocolV5x1 .unpack() should not unpack with wrong size (LocalDateTime with less fields) 1`] = `"Wrong struct size for LocalDateTime, expected 2 but was 1"`;
28+
29+
exports[`#unit BoltProtocolV5x1 .unpack() should not unpack with wrong size (LocalDateTime with more fields) 1`] = `"Wrong struct size for LocalDateTime, expected 2 but was 3"`;
30+
31+
exports[`#unit BoltProtocolV5x1 .unpack() should not unpack with wrong size (LocalTime with less fields) 1`] = `"Wrong struct size for LocalTime, expected 1 but was 0"`;
32+
33+
exports[`#unit BoltProtocolV5x1 .unpack() should not unpack with wrong size (LocalTime with more fields) 1`] = `"Wrong struct size for LocalTime, expected 1 but was 2"`;
34+
35+
exports[`#unit BoltProtocolV5x1 .unpack() should not unpack with wrong size (Node with less fields) 1`] = `"Wrong struct size for Node, expected 4 but was 3"`;
36+
37+
exports[`#unit BoltProtocolV5x1 .unpack() should not unpack with wrong size (Node with more fields) 1`] = `"Wrong struct size for Node, expected 4 but was 5"`;
38+
39+
exports[`#unit BoltProtocolV5x1 .unpack() should not unpack with wrong size (Path with less fields) 1`] = `"Wrong struct size for Path, expected 3 but was 2"`;
40+
41+
exports[`#unit BoltProtocolV5x1 .unpack() should not unpack with wrong size (Path with more fields) 1`] = `"Wrong struct size for Path, expected 3 but was 4"`;
42+
43+
exports[`#unit BoltProtocolV5x1 .unpack() should not unpack with wrong size (Point with less fields) 1`] = `"Wrong struct size for Point2D, expected 3 but was 2"`;
44+
45+
exports[`#unit BoltProtocolV5x1 .unpack() should not unpack with wrong size (Point with more fields) 1`] = `"Wrong struct size for Point2D, expected 3 but was 4"`;
46+
47+
exports[`#unit BoltProtocolV5x1 .unpack() should not unpack with wrong size (Point3D with less fields) 1`] = `"Wrong struct size for Point3D, expected 4 but was 3"`;
48+
49+
exports[`#unit BoltProtocolV5x1 .unpack() should not unpack with wrong size (Point3D with more fields) 1`] = `"Wrong struct size for Point3D, expected 4 but was 5"`;
50+
51+
exports[`#unit BoltProtocolV5x1 .unpack() should not unpack with wrong size (Relationship with less fields) 1`] = `"Wrong struct size for Relationship, expected 8 but was 5"`;
52+
53+
exports[`#unit BoltProtocolV5x1 .unpack() should not unpack with wrong size (Relationship with more fields) 1`] = `"Wrong struct size for Relationship, expected 8 but was 9"`;
54+
55+
exports[`#unit BoltProtocolV5x1 .unpack() should not unpack with wrong size (Time with less fields) 1`] = `"Wrong struct size for Time, expected 2 but was 1"`;
56+
57+
exports[`#unit BoltProtocolV5x1 .unpack() should not unpack with wrong size (Time with more fileds) 1`] = `"Wrong struct size for Time, expected 2 but was 3"`;
58+
59+
exports[`#unit BoltProtocolV5x1 .unpack() should not unpack with wrong size (UnboundRelationship with less fields) 1`] = `"Wrong struct size for UnboundRelationship, expected 4 but was 3"`;
60+
61+
exports[`#unit BoltProtocolV5x1 .unpack() should not unpack with wrong size (UnboundRelationship with more fields) 1`] = `"Wrong struct size for UnboundRelationship, expected 4 but was 5"`;

0 commit comments

Comments
 (0)