AsyncIO API
Client
Create an asynchronous client with a lazy connection pool.
The connection parameters may be specified either as a connection URI in dsn, or as specific keyword arguments, or both. If both dsn and keyword arguments are specified, the latter override the corresponding values parsed from the connection URI.
If no connection parameter is specified, the client will try to search in environment variables and then the current project, see Client Library Connection docs for more information.
Returns a new AsyncIOClient
object.
-
dsn
(str
) – If this parameter does not start withedgedb://
then this is interpreted as the name of a local instance.Otherwise it specifies a single string in the following format:edgedb://user:password@host:port/database?option=value
. The following options are recognized: host, port, user, database, password. For a complete reference on DSN, see the DSN Specification. -
host
– Database host address as an IP address or a domain name;If not specified, the following will be tried, in order:- host address(es) parsed from the dsn argument,
- the value of the
EDGEDB_HOST
environment variable, "localhost"
.
-
port
– Port number to connect to at the server host. If multiple host addresses were specified, this parameter may specify a sequence of port numbers of the same length as the host sequence, or it may specify a single port number to be used for all host addresses.If not specified, the value parsed from the dsn argument is used, or the value of theEDGEDB_PORT
environment variable, or5656
if neither is specified. -
user
– The name of the database role used for authentication.If not specified, the value parsed from the dsn argument is used, or the value of theEDGEDB_USER
environment variable, or the operating system name of the user running the application. -
database
– The name of the database to connect to.If not specified, the value parsed from the dsn argument is used, or the value of theEDGEDB_DATABASE
environment variable, or the operating system name of the user running the application. -
password
– Password to be used for authentication, if the server requires one. If not specified, the value parsed from the dsn argument is used, or the value of theEDGEDB_PASSWORD
environment variable. Note that the use of the environment variable is discouraged as other users and applications may be able to read it without needing specific privileges. -
secret_key
– Secret key to be used for authentication, if the server requires one. If not specified, the value parsed from the dsn argument is used, or the value of theEDGEDB_SECRET_KEY
environment variable. Note that the use of the environment variable is discouraged as other users and applications may be able to read it without needing specific privileges. -
timeout
(float
) – Connection timeout in seconds. -
concurrency
(int
) – Max number of connections in the pool. If not set, the suggested concurrency value provided by the server is used.
An instance of AsyncIOClient
.
The APIs on the returned client instance can be safely used by different
asyncio.Task
/coroutines, because under the hood they are
checking out different connections from the pool to run the queries:
client = edgedb.create_async_client()
await client.query('SELECT {1, 2, 3}')
The same for transactions:
client = edgedb.create_async_client()
async for tx in client.transaction():
async with tx:
await tx.query('SELECT {1, 2, 3}')
An asynchronous client with a connection pool, safe for concurrent use.
Async clients are created by calling
create_async_client()
.
Acquire a connection and use it to run a query and return the results
as an edgedb.Set
instance. The temporary
connection is automatically returned back to the pool.
-
query
(str
) – Query text. -
args
– Positional query arguments. -
kwargs
– Named query arguments.
An instance of edgedb.Set
containing
the query result.
Note that positional and named query arguments cannot be mixed.
Acquire a connection and use it to run an optional singleton-returning query and return its element. The temporary connection is automatically returned back to the pool.
-
query
(str
) – Query text. -
args
– Positional query arguments. -
kwargs
– Named query arguments.
Query result.
The query must return no more than one element. If the query returns
more than one element, an edgedb.ResultCardinalityMismatchError
is raised, if it returns an empty set, None
is returned.
Note, that positional and named query arguments cannot be mixed.
Acquire a connection and use it to run a singleton-returning query and return its element. The temporary connection is automatically returned back to the pool.
-
query
(str
) – Query text. -
args
– Positional query arguments. -
kwargs
– Named query arguments.
Query result.
The query must return exactly one element. If the query returns
more than one element, an edgedb.ResultCardinalityMismatchError
is raised, if it returns an empty set, an edgedb.NoDataError
is raised.
Note, that positional and named query arguments cannot be mixed.
Acquire a connection and use it to run a query and return the results as JSON. The temporary connection is automatically returned back to the pool.
-
query
(str
) – Query text. -
args
– Positional query arguments. -
kwargs
– Named query arguments.
A JSON string containing an array of query results.
Note, that positional and named query arguments cannot be mixed.
Caution is advised when reading decimal
values using
this method. The JSON specification does not have a limit
on significant digits, so a decimal
number can be
losslessly represented in JSON. However, the default JSON
decoder in Python will read all such numbers as float
values, which may result in errors or precision loss. If
such loss is unacceptable, then consider casting the value
into str
and decoding it on the client side into a
more appropriate type, such as Decimal
.
Acquire a connection and use it to run an optional singleton-returning query and return its element in JSON. The temporary connection is automatically returned back to the pool.
-
query
(str
) – Query text. -
args
– Positional query arguments. -
kwargs
– Named query arguments.
Query result encoded in JSON.
The query must return no more than one element. If the query returns
more than one element, an edgedb.ResultCardinalityMismatchError
is raised, if it returns an empty set, "null"
is returned.
Note, that positional and named query arguments cannot be mixed.
Caution is advised when reading decimal
values using
this method. The JSON specification does not have a limit
on significant digits, so a decimal
number can be
losslessly represented in JSON. However, the default JSON
decoder in Python will read all such numbers as float
values, which may result in errors or precision loss. If
such loss is unacceptable, then consider casting the value
into str
and decoding it on the client side into a
more appropriate type, such as Decimal
.
Acquire a connection and use it to run a singleton-returning query and return its element in JSON. The temporary connection is automatically returned back to the pool.
-
query
(str
) – Query text. -
args
– Positional query arguments. -
kwargs
– Named query arguments.
Query result encoded in JSON.
The query must return exactly one element. If the query returns
more than one element, an edgedb.ResultCardinalityMismatchError
is raised, if it returns an empty set, an edgedb.NoDataError
is raised.
Note, that positional and named query arguments cannot be mixed.
Caution is advised when reading decimal
values using
this method. The JSON specification does not have a limit
on significant digits, so a decimal
number can be
losslessly represented in JSON. However, the default JSON
decoder in Python will read all such numbers as float
values, which may result in errors or precision loss. If
such loss is unacceptable, then consider casting the value
into str
and decoding it on the client side into a
more appropriate type, such as Decimal
.
Acquire a connection and use it to execute an EdgeQL command (or commands). The temporary connection is automatically returned back to the pool.
query
(str
) – Query text.
The commands must take no arguments.
Example:
>>> ... ... ... ... ... ...
await con.execute('''
CREATE TYPE MyType {
CREATE PROPERTY a -> int64
};
FOR x IN {100, 200, 300}
UNION INSERT MyType { a := x };
''')
If the results of query are desired, query()
,
query_single()
or query_required_single()
should be used instead.
Open a retryable transaction loop.
This is the preferred method of initiating and running a database
transaction in a robust fashion. The transaction()
transaction loop will attempt to re-execute the transaction loop body
if a transient error occurs, such as a network error or a transaction
serialization error.
Returns an instance of AsyncIORetry
.
See Transactions for more details.
Example:
async for tx in con.transaction():
async with tx:
value = await tx.query_single("SELECT Counter.value")
await tx.execute(
"UPDATE Counter SET { value := <int64>$value }",
value=value + 1,
)
Note that we are executing queries on the tx
object rather
than on the original connection.
The transaction starts lazily. A connection is only acquired from the pool when the first query is issued on the transaction instance.
Attempt to gracefully close all connections in the pool.
Wait until all pool connections are released, close them and
shut down the pool. If any error (including cancellation) occurs
in aclose()
the pool will terminate by calling
terminate()
.
It is advisable to use asyncio.wait_for()
to set
a timeout.
If the client does not yet have any open connections in its pool, attempts to open a connection, else returns immediately.
Since the client lazily creates new connections as needed (up to the
configured concurrency
limit), the first connection attempt will
only occur when the first query is run on a client. ensureConnected
can be useful to catch any errors resulting from connection
mis-configuration by triggering the first connection attempt
explicitly.
Returns a shallow copy of the client with adjusted transaction options.
options
(TransactionOptions
) – Object that encapsulates transaction options.
See Transaction Options for details.
Returns a shallow copy of the client with adjusted retry options.
options
(RetryOptions
) – Object that encapsulates retry options.
See Retry Options for details.
Returns a shallow copy of the client with adjusted default module.
This is equivalent to using the set module
command, or using the
reset module
command when giving None
.
See State.with_default_module()
for details.
Returns a shallow copy of the client with adjusted module aliases.
This is equivalent to using the set alias
command.
See State.with_module_aliases()
for details.
Returns a shallow copy of the client without specified module aliases.
This is equivalent to using the reset alias
command.
See State.without_module_aliases()
for details.
Returns a shallow copy of the client with adjusted session config.
This is equivalent to using the configure session set
command.
See State.with_config()
for details.
Returns a shallow copy of the client without specified session config.
This is equivalent to using the configure session reset
command.
See State.without_config()
for details.
Returns a shallow copy of the client with adjusted global values.
This is equivalent to using the set global
command.
See State.with_globals()
for details.
Returns a shallow copy of the client without specified globals.
This is equivalent to using the reset global
command.
See State.without_globals()
for details.
Transactions
The most robust way to execute transactional code is to use
the transaction()
loop API:
async for tx in client.transaction():
async with tx:
await tx.execute("INSERT User { name := 'Don' }")
Note that we execute queries on the tx
object in the above
example, rather than on the original client
object.
The tx
object stores a connection acquired from the pool, so that all
queries can be executed on the same connection in the same transaction.
Transaction start is lazy. async for tx
or async with tx
won’t acquire
the connection and start the transaction. It’s only done when executing the
first query on the tx
object. That connection is pinned to the tx
object even when a reconnection is needed, until leaving the final
async with
transaction block.
The transaction()
API guarantees that:
-
Transactions are executed atomically;
-
If a transaction is failed for any of the number of transient errors (i.e. a network failure or a concurrent update error), the transaction would be retried;
-
If any other, non-retryable exception occurs, the transaction is rolled back, and the exception is propagated, immediately aborting the
transaction()
block.
The key implication of retrying transactions is that the entire nested code block can be re-run, including any non-querying Python code. Here is an example:
async for tx in client.transaction():
async with tx:
user = await tx.query_single(
"SELECT User { email } FILTER .login = <str>$login",
login=login,
)
data = await httpclient.get(
'https://service.local/email_info',
params=dict(email=user.email),
)
user = await tx.query_single('''
UPDATE User FILTER .login = <str>$login
SET { email_info := <json>$data}
''',
login=login,
data=data,
)
In the above example, the execution of the HTTP request would be retried too. The core of the issue is that whenever a transaction is interrupted the user’s email might have been changed (as the result of a concurrent transaction), so we have to redo all the work done.
Generally it’s recommended to not execute any long running code within the transaction unless absolutely necessary.
Transactions allocate expensive server resources, and having too many concurrent long-running transactions will negatively impact the performance of the DB server.
To rollback a transaction that is in progress raise an exception.
class RollBack(Exception):
"A user defined exception."
try:
async for tx in client.transaction():
async with tx:
raise RollBack
except RollBack:
pass
See also:
Represents a wrapper that yields AsyncIOTransaction
object when iterating.
See AsyncIOClient.transaction()
method for an example.
Yields AsyncIOTransaction
object every time transaction
has to be repeated.
Represents a transaction.
Instances of this type are yielded by a AsyncIORetry
iterator.
Acquire a connection if the current transaction doesn’t have one yet,
and use it to run a query and return the results
as an edgedb.Set
instance. The temporary
connection is automatically returned back to the pool when exiting the
transaction block.
See AsyncIOClient.query()
for details.
Acquire a connection if the current transaction doesn’t have one yet, and use it to run an optional singleton-returning query and return its element. The temporary connection is automatically returned back to the pool when exiting the transaction block.
See AsyncIOClient.query_single()
for details.
Acquire a connection if the current transaction doesn’t have one yet, and use it to run a singleton-returning query and return its element. The temporary connection is automatically returned back to the pool when exiting the transaction block.
See AsyncIOClient.query_required_single()
for details.
Acquire a connection if the current transaction doesn’t have one yet, and use it to run a query and return the results as JSON. The temporary connection is automatically returned back to the pool when exiting the transaction block.
See AsyncIOClient.query_json()
for details.
Acquire a connection if the current transaction doesn’t have one yet, and use it to run an optional singleton-returning query and return its element in JSON. The temporary connection is automatically returned back to the pool when exiting the transaction block.
See AsyncIOClient.query_single_json()
for details.
Acquire a connection if the current transaction doesn’t have one yet, and use it to run a singleton-returning query and return its element in JSON. The temporary connection is automatically returned back to the pool when exiting the transaction block.
See AsyncIOClient.query_requried_single_json()
for details.
Acquire a connection if the current transaction doesn’t have one yet, and use it to execute an EdgeQL command (or commands). The temporary connection is automatically returned back to the pool when exiting the transaction block.
See AsyncIOClient.execute()
for details.