Skip to content

Commit e191168

Browse files
authored
Introduce explicity resource management to Driver and Session objects (#1154)
This is a TC39 [proposal](https://github.com/tc39/proposal-explicit-resource-management) which is already implemented in Typescript 5.2, core-js, babel and other polyfill tools. This feature enables the user create the driver or a session with the `await using` keywords and then do not have to close the resource afterwards, since this resources will be closed after leaving the block which were created at. For example: ```typescript await using driver = neo4j.driver(uri, authToken) await using session = driver.session() await session.executeRead(tx => "RETURN 1") ``` Since Deno is more strict with typescript, small fixes had to be done in the driver. * Add a value to Result[Symbol.toStringTag]. * Fix Integer.shiftRight function to add proper integer conversion it. A package.json file was added to the `neo4j-driver-deno` folder for making easier to integrate the test runners to the environments.
1 parent 91dd8bf commit e191168

File tree

15 files changed

+102
-9
lines changed

15 files changed

+102
-9
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@
4040
"scripts": {
4141
"clean": "lerna clean -y && lerna run clean",
4242
"build": "lerna bootstrap --ci",
43-
"set_version::deno": "cd ./packages/neo4j-driver-deno && deno run --allow-read --allow-write ./versioning.ts --output=. --filename=current.version.ts",
44-
"build::deno": "cd ./packages/neo4j-driver-deno && deno run --allow-read --allow-write --allow-net ./generate.ts",
43+
"set_version::deno": "lerna run set_version --scope neo4j-driver-deno --stream -- ",
44+
"build::deno": "lerna run build --scope neo4j-driver-deno --stream -- ",
4545
"build::notci": "lerna bootstrap",
4646
"docs": "lerna run docs --stream --concurrency 1",
4747
"test::unit": "lerna run test::unit --stream",

packages/core/src/driver.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,12 @@ class Driver {
776776
return Promise.resolve()
777777
}
778778

779+
// eslint-disable-next-line
780+
// @ts-ignore
781+
[Symbol.asyncDispose] (): Promise<void> {
782+
return this.close()
783+
}
784+
779785
/**
780786
* @protected
781787
* @returns {void}

packages/core/src/integer.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -695,10 +695,11 @@ class Integer {
695695
*/
696696
shiftRight (numBits: number | Integer): Integer {
697697
let bitsCount: number = Integer.toNumber(numBits)
698+
const numBitNum: number = Integer.toNumber(numBits)
698699

699700
if ((bitsCount &= 63) === 0) {
700701
return Integer.ZERO
701-
} else if (numBits < 32) {
702+
} else if (numBitNum < 32) {
702703
return Integer.fromBits(
703704
(this.low >>> bitsCount) | (this.high << (32 - bitsCount)),
704705
this.high >> bitsCount

packages/core/src/result.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ class Result<R extends RecordShape = RecordShape> implements Promise<QueryResult
375375
* @param {function()|null} onfinally - function when the promise finished
376376
* @return {Promise} promise.
377377
*/
378-
[Symbol.toStringTag]: string
378+
[Symbol.toStringTag]: string = 'Result'
379379
finally (onfinally?: (() => void) | null): Promise<QueryResult<R>> {
380380
return this._getOrCreatePromise().finally(onfinally)
381381
}

packages/core/src/session.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,12 @@ class Session {
561561
}
562562
}
563563

564+
// eslint-disable-next-line
565+
// @ts-ignore
566+
[Symbol.asyncDispose] (): Promise<void> {
567+
return this.close()
568+
}
569+
564570
_connectionHolderWithMode (mode: SessionMode): ConnectionHolder {
565571
if (mode === ACCESS_MODE_READ) {
566572
return this._readConnectionHolder

packages/neo4j-driver-deno/lib/core/driver.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,12 @@ class Driver {
776776
return Promise.resolve()
777777
}
778778

779+
// eslint-disable-next-line
780+
// @ts-ignore
781+
[Symbol.asyncDispose] (): Promise<void> {
782+
return this.close()
783+
}
784+
779785
/**
780786
* @protected
781787
* @returns {void}

packages/neo4j-driver-deno/lib/core/integer.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -695,10 +695,11 @@ class Integer {
695695
*/
696696
shiftRight (numBits: number | Integer): Integer {
697697
let bitsCount: number = Integer.toNumber(numBits)
698+
const numBitNum: number = Integer.toNumber(numBits)
698699

699700
if ((bitsCount &= 63) === 0) {
700701
return Integer.ZERO
701-
} else if (numBits < 32) {
702+
} else if (numBitNum < 32) {
702703
return Integer.fromBits(
703704
(this.low >>> bitsCount) | (this.high << (32 - bitsCount)),
704705
this.high >> bitsCount

packages/neo4j-driver-deno/lib/core/result.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ class Result<R extends RecordShape = RecordShape> implements Promise<QueryResult
375375
* @param {function()|null} onfinally - function when the promise finished
376376
* @return {Promise} promise.
377377
*/
378-
[Symbol.toStringTag]: string
378+
[Symbol.toStringTag]: string = 'Result'
379379
finally (onfinally?: (() => void) | null): Promise<QueryResult<R>> {
380380
return this._getOrCreatePromise().finally(onfinally)
381381
}

packages/neo4j-driver-deno/lib/core/session.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,12 @@ class Session {
561561
}
562562
}
563563

564+
// eslint-disable-next-line
565+
// @ts-ignore
566+
[Symbol.asyncDispose] (): Promise<void> {
567+
return this.close()
568+
}
569+
564570
_connectionHolderWithMode (mode: SessionMode): ConnectionHolder {
565571
if (mode === ACCESS_MODE_READ) {
566572
return this._readConnectionHolder
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "neo4j-driver-deno",
3+
"version": "5.0.0-dev",
4+
"description": "Package just used for running scripts",
5+
"private": true,
6+
"main": "index.js",
7+
"directories": {
8+
"lib": "lib",
9+
"test": "test"
10+
},
11+
"scripts": {
12+
"test": "npm run test::integration",
13+
"test::integration": "deno test --allow-all ./test",
14+
"set_version": "deno run --allow-read --allow-write ./versioning.ts --output=. --filename=current.version.ts",
15+
"build": "deno run --allow-read --allow-write --allow-net ./generate.ts"
16+
},
17+
"author": "Neo4j",
18+
"license": "Apache-2.0"
19+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
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 neo4j from '../lib/mod.ts'
20+
21+
const env = Deno.env.toObject()
22+
23+
const username = env.TEST_NEO4J_USER || 'neo4j'
24+
const password = env.TEST_NEO4J_PASS || 'password'
25+
const hostname = env.TEST_NEO4J_HOST || 'localhost'
26+
const scheme = env.TEST_NEO4J_SCHEME || 'bolt'
27+
const boltPort = env.TEST_NEO4J_BOLT_PORT || 7687
28+
const uri = `${scheme}://${hostname}:${boltPort}`
29+
const authToken = neo4j.auth.basic(username, password)
30+
31+
// Deno will fail with resource leaks
32+
Deno.test('neo4j.driver should be able to use explicity resource management', async () => {
33+
await using driver = neo4j.driver(uri, authToken)
34+
35+
await driver.executeQuery('RETURN 1')
36+
})
37+
38+
// Deno will fail with resource leaks
39+
Deno.test('driver.session should be able to use explicity resource management', async () => {
40+
await using driver = neo4j.driver(uri, authToken)
41+
await using session = driver.session()
42+
43+
await session.executeRead(tx => "RETURN 1")
44+
})

packages/neo4j-driver/src/session-rx.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,10 @@ export default class RxSession {
163163
})
164164
}
165165

166+
[Symbol.asyncDispose] () {
167+
return this.close()
168+
}
169+
166170
/**
167171
* Returns the bookmarks received following the last successfully completed query, which is executed
168172
* either in an {@link RxTransaction} obtained from this session instance or directly through one of

packages/testkit-backend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"scripts": {
1313
"build": "rollup src/index.js --config rollup.config.js",
1414
"start": "node --version | grep -q v10. && node -r esm src/index.js || node --experimental-specifier-resolution=node src/index.js",
15-
"start::deno": "deno run --allow-read --allow-write --allow-net --allow-env --allow-run deno/index.ts",
15+
"start::deno": "deno run --allow-read --allow-write --allow-net --allow-env --allow-sys --allow-run deno/index.ts",
1616
"clean": "rm -fr node_modules public/index.js",
1717
"prepare": "npm run build",
1818
"node": "node"

testkit/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
FROM ubuntu:20.04
22

33
ARG NODE_VERSION=10
4-
ARG DENO_VERSION=1.19.3
4+
ARG DENO_VERSION=1.37.2
55

66
ENV DEBIAN_FRONTEND noninteractive
77
ENV NODE_OPTIONS --max_old_space_size=4096 --use-openssl-ca

testkit/build.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def init_monorepo():
1919
def clean_and_build():
2020
run_in_driver_repo(["npm", "run", "clean"], env=os.environ)
2121
run_in_driver_repo(["npm", "run", "build"], env=os.environ)
22-
run_in_driver_repo(["npm", "run", "build::deno", "--",
22+
run_in_driver_repo(["npm", "run", "build::deno", "--", "--",
2323
"--output=lib2/"], env=os.environ)
2424

2525
if is_deno() and is_team_city():

0 commit comments

Comments
 (0)