Try to fix the flakiness shown by deaf_listen() in CI. Maybe there is a
race condition in listen()/connect() but I have also seen problems
related with localhost in the /etc/hosts file and ipv6, so let's first
try this.
feat: add a timeout parameter to Connection.cancel_safe()
This will only work for PGcancelConn, i.e. libpq >= 17, or thanks to
added waiting logic in AsyncConnection's implementation; so we add a
note about the limitation in Connection's documentation.
fix: avoid explicit str() call when logging exception
This was done as paranoia check for Sentry which might uses the repr of
the exception even if we asked for `%s` and therefore might leak
secrets, but frankly it's not our responsibility.
Avoid catching NotSupported, just check for the libpq version.
Also avoid the half exception handler in `_cancel_gen()`: as in the
legacy branch, warn and ignore any error happening in the outermost
method, without adding an ignore exception policy in an implementation
method.
This method was useful before introducing cancel_safe, which is now the
function of choice for internal cancelling.
Also refactor the exception handling to account for possible errors in
`PGcancel.cancel()`, not only in `PGconn.get_cancel()`, to make sure to
not clobber an exception bubbling up with ours, whatever happens to the
underlying connection.
fix(pool): make sure there are no connection in the pool after close()
The case has been reported in #784. While not easy to reproduce, it
seems that it might be caused by the pool being closed while a worker is
still trying to create a connection, which will be put in the _pool
state after supposedly no other operation should have been performed.
Stop the workers and then empty the pool only after they have stopped to
run.
Also refactor the cleanup of the pool and waiting queue, moving them
to close(). There is no reason why a method called "stop workers" should
empty them, and there is no other code path that use such feature.
tests: fix allow to skip running the pool tests again
`pytest -m not pool` should allow to skip the pool test. However,
because of the attribute access at import time to define the test
marker, import failed as well.
Convert the marker to strings which will be used in a getattr by the
fixture. Extend async-to-sync to convert the pool classes names from the
string too.
Denis Laxalde [Fri, 24 Mar 2023 13:55:18 +0000 (14:55 +0100)]
feat: use non-blocking cancellation upon Copy termination
The logic of Copy termination, in finish(), is reworked so that
connection cancellation is invoked from there directly instead of from
_end_copy_out_gen() as we cannot call async code from the generator.
Denis Laxalde [Fri, 24 Mar 2023 13:55:18 +0000 (14:55 +0100)]
feat: add encrypted and non-blocking cancellation
We introduce Connection.cancel_safe() which uses the encrypted and
non-blocking libpq cancellation API available with PostgreSQL 17. As a
non-blocking entry point, cancel_safe() delegates to a generator function,
namely _cancel_gen(). If the libpq version is too old, the method raises
a NotSupportedError.
CTRL+C handling (in Connection.wait() or Cursor.stream()) also uses the
non-blocking cancellation but falls back to old method if the former is
not supported.
The behavior of cancel() method (either on Connection or
AsyncConnection) is kept unchanged to use the old cancellation API.
Similarly to PGconn, PGcancelConn must not be used after .finish(); we
raise an OperationalError to prevent segfault when the connection
pointer is NULL.
We split the previous (misnamed) test_cancel_nonblocking() into
test_cancel_conn_blocking() and test_cancel_conn_nonblocking()
respectively checking PQcancelBlocking() and
PQcancelStart()/PQcancelPoll().
The cancellable_query() is now responsible for creating the monitor_conn
and uses a PGconn value, coming from the pgconn fixture in tests.
Denis Laxalde [Thu, 23 Mar 2023 12:51:16 +0000 (13:51 +0100)]
feat: add libpq interface for encrypted and non-blocking cancellation
Encrypted and non-blocking cancellation should be part PostgreSQL 17:
- https://commitfest.postgresql.org/37/3511/
- https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=61461a300c1cb5d53955ecd792ad0ce75a104736
We here add the interface for libpq functions for this feature.
An extra test is introduced, it closely reproduces
src/test/modules/libpq_pipeline/libpq_pipeline::test_cancel() in
PostgreSQL test suite.
The error_message property of PGcancelConn is directly an str and
PGcancelConn has no encoding specified and all messages come from the
client (libpq).
Daniele Varrazzo [Fri, 26 Jan 2024 09:47:31 +0000 (09:47 +0000)]
refactor: handle timeout in the connection generator, not the waiting function
The waiting function is supposed to be generic, the timeout is a policy
decision of the generator.
This change aligns the semantics of the `timeout` parameter of `wait_conn()`
to the one of the other wait functions: the timeout is actually an
interval. It will be renamed to clarify that in a followup commit.
docs: let the 'pq' role possibly link to "devel" PostgreSQL docs
If we now set libpq_docs_version to 'devel', the pq Sphinx role will use
the master branch when looking libpq.sgml and the 'devel' URL component
when linking to libpq online documentation.
Daniele Varrazzo [Sun, 31 Mar 2024 20:57:42 +0000 (20:57 +0000)]
fix: more careful stripping of error prefixes
Only strip the known prefixes, both in English and in the currently
known localizations.
Added script to generate regexp to match every backend localization. The
script was executed on PostgreSQL commit f4ad0021af (on master branch,
before v17).
Denis Laxalde [Mon, 4 Mar 2024 07:37:58 +0000 (08:37 +0100)]
feat(tools): check last modification times in async_to_sync.py
We now only process _async.py files with a modification time higher than
their sync counterpart. A -B,--convert-all option is added to force
conversion of all (specified) input files and skip last-modification
time check.
fix: avoid to create reference loops in datetime adapters
Setting the reference to a bound method in the state creates a reference
loop.
The issue is minimal because the gc will be able to break these loops
anyway and because it mostly happens with exotic or unsupported
date/interval styles.
Daniele Varrazzo [Fri, 26 Jan 2024 09:47:31 +0000 (09:47 +0000)]
refactor: handle timeout in the connection generator, not the waiting function
The waiting function is supposed to be generic, the timeout is a policy
decision of the generator.
This change aligns the semantics of the `timeout` parameter of `wait_conn()`
to the one of the other wait functions: the timeout is actually an
interval. It will be renamed to clarify that in a followup commit.