Skip to content

Commit f58a089

Browse files
authored
Introduce explicity resource management to Transaction (neo4j#1155)
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 begin a transaction 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. Transaction will be closed using with the same behaviour as `Transaction.close` calls. So, the transaction will be rollback if still open. _Note: For better usage in cluster environments, you should use `executeRead` and `executeWrite` for handling retries._ Usage example: ```typescript await using tx = session.beginTransaction() await tx.run('CREATE (p:Person { name:$name }) RETURN p', { name }).summary() await tx.commit() ```
1 parent bf780de commit f58a089

File tree

3 files changed

+53
-0
lines changed

3 files changed

+53
-0
lines changed

packages/core/src/transaction.ts

+6
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,12 @@ class Transaction {
291291
}
292292
}
293293

294+
// eslint-disable-next-line
295+
// @ts-ignore
296+
[Symbol.asyncDispose] (): Promise<void> {
297+
return this.close()
298+
}
299+
294300
_onErrorCallback (error: Error): Promise<Connection | null> {
295301
// error will be "acknowledged" by sending a RESET message
296302
// database will then forget about this transaction and cleanup all corresponding resources

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

+6
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,12 @@ class Transaction {
291291
}
292292
}
293293

294+
// eslint-disable-next-line
295+
// @ts-ignore
296+
[Symbol.asyncDispose] (): Promise<void> {
297+
return this.close()
298+
}
299+
294300
_onErrorCallback (error: Error): Promise<Connection | null> {
295301
// error will be "acknowledged" by sending a RESET message
296302
// database will then forget about this transaction and cleanup all corresponding resources

packages/neo4j-driver-deno/test/neo4j.test.ts

+41
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
* limitations under the License.
1818
*/
1919
import neo4j from '../lib/mod.ts'
20+
//@ts-ignore
21+
import { assertEquals } from "https://deno.land/[email protected]/testing/asserts.ts";
2022

2123
const env = Deno.env.toObject()
2224

@@ -42,3 +44,42 @@ Deno.test('driver.session should be able to use explicity resource management',
4244

4345
await session.executeRead(tx => "RETURN 1")
4446
})
47+
48+
49+
// Deno will fail with resource leaks
50+
Deno.test('session.beginTransaction should rollback the transaction if not committed', async () => {
51+
await using driver = neo4j.driver(uri, authToken)
52+
await using session = driver.session()
53+
const name = "Must Be Conor"
54+
55+
56+
{
57+
await using tx = session.beginTransaction()
58+
await tx.run('CREATE (p:Person { name:$name }) RETURN p', { name }).summary()
59+
}
60+
61+
const { records } = await driver.executeQuery('MATCH (p:Person { name:$name }) RETURN p', { name })
62+
assertEquals(records.length, 0)
63+
})
64+
65+
66+
// Deno will fail with resource leaks
67+
Deno.test('session.beginTransaction should noop if resource committed', async () => {
68+
await using driver = neo4j.driver(uri, authToken)
69+
try {
70+
await using session = driver.session()
71+
const name = "Must Be Conor"
72+
73+
{
74+
await using tx = session.beginTransaction()
75+
await tx.run('CREATE (p:Person { name:$name }) RETURN p', { name }).summary()
76+
await tx.commit()
77+
}
78+
79+
const { records } = await driver.executeQuery('MATCH (p:Person { name:$name }) RETURN p', { name })
80+
assertEquals(records.length, 1)
81+
} finally {
82+
// cleaning up
83+
await driver.executeQuery('MATCH (p:Person { name:$name }) DELETE(p)', { name })
84+
}
85+
})

0 commit comments

Comments
 (0)