Skip to content

Commit a71a4fc

Browse files
authored
Merge pull request #471 from ali-ince/2.0-multidb-routing
Multi-database routing
2 parents db0977a + 5f3f5a2 commit a71a4fc

File tree

191 files changed

+6031
-4511
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

191 files changed

+6031
-4511
lines changed

gulpfile.babel.js

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,10 @@ const file = require('gulp-file')
3535
const semver = require('semver')
3636
const sharedNeo4j = require('./test/internal/shared-neo4j').default
3737
const ts = require('gulp-typescript')
38-
const JasmineConsoleReporter = require('jasmine-console-reporter')
38+
const JasmineReporter = require('jasmine-spec-reporter').SpecReporter
3939
const karma = require('karma')
4040
const log = require('fancy-log')
41+
const JasmineExec = require('jasmine')
4142

4243
/**
4344
* Useful to investigate resource leaks in tests. Enable to see active sockets and file handles after the 'test' task.
@@ -112,6 +113,18 @@ gulp.task(
112113
})
113114
)
114115

116+
gulp.task('test-nodejs-unit', () => {
117+
return runJasmineTests('#unit*')
118+
})
119+
120+
gulp.task('test-nodejs-stub', () => {
121+
return runJasmineTests('#stub*')
122+
})
123+
124+
gulp.task('test-nodejs-integration', () => {
125+
return runJasmineTests('#integration*')
126+
})
127+
115128
gulp.task('run-browser-test-chrome', function (cb) {
116129
runKarma('chrome', cb)
117130
})
@@ -218,12 +231,23 @@ function logActiveNodeHandles () {
218231
}
219232

220233
function newJasmineConsoleReporter () {
221-
return new JasmineConsoleReporter({
222-
colors: 1,
223-
cleanStack: 1,
224-
verbosity: 4,
225-
listStyle: 'indent',
226-
activity: false
234+
return new JasmineReporter({
235+
colors: {
236+
enabled: true
237+
},
238+
spec: {
239+
displayDuration: true,
240+
displayErrorMessages: true,
241+
displayStacktrace: true,
242+
displayFailed: true,
243+
displaySuccessful: true,
244+
displayPending: false
245+
},
246+
summary: {
247+
displayFailed: true,
248+
displayStacktrace: true,
249+
displayErrorMessages: true
250+
}
227251
})
228252
}
229253

@@ -237,3 +261,24 @@ function runKarma (browser, cb) {
237261
}
238262
).start()
239263
}
264+
265+
function runJasmineTests (filterString) {
266+
return new Promise((resolve, reject) => {
267+
const jasmine = new JasmineExec()
268+
jasmine.loadConfigFile('./spec/support/jasmine.json')
269+
jasmine.loadHelpers()
270+
jasmine.loadSpecs()
271+
jasmine.configureDefaultReporter({
272+
print: () => {}
273+
})
274+
jasmine.addReporter(newJasmineConsoleReporter())
275+
jasmine.onComplete(passed => {
276+
if (passed) {
277+
resolve()
278+
} else {
279+
reject(new Error('tests failed'))
280+
}
281+
})
282+
jasmine.execute(null, filterString)
283+
})
284+
}

package-lock.json

Lines changed: 503 additions & 646 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
"gulp-uglify": "^3.0.2",
7575
"gulp-watch": "^5.0.1",
7676
"husky": "^2.3.0",
77-
"jasmine-console-reporter": "^3.1.0",
77+
"jasmine-spec-reporter": "^4.2.1",
7878
"karma": "^4.1.0",
7979
"karma-browserify": "^6.0.0",
8080
"karma-chrome-launcher": "^2.2.0",

spec/support/jasmine.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"spec_dir": "test",
3+
"spec_files": ["**/*.test.js", "!**/browser/*.js"],
4+
"helpers": ["../node_modules/@babel/register/lib/node.js"],
5+
"stopSpecOnExpectationFailure": false,
6+
"random": true
7+
}

src/driver.js

Lines changed: 22 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919

2020
import Session from './session'
2121
import Pool from './internal/pool'
22-
import Connection from './internal/connection'
22+
import ChannelConnection from './internal/connection-channel'
2323
import { newError, SERVICE_UNAVAILABLE } from './error'
24-
import { DirectConnectionProvider } from './internal/connection-providers'
24+
import DirectConnectionProvider from './internal/connection-provider-direct'
2525
import Bookmark from './internal/bookmark'
2626
import ConnectivityVerifier from './internal/connectivity-verifier'
2727
import PoolConfig, {
@@ -76,19 +76,9 @@ class Driver {
7676
this._id = idGenerator++
7777
this._address = address
7878
this._userAgent = userAgent
79-
this._openConnections = {}
8079
this._authToken = authToken
8180
this._config = config
8281
this._log = Logger.create(config)
83-
this._pool = new Pool({
84-
create: this._createConnection.bind(this),
85-
destroy: this._destroyConnection.bind(this),
86-
validate: this._validateConnection.bind(this),
87-
installIdleObserver: this._installIdleObserverOnConnection.bind(this),
88-
removeIdleObserver: this._removeIdleObserverOnConnection.bind(this),
89-
config: PoolConfig.fromDriverConfig(config),
90-
log: this._log
91-
})
9282

9383
/**
9484
* Reference to the connection provider. Initialized lazily by {@link _getOrCreateConnectionProvider}.
@@ -111,73 +101,13 @@ class Driver {
111101

112102
/**
113103
* Verifies connectivity of this driver by trying to open a connection with the provided driver options.
114-
* @param {string} [db=''] the target database to verify connectivity for.
104+
* @param {string} [database=''] the target database to verify connectivity for.
115105
* @returns {Promise<object>} promise resolved with server info or rejected with error.
116106
*/
117-
verifyConnectivity ({ db = '' } = {}) {
107+
verifyConnectivity ({ database = '' } = {}) {
118108
const connectionProvider = this._getOrCreateConnectionProvider()
119109
const connectivityVerifier = new ConnectivityVerifier(connectionProvider)
120-
return connectivityVerifier.verify({ db })
121-
}
122-
123-
/**
124-
* Create a new connection and initialize it.
125-
* @return {Promise<Connection>} promise resolved with a new connection or rejected when failed to connect.
126-
* @access private
127-
*/
128-
_createConnection (address, release) {
129-
const connection = Connection.create(
130-
address,
131-
this._config,
132-
this._createConnectionErrorHandler(),
133-
this._log
134-
)
135-
connection._release = () => release(address, connection)
136-
this._openConnections[connection.id] = connection
137-
138-
return connection.connect(this._userAgent, this._authToken).catch(error => {
139-
if (this.onError) {
140-
// notify Driver.onError callback about connection initialization errors
141-
this.onError(error)
142-
}
143-
// let's destroy this connection
144-
this._destroyConnection(connection)
145-
// propagate the error because connection failed to connect / initialize
146-
throw error
147-
})
148-
}
149-
150-
/**
151-
* Check that a connection is usable
152-
* @return {boolean} true if the connection is open
153-
* @access private
154-
**/
155-
_validateConnection (conn) {
156-
if (!conn.isOpen()) {
157-
return false
158-
}
159-
160-
const maxConnectionLifetime = this._config.maxConnectionLifetime
161-
const lifetime = Date.now() - conn.creationTimestamp
162-
return lifetime <= maxConnectionLifetime
163-
}
164-
165-
_installIdleObserverOnConnection (conn, observer) {
166-
conn._queueObserver(observer)
167-
}
168-
169-
_removeIdleObserverOnConnection (conn) {
170-
conn._updateCurrentObserver()
171-
}
172-
173-
/**
174-
* Dispose of a connection.
175-
* @return {Connection} the connection to dispose.
176-
* @access private
177-
*/
178-
_destroyConnection (conn) {
179-
delete this._openConnections[conn.id]
180-
conn.close()
110+
return connectivityVerifier.verify({ database })
181111
}
182112

183113
/**
@@ -194,13 +124,13 @@ class Driver {
194124
* @param {string} [defaultAccessMode=WRITE] the access mode of this session, allowed values are {@link READ} and {@link WRITE}.
195125
* @param {string|string[]} [bookmarks=null] the initial reference or references to some previous
196126
* transactions. Value is optional and absence indicates that that the bookmarks do not exist or are unknown.
197-
* @param {string} [db=''] the database this session will connect to.
127+
* @param {string} [database=''] the database this session will connect to.
198128
* @return {Session} new session.
199129
*/
200130
session ({
201131
defaultAccessMode = WRITE,
202132
bookmarks: bookmarkOrBookmarks,
203-
db = ''
133+
database = ''
204134
} = {}) {
205135
const sessionMode = Driver._validateSessionMode(defaultAccessMode)
206136
const connectionProvider = this._getOrCreateConnectionProvider()
@@ -209,7 +139,7 @@ class Driver {
209139
: Bookmark.empty()
210140
return new Session({
211141
mode: sessionMode,
212-
db,
142+
database,
213143
connectionProvider,
214144
bookmark,
215145
config: this._config
@@ -225,38 +155,27 @@ class Driver {
225155
}
226156

227157
// Extension point
228-
_createConnectionProvider (address, connectionPool, driverOnErrorCallback) {
229-
return new DirectConnectionProvider(
230-
address,
231-
connectionPool,
232-
driverOnErrorCallback
233-
)
234-
}
235-
236-
// Extension point
237-
_createConnectionErrorHandler () {
238-
return new ConnectionErrorHandler(SERVICE_UNAVAILABLE)
158+
_createConnectionProvider (address, userAgent, authToken) {
159+
return new DirectConnectionProvider({
160+
id: this._id,
161+
config: this._config,
162+
log: this._log,
163+
address: address,
164+
userAgent: userAgent,
165+
authToken: authToken
166+
})
239167
}
240168

241169
_getOrCreateConnectionProvider () {
242170
if (!this._connectionProvider) {
243-
const driverOnErrorCallback = this._driverOnErrorCallback.bind(this)
244171
this._connectionProvider = this._createConnectionProvider(
245172
this._address,
246-
this._pool,
247-
driverOnErrorCallback
173+
this._userAgent,
174+
this._authToken
248175
)
249176
}
250-
return this._connectionProvider
251-
}
252177

253-
_driverOnErrorCallback (error) {
254-
const userDefinedOnErrorCallback = this.onError
255-
if (userDefinedOnErrorCallback && error.code === SERVICE_UNAVAILABLE) {
256-
userDefinedOnErrorCallback(error)
257-
} else {
258-
// we don't need to tell the driver about this error
259-
}
178+
return this._connectionProvider
260179
}
261180

262181
/**
@@ -266,18 +185,8 @@ class Driver {
266185
*/
267186
close () {
268187
this._log.info(`Driver ${this._id} closing`)
269-
270-
try {
271-
// purge all idle connections in the connection pool
272-
this._pool.purgeAll()
273-
} finally {
274-
// then close all connections driver has ever created
275-
// it is needed to close connections that are active right now and are acquired from the pool
276-
for (let connectionId in this._openConnections) {
277-
if (this._openConnections.hasOwnProperty(connectionId)) {
278-
this._openConnections[connectionId].close()
279-
}
280-
}
188+
if (this._connectionProvider) {
189+
this._connectionProvider.close()
281190
}
282191
}
283192
}

src/internal/bolt-protocol-util.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ function assertTxConfigIsEmpty (txConfig, connection, observer) {
3939

4040
/**
4141
* Asserts that the passed-in database name is empty.
42-
* @param {string} db
42+
* @param {string} database
4343
* @param {Connection} connection
4444
* @param {StreamObserver} observer
4545
*/
46-
function assertDbIsEmpty (db, connection, observer) {
47-
if (db) {
46+
function assertDatabaseIsEmpty (database, connection, observer) {
47+
if (database) {
4848
const error = newError(
4949
'Driver is connected to the database that does not support multiple databases. ' +
5050
'Please upgrade to neo4j 4.0.0 or later in order to use this functionality'
@@ -57,4 +57,4 @@ function assertDbIsEmpty (db, connection, observer) {
5757
}
5858
}
5959

60-
export { assertDbIsEmpty, assertTxConfigIsEmpty }
60+
export { assertDatabaseIsEmpty, assertTxConfigIsEmpty }

src/internal/bolt-protocol-v1.js

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ import * as v1 from './packstream-v1'
2121
import Bookmark from './bookmark'
2222
import TxConfig from './tx-config'
2323
import { ACCESS_MODE_WRITE } from './constants'
24-
import { assertDbIsEmpty, assertTxConfigIsEmpty } from './bolt-protocol-util'
24+
import {
25+
assertDatabaseIsEmpty,
26+
assertTxConfigIsEmpty
27+
} from './bolt-protocol-util'
2528

2629
export default class BoltProtocol {
2730
/**
@@ -81,12 +84,12 @@ export default class BoltProtocol {
8184
* @param {StreamObserver} observer the response observer.
8285
* @param {Bookmark} bookmark the bookmark.
8386
* @param {TxConfig} txConfig the configuration.
84-
* @param {string} db the target database name.
87+
* @param {string} database the target database name.
8588
* @param {string} mode the access mode.
8689
*/
87-
beginTransaction (observer, { bookmark, txConfig, db, mode }) {
90+
beginTransaction (observer, { bookmark, txConfig, database, mode }) {
8891
assertTxConfigIsEmpty(txConfig, this._connection, observer)
89-
assertDbIsEmpty(db, this._connection, observer)
92+
assertDatabaseIsEmpty(database, this._connection, observer)
9093

9194
const runMessage = RequestMessage.run(
9295
'BEGIN',
@@ -133,14 +136,14 @@ export default class BoltProtocol {
133136
* @param {StreamObserver} observer the response observer.
134137
* @param {Bookmark} bookmark the bookmark.
135138
* @param {TxConfig} txConfig the auto-commit transaction configuration.
136-
* @param {string} db the target database name.
139+
* @param {string} database the target database name.
137140
* @param {string} mode the access mode.
138141
*/
139-
run (statement, parameters, observer, { bookmark, txConfig, db, mode }) {
142+
run (statement, parameters, observer, { bookmark, txConfig, database, mode }) {
140143
// bookmark and mode are ignored in this version of the protocol
141144
assertTxConfigIsEmpty(txConfig, this._connection, observer)
142-
// passing in a db name on this protocol version throws an error
143-
assertDbIsEmpty(db, this._connection, observer)
145+
// passing in a database name on this protocol version throws an error
146+
assertDatabaseIsEmpty(database, this._connection, observer)
144147

145148
const runMessage = RequestMessage.run(statement, parameters)
146149
const pullAllMessage = RequestMessage.pullAll()

0 commit comments

Comments
 (0)