Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Classify SqlState Connection Exceptions as operational errors #1148

Merged
merged 1 commit into from Nov 17, 2020

Conversation

sjustas
Copy link

@sjustas sjustas commented Sep 7, 2020

tl;dr: conform with PEP 249 better, so that libraries can treat disconnect errors caused by PgBouncer as transient.

DatabaseError is too broad and is considered not transient failure by libraries, which causes failures where an operation could simply be re-tried, like relstorage:drivers.py#L157 or pjpersist:datamanager.py#L100

A real world example: conntect to PgBouncer instead of Postgres directly. Now, if the Postgres server is disrupted, you get a ProtocolViolation (SqlState 08P01) sent by PgBouncer: pgbouncer:src/server.c#L481 which leads to pgbouncer:/src/proto.c#L128.

Traceback (most recent call last):
  File ".../ve3.7/lib/python3.7/site-packages/celery/app/trace.py", line 385, in trace_task
    R = retval = fun(*args, **kwargs)
  <...>
  File ".../src/app/taskcontext.py", line 39, in celery_request
    conn = db.open()
  File ".../ve3.7/lib/python3.7/site-packages/ZODB/DB.py", line 793, in open
    result.open(transaction_manager)
  File ".../ve3.7/lib/python3.7/site-packages/ZODB/Connection.py", line 921, in open
    self.newTransaction(None, False)
  File ".../ve3.7/lib/python3.7/site-packages/ZODB/Connection.py", line 737, in newTransaction
    invalidated = self._storage.poll_invalidations()
  File ".../ve3.7/lib/python3.7/site-packages/relstorage/storage.py", line 1421, in poll_invalidations
    changes, new_polled_tid = self._restart_load_and_poll()
  File ".../ve3.7/lib/python3.7/site-packages/relstorage/storage.py", line 1395, in _restart_load_and_poll
    self._adapter.poller.poll_invalidations, prev, ignore_tid)
  File ".../ve3.7/lib/python3.7/site-packages/relstorage/storage.py", line 365, in _restart_load_and_call
    return f(self._load_conn, self._load_cursor, *args, **kw)
  File ".../ve3.7/lib/python3.7/site-packages/relstorage/adapters/poller.py", line 95, in poll_invalidations
    cursor.execute(self.poll_query)
psycopg2.errors.ProtocolViolation: server conn crashed?
server closed the connection unexpectedly
        This probably means the server terminated abnormally
        before or while processing the request.

PEP 249 states that unexpected disconnects and similar failures not under programmers control should be considered OperationalFailure, so higher level library developers tend to treat that exception transient.

OperationalError is inherited from DatabaseError, so this PR is mostly backwards-compatible.

@sjustas
Copy link
Author

sjustas commented Nov 17, 2020

Hey @dvarrazzo, does a change like this look reasonable to include into psycopg2?
No worries if you don't have time to look at it right now, I appreciate this is an open source effort! Just didn't want this to slip under the radar in case it looks insignificant.

@dvarrazzo
Copy link
Member

Hello @sjustas

thank you. It is not insignificant: I think the 08 errors are misclassified, yes. Because your patch converts those errors into a subclass I think it's good to accept. Other misclassifications (PL/pgSQL errors as InternalError) are pretty bad, but cannot be changed without breaking compatibility.

Could you please add a test to verify issubclass() and an entry in the NEWS file for psycopg 2.9 (we'll probably backport it too on 2.8.next too, but now master is on 2.9).

Thank you very much.

@dvarrazzo
Copy link
Member

Oh, I've noticed now that you opened the issue back in September. I apologise: it did slip under my radar, but it's absolutely something I'd like to address 👍

dvarrazzo added a commit to psycopg/psycopg that referenced this pull request Nov 17, 2020
@dvarrazzo dvarrazzo merged commit e85ef22 into psycopg:master Nov 17, 2020
@dvarrazzo
Copy link
Member

Merged, thank you very much!

@sjustas
Copy link
Author

sjustas commented Nov 18, 2020

Thank you!

@sjustas
Copy link
Author

sjustas commented Mar 31, 2021

Hey @dvarrazzo, hope you are well! Is there a chance of a new release with this small fix some time this spring? Would appreciate this a lot!

@dvarrazzo
Copy link
Member

@sjustas thank you for the nudge. I can't immediately but might in a few weeks time.

Thank you for the patience

@sjustas
Copy link
Author

sjustas commented Apr 2, 2021

No worries, and thanks in advance!

mergify bot pushed a commit to andrewbolster/bolster that referenced this pull request Nov 15, 2021
Bumps [psycopg2-binary](https://github.com/psycopg/psycopg2) from 2.9.1 to 2.9.2.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/psycopg/psycopg2/blob/master/NEWS">psycopg2-binary's changelog</a>.</em></p>
<blockquote>
<h2>Current release</h2>
<p>What's new in psycopg 2.9.2
^^^^^^^^^^^^^^^^^^^^^^^^^^^</p>
<ul>
<li>Raise <code>ValueError</code> for dates &gt;= Y10k (:ticket:<code>[#1307](https://github.com/psycopg/psycopg2/issues/1307)</code>).</li>
<li><code>~psycopg2.errorcodes</code> map and <code>~psycopg2.errors</code> classes updated to
PostgreSQL 14.</li>
<li>Add preliminary support for Python 3.11 (:tickets:<code>[#1376](psycopg/psycopg2#1376), [#1386](https://github.com/psycopg/psycopg2/issues/1386)</code>).</li>
<li>Wheel package compiled against OpenSSL 1.1.1l and PostgreSQL 14.1
(:ticket:<code>[#1388](https://github.com/psycopg/psycopg2/issues/1388)</code>).</li>
</ul>
<p>What's new in psycopg 2.9.1
^^^^^^^^^^^^^^^^^^^^^^^^^^^</p>
<p>Fix regression with named <code>sql.Placeholder</code> (:ticket:<code>[#1291](https://github.com/psycopg/psycopg2/issues/1291)</code>).</p>
<h2>What's new in psycopg 2.9</h2>
<ul>
<li><code>with connection</code> starts a transaction on autocommit transactions too
(:ticket:<code>[#941](https://github.com/psycopg/psycopg2/issues/941)</code>).</li>
<li>Timezones with fractional minutes are supported on Python 3.7 and following
(:ticket:<code>[#1272](https://github.com/psycopg/psycopg2/issues/1272)</code>).</li>
<li>Escape table and column names in <code>~cursor.copy_from()</code> and
<code>~cursor.copy_to()</code>.</li>
<li>Connection exceptions with sqlstate <code>08XXX</code> reclassified as
<code>~psycopg2.OperationalError</code> (a subclass of the previously used
<code>~psycopg2.DatabaseError</code>) (:ticket:<code>[#1148](https://github.com/psycopg/psycopg2/issues/1148)</code>).</li>
<li>Include library dirs required from libpq to work around MacOS build problems
(:ticket:<code>[#1200](https://github.com/psycopg/psycopg2/issues/1200)</code>).</li>
</ul>
<p>Other changes:</p>
<ul>
<li>Dropped support for Python 2.7, 3.4, 3.5 (:tickets:<code>[#1198](psycopg/psycopg2#1198), [#1000](psycopg/psycopg2#1000), [#1197](https://github.com/psycopg/psycopg2/issues/1197)</code>).</li>
<li>Dropped support for mx.DateTime.</li>
<li>Use <code>datetime.timezone</code> objects by default in datetime objects instead of
<code>~psycopg2.tz.FixedOffsetTimezone</code>.</li>
<li>The <code>psycopg2.tz</code> module is deprecated and scheduled to be dropped in the
next major release.</li>
<li>Provide :pep:<code>599</code> wheels packages (manylinux2014 tag) for i686 and x86_64
platforms.</li>
<li>Provide :pep:<code>600</code> wheels packages (manylinux_2_24 tag) for aarch64 and
ppc64le platforms.</li>
<li>Wheel package compiled against OpenSSL 1.1.1k and PostgreSQL 13.3.</li>
<li>Build system for Linux/MacOS binary packages moved to GitHub Actions.</li>
</ul>

</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a href="https://github.com/psycopg/psycopg2/commits">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=psycopg2-binary&package-manager=pip&previous-version=2.9.1&new-version=2.9.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>
mergify bot pushed a commit to andrewbolster/bolster that referenced this pull request Dec 29, 2021
Bumps [psycopg2-binary](https://github.com/psycopg/psycopg2) from 2.9.2 to 2.9.3.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/psycopg/psycopg2/blob/master/NEWS">psycopg2-binary's changelog</a>.</em></p>
<blockquote>
<h2>Current release</h2>
<p>What's new in psycopg 2.9.3
^^^^^^^^^^^^^^^^^^^^^^^^^^^</p>
<ul>
<li>Alpine (musl) wheels now available (:ticket:<code>[#1148](https://github.com/psycopg/psycopg2/issues/1148)</code>).</li>
</ul>
<p>What's new in psycopg 2.9.2
^^^^^^^^^^^^^^^^^^^^^^^^^^^</p>
<ul>
<li>Raise <code>ValueError</code> for dates &gt;= Y10k (:ticket:<code>[#1307](https://github.com/psycopg/psycopg2/issues/1307)</code>).</li>
<li><code>~psycopg2.errorcodes</code> map and <code>~psycopg2.errors</code> classes updated to
PostgreSQL 14.</li>
<li>Add preliminary support for Python 3.11 (:tickets:<code>[#1376](psycopg/psycopg2#1376), [#1386](https://github.com/psycopg/psycopg2/issues/1386)</code>).</li>
<li>Wheel package compiled against OpenSSL 1.1.1l and PostgreSQL 14.1
(:ticket:<code>[#1388](https://github.com/psycopg/psycopg2/issues/1388)</code>).</li>
</ul>
<p>What's new in psycopg 2.9.1
^^^^^^^^^^^^^^^^^^^^^^^^^^^</p>
<p>Fix regression with named <code>sql.Placeholder</code> (:ticket:<code>[#1291](https://github.com/psycopg/psycopg2/issues/1291)</code>).</p>
<h2>What's new in psycopg 2.9</h2>
<ul>
<li><code>with connection</code> starts a transaction on autocommit transactions too
(:ticket:<code>[#941](https://github.com/psycopg/psycopg2/issues/941)</code>).</li>
<li>Timezones with fractional minutes are supported on Python 3.7 and following
(:ticket:<code>[#1272](https://github.com/psycopg/psycopg2/issues/1272)</code>).</li>
<li>Escape table and column names in <code>~cursor.copy_from()</code> and
<code>~cursor.copy_to()</code>.</li>
<li>Connection exceptions with sqlstate <code>08XXX</code> reclassified as
<code>~psycopg2.OperationalError</code> (a subclass of the previously used
<code>~psycopg2.DatabaseError</code>) (:ticket:<code>[#1148](https://github.com/psycopg/psycopg2/issues/1148)</code>).</li>
<li>Include library dirs required from libpq to work around MacOS build problems
(:ticket:<code>[#1200](https://github.com/psycopg/psycopg2/issues/1200)</code>).</li>
</ul>
<p>Other changes:</p>
<ul>
<li>Dropped support for Python 2.7, 3.4, 3.5 (:tickets:<code>[#1198](psycopg/psycopg2#1198), [#1000](psycopg/psycopg2#1000), [#1197](https://github.com/psycopg/psycopg2/issues/1197)</code>).</li>
<li>Dropped support for mx.DateTime.</li>
<li>Use <code>datetime.timezone</code> objects by default in datetime objects instead of
<code>~psycopg2.tz.FixedOffsetTimezone</code>.</li>
<li>The <code>psycopg2.tz</code> module is deprecated and scheduled to be dropped in the
next major release.</li>
<li>Provide :pep:<code>599</code> wheels packages (manylinux2014 tag) for i686 and x86_64</li>
</ul>

</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a href="https://github.com/psycopg/psycopg2/commits">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=psycopg2-binary&package-manager=pip&previous-version=2.9.2&new-version=2.9.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants