[go: up one dir, main page]

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

Fix view retrying for PostgreSQL serialization errors (TransactionRollbackError) #222

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

koirikivi
Copy link
Collaborator

Websauna should automatically retry views if a retryable exception occurs. However, this is currently bugged: Websauna won't retry views where a psycopg2.extensions.TransactionRollbackError is thrown (ie. when a serialization error occurs in PostgreSQL)

This can be tested manually by following instructions in this repo: https://github.com/koirikivi/websauna_retry_test

The first commit removes call to request.tm.abort() in websauna.system.core.views.internalservererror.internal_server_error. This call should not be needed, as pyramid_tm should handle the rollback in the case of an exception.

The second commit amends websauna.system.core.views.internalservererror.internal_server_error to avoid spamming logger.exception when a view is retried. I'm less sure about the implementation here, though it seems to work empirically. Review kindly requested!

Full story:

  • Websauna uses pyramid_retry to handle view retrying
  • pyramid_retry needs request.exception to retry
  • request.invoke_exception_view sets request.exception but only if
    it returns a view. If no exception view is configured,
    request.exception will be None.
  • Websauna adds a default exception view
    (websauna.system.core.views.internalservererror.internal_server_error),
    However, this is disabled in development by default since debug toolbar is
    enabled by default. In production settings, debug toolbar is disabled and
    pyramid_retry SHOULD work.
  • However, calling request.tm.abort() kills the current zope transaction,
    which causes a new transaction to be created when the retry process happens.
  • This new transaction no longer has the SessionDataManager from
    zope.sqlalchemy attached, which means that it no longer knows how to retry
    certain database exceptions, like those raised by psycopg2 when a
    serialization error occurs.

…ing)

Websauna should automatically retry views if a retryable exception occurs.
However, this was bugged before this commit. Full story here:

- Websauna uses `pyramid_retry` to handle view retrying
- `pyramid_retry` needs `request.exception` to retry
- `request.invoke_exception_view` sets `request.exception` but only if
  it returns a view. If no exception view is configured,
  `request.exception` will be `None`.
- Websauna adds a default exception view
  (websauna.system.core.views.internalservererror.internal_server_error),
  However, this is disabled in development by default since debug toolbar is
  enabled by default. In production settings, debug toolbar is disabled and
  `pyramid_retry` SHOULD work.
- However, calling `request.tm.abort()` kills the current zope transaction,
  which causes a new transaction to be created when the retry process happens.
- This new transaction no longer has the `SessionDataManager` from
  `zope.sqlalchemy` attached, which means that it no longer knows how to retry
  certain database exceptions, like those raised by psycopg2 when a
  serialization error occurs.

Fix by removing call to `request.tm.abort()`. It should not be needed anyway,
since `pyramid_tm` should handle the rollback in the case of an exception.
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.

1 participant