@@ -530,6 +530,75 @@ async def _run_transaction(
530530 else :
531531 raise ServiceUnavailable ("Transaction failed" )
532532
533+ async def execute_read (
534+ self ,
535+ transaction_function : t .Callable [
536+ te .Concatenate [AsyncManagedTransaction , _P ], t .Awaitable [_R ]
537+ ],
538+ * args : _P .args , ** kwargs : _P .kwargs
539+ ) -> _R :
540+ """Execute a unit of work in a managed read transaction.
541+
542+ .. note::
543+ This does not necessarily imply access control, see the session
544+ configuration option :ref:`default-access-mode-ref`.
545+
546+ This transaction will automatically be committed when the function
547+ returns, unless an exception is thrown during query execution or by
548+ the user code. Note, that this function performs retries and that the
549+ supplied `transaction_function` might get invoked more than once.
550+ Therefore, it needs to be idempotent (i.e., have the same effect,
551+ regardless if called once or many times).
552+
553+ Example::
554+
555+ async def do_cypher_tx(tx, cypher):
556+ result = await tx.run(cypher)
557+ values = [record.values() async for record in result]
558+ return values
559+
560+ async with driver.session() as session:
561+ values = await session.execute_read(do_cypher_tx, "RETURN 1 AS x")
562+
563+ Example::
564+
565+ async def get_two_tx(tx):
566+ result = await tx.run("UNWIND [1,2,3,4] AS x RETURN x")
567+ values = []
568+ async for record in result:
569+ if len(values) >= 2:
570+ break
571+ values.append(record.values())
572+ # or shorter: values = [record.values()
573+ # for record in await result.fetch(2)]
574+
575+ # discard the remaining records if there are any
576+ summary = await result.consume()
577+ # use the summary for logging etc.
578+ return values
579+
580+ async with driver.session() as session:
581+ values = await session.execute_read(get_two_tx)
582+
583+ :param transaction_function: a function that takes a transaction as an
584+ argument and does work with the transaction.
585+ `transaction_function(tx, *args, **kwargs)` where `tx` is a
586+ :class:`.AsyncManagedTransaction`.
587+ :param args: additional arguments for the `transaction_function`
588+ :param kwargs: key word arguments for the `transaction_function`
589+
590+ :raises SessionError: if the session has been closed.
591+
592+ :return: a result as returned by the given unit of work
593+
594+ .. versionadded:: 5.0
595+ """
596+ return await self ._run_transaction (
597+ READ_ACCESS , transaction_function , * args , ** kwargs
598+ )
599+
600+ # TODO 6.0: Remove this method
601+ @deprecated ("read_transaction has been renamed to execute_read" )
533602 async def read_transaction (
534603 self ,
535604 transaction_function : t .Callable [
@@ -590,11 +659,64 @@ async def get_two_tx(tx):
590659 :raises SessionError: if the session has been closed.
591660
592661 :return: a result as returned by the given unit of work
662+
663+ .. deprecated:: 5.0
664+ Method was renamed to :meth:`.execute_read`.
593665 """
594666 return await self ._run_transaction (
595667 READ_ACCESS , transaction_function , * args , ** kwargs
596668 )
597669
670+ async def execute_write (
671+ self ,
672+ transaction_function : t .Callable [
673+ te .Concatenate [AsyncManagedTransaction , _P ], t .Awaitable [_R ]
674+ ],
675+ * args : _P .args , ** kwargs : _P .kwargs
676+ ) -> _R :
677+ """Execute a unit of work in a managed write transaction.
678+
679+ .. note::
680+ This does not necessarily imply access control, see the session
681+ configuration option :ref:`default-access-mode-ref`.
682+
683+ This transaction will automatically be committed when the function
684+ returns unless, an exception is thrown during query execution or by
685+ the user code. Note, that this function performs retries and that the
686+ supplied `transaction_function` might get invoked more than once.
687+ Therefore, it needs to be idempotent (i.e., have the same effect,
688+ regardless if called once or many times).
689+
690+ Example::
691+
692+ async def create_node_tx(tx, name):
693+ query = "CREATE (n:NodeExample { name: $name }) RETURN id(n) AS node_id"
694+ result = await tx.run(query, name=name)
695+ record = await result.single()
696+ return record["node_id"]
697+
698+ async with driver.session() as session:
699+ node_id = await session.execute_write(create_node_tx, "example")
700+
701+ :param transaction_function: a function that takes a transaction as an
702+ argument and does work with the transaction.
703+ `transaction_function(tx, *args, **kwargs)` where `tx` is a
704+ :class:`.AsyncManagedTransaction`.
705+ :param args: additional arguments for the `transaction_function`
706+ :param kwargs: key word arguments for the `transaction_function`
707+
708+ :raises SessionError: if the session has been closed.
709+
710+ :return: a result as returned by the given unit of work
711+
712+ .. versionadded:: 5.0
713+ """
714+ return await self ._run_transaction (
715+ WRITE_ACCESS , transaction_function , * args , ** kwargs
716+ )
717+
718+ # TODO 6.0: Remove this method
719+ @deprecated ("write_transaction has been renamed to execute_write" )
598720 async def write_transaction (
599721 self ,
600722 transaction_function : t .Callable [
@@ -636,6 +758,9 @@ async def create_node_tx(tx, name):
636758 :raises SessionError: if the session has been closed.
637759
638760 :return: a result as returned by the given unit of work
761+
762+ .. deprecated:: 5.0
763+ Method was renamed to :meth:`.execute_write`.
639764 """
640765 return await self ._run_transaction (
641766 WRITE_ACCESS , transaction_function , * args , ** kwargs
0 commit comments