Skip to content

Commit 84b42d7

Browse files
authored
Merge pull request #444 from ali-ince/1.7-pass-access-mode
Pass AccessMode in BEGIN and RUN messages
2 parents 9a4fde2 + 2b5466b commit 84b42d7

19 files changed

+313
-54
lines changed

src/v1/driver.js

+9-8
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import ConnectivityVerifier from './internal/connectivity-verifier';
2828
import PoolConfig, {DEFAULT_ACQUISITION_TIMEOUT, DEFAULT_MAX_SIZE} from './internal/pool-config';
2929
import Logger from './internal/logger';
3030
import ConnectionErrorHandler from './internal/connection-error-handler';
31+
import {ACCESS_MODE_READ, ACCESS_MODE_WRITE} from './internal/constants';
3132

3233
const DEFAULT_MAX_CONNECTION_LIFETIME = 60 * 60 * 1000; // 1 hour
3334

@@ -36,14 +37,14 @@ const DEFAULT_MAX_CONNECTION_LIFETIME = 60 * 60 * 1000; // 1 hour
3637
* Should be used like this: `driver.session(neo4j.session.READ)`.
3738
* @type {string}
3839
*/
39-
const READ = 'READ';
40+
const READ = ACCESS_MODE_READ;
4041

4142
/**
4243
* Constant that represents write session access mode.
4344
* Should be used like this: `driver.session(neo4j.session.WRITE)`.
4445
* @type {string}
4546
*/
46-
const WRITE = 'WRITE';
47+
const WRITE = ACCESS_MODE_WRITE;
4748

4849
let idGenerator = 0;
4950

@@ -174,15 +175,15 @@ class Driver {
174175
}
175176

176177
/**
177-
* Acquire a session to communicate with the database. The driver maintains
178-
* a pool of sessions, so calling this method is normally cheap because you
179-
* will be pulling a session out of the common pool.
178+
* Acquire a session to communicate with the database. The session will
179+
* borrow connections from the underlying connection pool as required and
180+
* should be considered lightweight and disposable.
180181
*
181182
* This comes with some responsibility - make sure you always call
182183
* {@link close} when you are done using a session, and likewise,
183184
* make sure you don't close your session before you are done using it. Once
184-
* it is returned to the pool, the session will be reset to a clean state and
185-
* made available for others to use.
185+
* it is closed, the underlying connection will be released to the connection
186+
* pool and made available for others to use.
186187
*
187188
* @param {string} [mode=WRITE] the access mode of this session, allowed values are {@link READ} and {@link WRITE}.
188189
* @param {string|string[]} [bookmarkOrBookmarks=null] the initial reference or references to some previous
@@ -198,7 +199,7 @@ class Driver {
198199

199200
static _validateSessionMode(rawMode) {
200201
const mode = rawMode || WRITE;
201-
if (mode !== READ && mode !== WRITE) {
202+
if (mode !== ACCESS_MODE_READ && mode !== ACCESS_MODE_WRITE) {
202203
throw newError('Illegal session mode ' + mode);
203204
}
204205
return mode;

src/v1/internal/bolt-protocol-v1.js

+12-5
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import * as v1 from './packstream-v1';
2121
import {newError} from '../error';
2222
import Bookmark from './bookmark';
2323
import TxConfig from './tx-config';
24+
import {ACCESS_MODE_WRITE} from "./constants";
2425

2526
export default class BoltProtocol {
2627

@@ -80,9 +81,10 @@ export default class BoltProtocol {
8081
* Begin an explicit transaction.
8182
* @param {Bookmark} bookmark the bookmark.
8283
* @param {TxConfig} txConfig the configuration.
84+
* @param {string} mode the access mode.
8385
* @param {StreamObserver} observer the response observer.
8486
*/
85-
beginTransaction(bookmark, txConfig, observer) {
87+
beginTransaction(bookmark, txConfig, mode, observer) {
8688
assertTxConfigIsEmpty(txConfig, this._connection, observer);
8789

8890
const runMessage = RequestMessage.run('BEGIN', bookmark.asBeginTransactionParameters());
@@ -97,15 +99,19 @@ export default class BoltProtocol {
9799
* @param {StreamObserver} observer the response observer.
98100
*/
99101
commitTransaction(observer) {
100-
this.run('COMMIT', {}, Bookmark.empty(), TxConfig.empty(), observer);
102+
// WRITE access mode is used as a place holder here, it has
103+
// no effect on behaviour for Bolt V1 & V2
104+
this.run('COMMIT', {}, Bookmark.empty(), TxConfig.empty(), ACCESS_MODE_WRITE, observer);
101105
}
102106

103107
/**
104108
* Rollback the explicit transaction.
105109
* @param {StreamObserver} observer the response observer.
106110
*/
107111
rollbackTransaction(observer) {
108-
this.run('ROLLBACK', {}, Bookmark.empty(), TxConfig.empty(), observer);
112+
// WRITE access mode is used as a place holder here, it has
113+
// no effect on behaviour for Bolt V1 & V2
114+
this.run('ROLLBACK', {}, Bookmark.empty(), TxConfig.empty(), ACCESS_MODE_WRITE, observer);
109115
}
110116

111117
/**
@@ -114,10 +120,11 @@ export default class BoltProtocol {
114120
* @param {object} parameters the statement parameters.
115121
* @param {Bookmark} bookmark the bookmark.
116122
* @param {TxConfig} txConfig the auto-commit transaction configuration.
123+
* @param {string} mode the access mode.
117124
* @param {StreamObserver} observer the response observer.
118125
*/
119-
run(statement, parameters, bookmark, txConfig, observer) {
120-
// bookmark is ignored in this version of the protocol
126+
run(statement, parameters, bookmark, txConfig, mode, observer) {
127+
// bookmark and mode are ignored in this versioon of the protocol
121128
assertTxConfigIsEmpty(txConfig, this._connection, observer);
122129

123130
const runMessage = RequestMessage.run(statement, parameters);

src/v1/internal/bolt-protocol-v3.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ export default class BoltProtocol extends BoltProtocolV2 {
5252
this._connection.write(message, observer, true);
5353
}
5454

55-
beginTransaction(bookmark, txConfig, observer) {
55+
beginTransaction(bookmark, txConfig, mode, observer) {
5656
prepareToHandleSingleResponse(observer);
57-
const message = RequestMessage.begin(bookmark, txConfig);
57+
const message = RequestMessage.begin(bookmark, txConfig, mode);
5858
this._connection.write(message, observer, true);
5959
}
6060

@@ -70,8 +70,8 @@ export default class BoltProtocol extends BoltProtocolV2 {
7070
this._connection.write(message, observer, true);
7171
}
7272

73-
run(statement, parameters, bookmark, txConfig, observer) {
74-
const runMessage = RequestMessage.runWithMetadata(statement, parameters, bookmark, txConfig);
73+
run(statement, parameters, bookmark, txConfig, mode, observer) {
74+
const runMessage = RequestMessage.runWithMetadata(statement, parameters, bookmark, txConfig, mode);
7575
const pullAllMessage = RequestMessage.pullAll();
7676

7777
this._connection.write(runMessage, observer, false);

src/v1/internal/connection-holder.js

+8
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,14 @@ export default class ConnectionHolder {
3636
this._connectionPromise = Promise.resolve(null);
3737
}
3838

39+
/**
40+
* Returns the assigned access mode.
41+
* @returns {string} access mode
42+
*/
43+
mode() {
44+
return this._mode;
45+
}
46+
3947
/**
4048
* Make this holder initialize new connection if none exists already.
4149
* @return {undefined}

src/v1/internal/constants.js

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* Copyright (c) 2002-2019 "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+
const ACCESS_MODE_READ = 'READ';
21+
const ACCESS_MODE_WRITE = 'WRITE';
22+
23+
export {
24+
ACCESS_MODE_READ,
25+
ACCESS_MODE_WRITE
26+
}

src/v1/internal/request-message.js

+15-5
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
* limitations under the License.
1818
*/
1919

20+
import {ACCESS_MODE_READ} from './constants';
21+
2022
// Signature bytes for each request message type
2123
const INIT = 0x01; // 0000 0001 // INIT <user_agent> <authentication_token>
2224
const ACK_FAILURE = 0x0E; // 0000 1110 // ACK_FAILURE - unused
@@ -31,6 +33,8 @@ const BEGIN = 0x11; // 0001 0001 // BEGIN <metadata>
3133
const COMMIT = 0x12; // 0001 0010 // COMMIT
3234
const ROLLBACK = 0x13; // 0001 0011 // ROLLBACK
3335

36+
const READ_MODE = "r";
37+
3438
export default class RequestMessage {
3539

3640
constructor(signature, fields, toString) {
@@ -90,10 +94,11 @@ export default class RequestMessage {
9094
* Create a new BEGIN message.
9195
* @param {Bookmark} bookmark the bookmark.
9296
* @param {TxConfig} txConfig the configuration.
97+
* @param {string} mode the access mode.
9398
* @return {RequestMessage} new BEGIN message.
9499
*/
95-
static begin(bookmark, txConfig) {
96-
const metadata = buildTxMetadata(bookmark, txConfig);
100+
static begin(bookmark, txConfig, mode) {
101+
const metadata = buildTxMetadata(bookmark, txConfig, mode);
97102
return new RequestMessage(BEGIN, [metadata], () => `BEGIN ${JSON.stringify(metadata)}`);
98103
}
99104

@@ -119,10 +124,11 @@ export default class RequestMessage {
119124
* @param {object} parameters the statement parameters.
120125
* @param {Bookmark} bookmark the bookmark.
121126
* @param {TxConfig} txConfig the configuration.
127+
* @param {string} mode the access mode.
122128
* @return {RequestMessage} new RUN message with additional metadata.
123129
*/
124-
static runWithMetadata(statement, parameters, bookmark, txConfig) {
125-
const metadata = buildTxMetadata(bookmark, txConfig);
130+
static runWithMetadata(statement, parameters, bookmark, txConfig, mode) {
131+
const metadata = buildTxMetadata(bookmark, txConfig, mode);
126132
return new RequestMessage(RUN, [statement, parameters, metadata],
127133
() => `RUN ${statement} ${JSON.stringify(parameters)} ${JSON.stringify(metadata)}`);
128134
}
@@ -140,9 +146,10 @@ export default class RequestMessage {
140146
* Create an object that represent transaction metadata.
141147
* @param {Bookmark} bookmark the bookmark.
142148
* @param {TxConfig} txConfig the configuration.
149+
* @param {string} mode the access mode.
143150
* @return {object} a metadata object.
144151
*/
145-
function buildTxMetadata(bookmark, txConfig) {
152+
function buildTxMetadata(bookmark, txConfig, mode) {
146153
const metadata = {};
147154
if (!bookmark.isEmpty()) {
148155
metadata['bookmarks'] = bookmark.values();
@@ -153,6 +160,9 @@ function buildTxMetadata(bookmark, txConfig) {
153160
if (txConfig.metadata) {
154161
metadata['tx_metadata'] = txConfig.metadata;
155162
}
163+
if (mode === ACCESS_MODE_READ) {
164+
metadata['mode'] = READ_MODE;
165+
}
156166
return metadata;
157167
}
158168

src/v1/internal/routing-util.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import Integer, {int} from '../integer';
2222
import {ServerVersion, VERSION_3_2_0} from './server-version';
2323
import Bookmark from './bookmark';
2424
import TxConfig from './tx-config';
25+
import {ACCESS_MODE_WRITE} from "./constants";
2526

2627
const CALL_GET_SERVERS = 'CALL dbms.cluster.routing.getServers';
2728
const CALL_GET_ROUTING_TABLE = 'CALL dbms.cluster.routing.getRoutingTable($context)';
@@ -125,7 +126,7 @@ export default class RoutingUtil {
125126
params = {};
126127
}
127128

128-
connection.protocol().run(query, params, Bookmark.empty(), TxConfig.empty(), streamObserver);
129+
connection.protocol().run(query, params, Bookmark.empty(), TxConfig.empty(), ACCESS_MODE_WRITE, streamObserver);
129130
});
130131
}
131132
}

src/v1/session.js

+9-8
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ import Transaction from './transaction';
2222
import {newError} from './error';
2323
import {validateStatementAndParameters} from './internal/util';
2424
import ConnectionHolder from './internal/connection-holder';
25-
import Driver, {READ, WRITE} from './driver';
25+
import Driver from './driver';
26+
import {ACCESS_MODE_READ, ACCESS_MODE_WRITE} from './internal/constants';
2627
import TransactionExecutor from './internal/transaction-executor';
2728
import Bookmark from './internal/bookmark';
2829
import TxConfig from './internal/tx-config';
@@ -64,8 +65,8 @@ class Session {
6465
*/
6566
constructor(mode, connectionProvider, bookmark, config) {
6667
this._mode = mode;
67-
this._readConnectionHolder = new ConnectionHolder(READ, connectionProvider);
68-
this._writeConnectionHolder = new ConnectionHolder(WRITE, connectionProvider);
68+
this._readConnectionHolder = new ConnectionHolder(ACCESS_MODE_READ, connectionProvider);
69+
this._writeConnectionHolder = new ConnectionHolder(ACCESS_MODE_WRITE, connectionProvider);
6970
this._open = true;
7071
this._hasTx = false;
7172
this._lastBookmark = bookmark;
@@ -86,7 +87,7 @@ class Session {
8687
const autoCommitTxConfig = transactionConfig ? new TxConfig(transactionConfig) : TxConfig.empty();
8788

8889
return this._run(query, params, (connection, streamObserver) =>
89-
connection.protocol().run(query, params, this._lastBookmark, autoCommitTxConfig, streamObserver)
90+
connection.protocol().run(query, params, this._lastBookmark, autoCommitTxConfig, this._mode, streamObserver)
9091
);
9192
}
9293

@@ -179,7 +180,7 @@ class Session {
179180
*/
180181
readTransaction(transactionWork, transactionConfig) {
181182
const config = new TxConfig(transactionConfig);
182-
return this._runTransaction(READ, config, transactionWork);
183+
return this._runTransaction(ACCESS_MODE_READ, config, transactionWork);
183184
}
184185

185186
/**
@@ -198,7 +199,7 @@ class Session {
198199
*/
199200
writeTransaction(transactionWork, transactionConfig) {
200201
const config = new TxConfig(transactionConfig);
201-
return this._runTransaction(WRITE, config, transactionWork);
202+
return this._runTransaction(ACCESS_MODE_WRITE, config, transactionWork);
202203
}
203204

204205
_runTransaction(accessMode, transactionConfig, transactionWork) {
@@ -238,9 +239,9 @@ class Session {
238239
}
239240

240241
_connectionHolderWithMode(mode) {
241-
if (mode === READ) {
242+
if (mode === ACCESS_MODE_READ) {
242243
return this._readConnectionHolder;
243-
} else if (mode === WRITE) {
244+
} else if (mode === ACCESS_MODE_WRITE) {
244245
return this._writeConnectionHolder;
245246
} else {
246247
throw newError('Unknown access mode: ' + mode);

src/v1/transaction.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class Transaction {
4646
const streamObserver = new _TransactionStreamObserver(this);
4747

4848
this._connectionHolder.getConnection(streamObserver)
49-
.then(conn => conn.protocol().beginTransaction(bookmark, txConfig, streamObserver))
49+
.then(conn => conn.protocol().beginTransaction(bookmark, txConfig, this._connectionHolder.mode(), streamObserver))
5050
.catch(error => streamObserver.onError(error));
5151
}
5252

@@ -158,7 +158,7 @@ let _states = {
158158
const txConfig = TxConfig.empty();
159159

160160
connectionHolder.getConnection(observer)
161-
.then(conn => conn.protocol().run(statement, parameters, bookmark, txConfig, observer))
161+
.then(conn => conn.protocol().run(statement, parameters, bookmark, txConfig, connectionHolder.mode(), observer))
162162
.catch(error => observer.onError(error));
163163

164164
return _newRunResult(observer, statement, parameters, () => observer.serverMetadata());

test/internal/bolt-protocol-v1.test.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import BoltProtocolV1 from '../../src/v1/internal/bolt-protocol-v1';
2121
import RequestMessage from '../../src/v1/internal/request-message';
2222
import Bookmark from '../../src/v1/internal/bookmark';
2323
import TxConfig from '../../src/v1/internal/tx-config';
24+
import {WRITE} from "../../src/v1/driver";
2425

2526
class MessageRecorder {
2627

@@ -78,7 +79,7 @@ describe('BoltProtocolV1', () => {
7879
const parameters = {x: 'x', y: 'y'};
7980
const observer = {};
8081

81-
protocol.run(statement, parameters, Bookmark.empty(), TxConfig.empty(), observer);
82+
protocol.run(statement, parameters, Bookmark.empty(), TxConfig.empty(), WRITE, observer);
8283

8384
recorder.verifyMessageCount(2);
8485

@@ -110,7 +111,7 @@ describe('BoltProtocolV1', () => {
110111
const bookmark = new Bookmark('neo4j:bookmark:v1:tx42');
111112
const observer = {};
112113

113-
protocol.beginTransaction(bookmark, TxConfig.empty(), observer);
114+
protocol.beginTransaction(bookmark, TxConfig.empty(), WRITE, observer);
114115

115116
recorder.verifyMessageCount(2);
116117

test/internal/connection.test.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import ConnectionErrorHandler from '../../src/v1/internal/connection-error-handl
3232
import testUtils from '../internal/test-utils';
3333
import Bookmark from '../../src/v1/internal/bookmark';
3434
import TxConfig from '../../src/v1/internal/tx-config';
35+
import {WRITE} from "../../src/v1/driver";
3536

3637
const ILLEGAL_MESSAGE = {signature: 42, fields: []};
3738
const SUCCESS_MESSAGE = {signature: 0x70, fields: [{}]};
@@ -98,7 +99,7 @@ describe('Connection', () => {
9899

99100
connection.connect('mydriver/0.0.0', basicAuthToken())
100101
.then(() => {
101-
connection.protocol().run('RETURN 1.0', {}, Bookmark.empty(), TxConfig.empty(), streamObserver);
102+
connection.protocol().run('RETURN 1.0', {}, Bookmark.empty(), TxConfig.empty(), WRITE, streamObserver);
102103
});
103104
});
104105

0 commit comments

Comments
 (0)