Skip to content

Commit 4693282

Browse files
author
Zhen Li
committed
Merge branch '1.7' into 4.0
2 parents b74ae32 + 988410e commit 4693282

File tree

3 files changed

+81
-28
lines changed

3 files changed

+81
-28
lines changed

src/session.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,9 @@ class Session {
103103
? new TxConfig(transactionConfig)
104104
: TxConfig.empty()
105105

106-
return this._run(validatedQuery, params, connection =>
107-
connection.protocol().run(validatedQuery, params, {
106+
return this._run(validatedQuery, params, connection => {
107+
this._assertSessionIsOpen()
108+
return connection.protocol().run(validatedQuery, params, {
108109
bookmark: this._lastBookmark,
109110
txConfig: autoCommitTxConfig,
110111
mode: this._mode,
@@ -113,7 +114,7 @@ class Session {
113114
reactive: this._reactive,
114115
fetchSize: this._fetchSize
115116
})
116-
)
117+
})
117118
}
118119

119120
_run (query, parameters, customRunner) {
@@ -188,13 +189,20 @@ class Session {
188189
connectionHolder,
189190
onClose: this._transactionClosed.bind(this),
190191
onBookmark: this._updateBookmark.bind(this),
192+
onConnection: this._assertSessionIsOpen.bind(this),
191193
reactive: this._reactive,
192194
fetchSize: this._fetchSize
193195
})
194196
tx._begin(this._lastBookmark, txConfig)
195197
return tx
196198
}
197199

200+
_assertSessionIsOpen () {
201+
if (!this._open) {
202+
throw newError('You cannot run more transactions on a closed session.')
203+
}
204+
}
205+
198206
_transactionClosed () {
199207
this._hasTx = false
200208
}

src/transaction.js

Lines changed: 52 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,25 @@ class Transaction {
4242
* @param {ConnectionHolder} connectionHolder - the connection holder to get connection from.
4343
* @param {function()} onClose - Function to be called when transaction is committed or rolled back.
4444
* @param {function(bookmark: Bookmark)} onBookmark callback invoked when new bookmark is produced.
45+
* * @param {function()} onConnection - Function to be called when a connection is obtained to ensure the conneciton
46+
* is not yet released.
4547
* @param {boolean} reactive whether this transaction generates reactive streams
4648
* @param {number} fetchSize - the record fetch size in each pulling batch.
4749
*/
48-
constructor ({ connectionHolder, onClose, onBookmark, reactive, fetchSize }) {
50+
constructor ({
51+
connectionHolder,
52+
onClose,
53+
onBookmark,
54+
onConnection,
55+
reactive,
56+
fetchSize
57+
}) {
4958
this._connectionHolder = connectionHolder
5059
this._reactive = reactive
5160
this._state = _states.ACTIVE
5261
this._onClose = onClose
5362
this._onBookmark = onBookmark
63+
this._onConnection = onConnection
5464
this._onError = this._onErrorCallback.bind(this)
5565
this._onComplete = this._onCompleteCallback.bind(this)
5666
this._fetchSize = fetchSize
@@ -60,16 +70,17 @@ class Transaction {
6070
_begin (bookmark, txConfig) {
6171
this._connectionHolder
6272
.getConnection()
63-
.then(conn =>
64-
conn.protocol().beginTransaction({
73+
.then(conn => {
74+
this._onConnection()
75+
return conn.protocol().beginTransaction({
6576
bookmark: bookmark,
6677
txConfig: txConfig,
6778
mode: this._connectionHolder.mode(),
6879
database: this._connectionHolder.database(),
6980
beforeError: this._onError,
7081
afterComplete: this._onComplete
7182
})
72-
)
83+
})
7384
.catch(error => this._onError(error))
7485
}
7586

@@ -91,6 +102,7 @@ class Transaction {
91102
connectionHolder: this._connectionHolder,
92103
onError: this._onError,
93104
onComplete: this._onComplete,
105+
onConnection: this._onConnection,
94106
reactive: this._reactive,
95107
fetchSize: this._fetchSize
96108
})
@@ -110,6 +122,7 @@ class Transaction {
110122
connectionHolder: this._connectionHolder,
111123
onError: this._onError,
112124
onComplete: this._onComplete,
125+
onConnection: this._onConnection,
113126
pendingResults: this._results
114127
})
115128
this._state = committed.state
@@ -136,6 +149,7 @@ class Transaction {
136149
connectionHolder: this._connectionHolder,
137150
onError: this._onError,
138151
onComplete: this._onComplete,
152+
onConnection: this._onConnection,
139153
pendingResults: this._results
140154
})
141155
this._state = rolledback.state
@@ -176,25 +190,39 @@ class Transaction {
176190
const _states = {
177191
// The transaction is running with no explicit success or failure marked
178192
ACTIVE: {
179-
commit: ({ connectionHolder, onError, onComplete, pendingResults }) => {
193+
commit: ({
194+
connectionHolder,
195+
onError,
196+
onComplete,
197+
onConnection,
198+
pendingResults
199+
}) => {
180200
return {
181201
result: finishTransaction(
182202
true,
183203
connectionHolder,
184204
onError,
185205
onComplete,
206+
onConnection,
186207
pendingResults
187208
),
188209
state: _states.SUCCEEDED
189210
}
190211
},
191-
rollback: ({ connectionHolder, onError, onComplete, pendingResults }) => {
212+
rollback: ({
213+
connectionHolder,
214+
onError,
215+
onComplete,
216+
onConnection,
217+
pendingResults
218+
}) => {
192219
return {
193220
result: finishTransaction(
194221
false,
195222
connectionHolder,
196223
onError,
197224
onComplete,
225+
onConnection,
198226
pendingResults
199227
),
200228
state: _states.ROLLED_BACK
@@ -203,22 +231,30 @@ const _states = {
203231
run: (
204232
query,
205233
parameters,
206-
{ connectionHolder, onError, onComplete, reactive, fetchSize }
234+
{
235+
connectionHolder,
236+
onError,
237+
onComplete,
238+
onConnection,
239+
reactive,
240+
fetchSize
241+
}
207242
) => {
208243
// RUN in explicit transaction can't contain bookmarks and transaction configuration
209244
// No need to include mode and database name as it shall be inclued in begin
210245
const observerPromise = connectionHolder
211246
.getConnection()
212-
.then(conn =>
213-
conn.protocol().run(query, parameters, {
247+
.then(conn => {
248+
onConnection()
249+
return conn.protocol().run(query, parameters, {
214250
bookmark: Bookmark.empty(),
215251
txConfig: TxConfig.empty(),
216252
beforeError: onError,
217253
afterComplete: onComplete,
218254
reactive: reactive,
219255
fetchSize: fetchSize
220256
})
221-
)
257+
})
222258
.catch(error => new FailedObserver({ error, onError }))
223259

224260
return newCompletedResult(observerPromise, query, parameters)
@@ -249,11 +285,7 @@ const _states = {
249285
state: _states.FAILED
250286
}
251287
},
252-
run: (
253-
query,
254-
parameters,
255-
{ connectionHolder, onError, onComplete, reactive }
256-
) => {
288+
run: (query, parameters, { connectionHolder, onError, onComplete }) => {
257289
return newCompletedResult(
258290
new FailedObserver({
259291
error: newError(
@@ -299,11 +331,7 @@ const _states = {
299331
state: _states.SUCCEEDED
300332
}
301333
},
302-
run: (
303-
query,
304-
parameters,
305-
{ connectionHolder, onError, onComplete, reactive }
306-
) => {
334+
run: (query, parameters, { connectionHolder, onError, onComplete }) => {
307335
return newCompletedResult(
308336
new FailedObserver({
309337
error: newError(
@@ -348,11 +376,7 @@ const _states = {
348376
state: _states.ROLLED_BACK
349377
}
350378
},
351-
run: (
352-
query,
353-
parameters,
354-
{ connectionHolder, onError, onComplete, reactive }
355-
) => {
379+
run: (query, parameters, { connectionHolder, onError, onComplete }) => {
356380
return newCompletedResult(
357381
new FailedObserver({
358382
error: newError(
@@ -373,18 +397,21 @@ const _states = {
373397
* @param {ConnectionHolder} connectionHolder
374398
* @param {function(err:Error): any} onError
375399
* @param {function(metadata:object): any} onComplete
400+
* @param {function() : any} onConnection
376401
* @param {list<Result>>}pendingResults all run results in this transaction
377402
*/
378403
function finishTransaction (
379404
commit,
380405
connectionHolder,
381406
onError,
382407
onComplete,
408+
onConnection,
383409
pendingResults
384410
) {
385411
const observerPromise = connectionHolder
386412
.getConnection()
387413
.then(connection => {
414+
onConnection()
388415
pendingResults.forEach(r => r._cancel())
389416
return Promise.all(pendingResults).then(results => {
390417
if (commit) {

test/transaction.test.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import neo4j from '../src'
2020
import sharedNeo4j from './internal/shared-neo4j'
2121
import { ServerVersion } from '../src/internal/server-version'
2222
import TxConfig from '../src/internal/tx-config'
23+
import { READ } from '../src/driver'
2324

2425
describe('#integration transaction', () => {
2526
let driver
@@ -589,6 +590,23 @@ describe('#integration transaction', () => {
589590
expect(result).toBeUndefined()
590591
})
591592

593+
it('should reset transaction', async done => {
594+
const session = driver.session({ defaultAccessMode: READ })
595+
const tx = session.beginTransaction()
596+
await tx.run('RETURN 1')
597+
598+
const closePromise = session.close()
599+
try {
600+
await tx.run('Match (n:Person) RETURN n')
601+
} catch (error) {
602+
expect(error.message).toBe(
603+
'You cannot run more transactions on a closed session.'
604+
)
605+
await closePromise
606+
done()
607+
}
608+
})
609+
592610
function expectSyntaxError (error) {
593611
expect(error.code).toBe('Neo.ClientError.Statement.SyntaxError')
594612
}

0 commit comments

Comments
 (0)