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

set_rollback's atomic check is inaccurate #6921

Open
6 tasks done
adamchainz opened this issue Sep 10, 2019 · 2 comments · May be fixed by #6922
Open
6 tasks done

set_rollback's atomic check is inaccurate #6921

adamchainz opened this issue Sep 10, 2019 · 2 comments · May be fixed by #6922

Comments

@adamchainz
Copy link
Contributor

Checklist

  • I have verified that that issue exists against the master branch of Django REST framework.
  • I have searched for similar issues in both open and closed tickets and cannot find a duplicate.
  • This is not a usage question. (Those should be directed to the discussion group instead.)
  • This cannot be dealt with as a third party library. (We prefer new functionality to be in the form of third party libraries where possible.)
  • I have reduced the issue to the simplest possible case.
  • I have included a failing test as a pull request. (If you are unable to do so we can still accept the issue.)

Steps to reproduce

Wrap a view that errors with @non_atomic_requests, but use a transaction around it somehow. The easiest way is to test it from a Django TestCase, which uses transactions around each test. Another way would be to have a custom middleware that does a transaction a different way.

Expected behavior

rest_framework.set_rollback should not call transaction.set_rollback because the view is declared as non-atomic.

Actual behavior

rest_framework.set_rollback calls transaction.set_rollback. Its check for "is this view non-atomic" checks connection.in_atomic_block which as indicated above can be true for a number of reasons.

@adamchainz adamchainz changed the title set_rollback() isn't multi-DB aware set_rollback's atomic check is inaccurate Sep 10, 2019
adamchainz added a commit to adamchainz/django-rest-framework that referenced this issue Sep 10, 2019
\## Description

Fixes encode#6921.

Added tests that fail before and pass afterwards.

Remove the check for `connection.in_atomic_block` to determine if the current request is under a `transaction.atomic` from `ATOMIC_REQUESTS`. Instead, duplicate the method that Django itself uses [in BaseHandler](https://github.com/django/django/blob/964dd4f4f208722d8993a35c1ff047d353cea1ea/django/core/handlers/base.py#L64).

This requires fetching the actual view function from `as_view()`, as seen by the URL resolver / BaseHandler. Since this requires `request`, I've also changed the accesses in `get_exception_handler_context` to be direct attribute accesses rather than `getattr()`. It seems the `getattr` defaults not accessible since `self.request`, `self.args`, and `self.kwargs` are always set in `dispatch()` before `handle_exception()` can ever be called. This is useful since `request` is always needed for the new `set_rollback` logic.
@adamchainz adamchainz linked a pull request Sep 10, 2019 that will close this issue
adamchainz added a commit to adamchainz/django-rest-framework that referenced this issue Sep 24, 2019
\## Description

Fixes encode#6921.

Added tests that fail before and pass afterwards.

Remove the check for `connection.in_atomic_block` to determine if the current request is under a `transaction.atomic` from `ATOMIC_REQUESTS`. Instead, duplicate the method that Django itself uses [in BaseHandler](https://github.com/django/django/blob/964dd4f4f208722d8993a35c1ff047d353cea1ea/django/core/handlers/base.py#L64).

This requires fetching the actual view function from `as_view()`, as seen by the URL resolver / BaseHandler. Since this requires `request`, I've also changed the accesses in `get_exception_handler_context` to be direct attribute accesses rather than `getattr()`. It seems the `getattr` defaults not accessible since `self.request`, `self.args`, and `self.kwargs` are always set in `dispatch()` before `handle_exception()` can ever be called. This is useful since `request` is always needed for the new `set_rollback` logic.
adamchainz added a commit to adamchainz/django-rest-framework that referenced this issue Dec 13, 2019
\## Description

Fixes encode#6921.

Added tests that fail before and pass afterwards.

Remove the check for `connection.in_atomic_block` to determine if the current request is under a `transaction.atomic` from `ATOMIC_REQUESTS`. Instead, duplicate the method that Django itself uses [in BaseHandler](https://github.com/django/django/blob/964dd4f4f208722d8993a35c1ff047d353cea1ea/django/core/handlers/base.py#L64).

This requires fetching the actual view function from `as_view()`, as seen by the URL resolver / BaseHandler. Since this requires `request`, I've also changed the accesses in `get_exception_handler_context` to be direct attribute accesses rather than `getattr()`. It seems the `getattr` defaults not accessible since `self.request`, `self.args`, and `self.kwargs` are always set in `dispatch()` before `handle_exception()` can ever be called. This is useful since `request` is always needed for the new `set_rollback` logic.
@sww314
Copy link

sww314 commented May 5, 2021

I am seeing this on DRF 3.12

When using a @transaction.non_atomic_requests, I get an transaction error. I am also using a multi-db solution.

@stale
Copy link

stale bot commented Apr 29, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Apr 29, 2022
@auvipy auvipy removed the stale label Jan 6, 2023
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 a pull request may close this issue.

3 participants