-
Notifications
You must be signed in to change notification settings - Fork 5
Raise error when encountering unhandled callbacks #93
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,14 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). | |
|
||
## [Unreleased] | ||
|
||
### Added | ||
|
||
- An error will be raised when opening a transaction if there are pre-existing unhandled after-commit callbacks. | ||
The pre-existing callbacks would previously run when `transaction` exits. | ||
This helps catch order-of-execution bugs in tests. | ||
The old behavior can be restored using `settings.SUBATOMIC_CATCH_UNHANDLED_AFTER_COMMIT_CALLBACKS` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we keep this feature tests-only, we should have |
||
to facilitate gradual adoption of this stricter rule. | ||
meshy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
### Fixed | ||
|
||
- Ensure cleanup actions in `durable` always happen when the wrapped code raises an unexpected error. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -194,11 +194,23 @@ def _execute_on_commit_callbacks_in_tests(using: str | None = None) -> Generator | |
- Django 4.2's `run_and_clear_commit_hooks` function: | ||
https://github.com/django/django/blob/stable/4.2.x/django/db/backends/base/base.py#L762-L779 | ||
""" | ||
only_in_testcase_transaction = _innermost_atomic_block_wraps_testcase(using=using) | ||
|
||
if ( | ||
getattr(settings, "SUBATOMIC_CATCH_UNHANDLED_AFTER_COMMIT_CALLBACKS", True) | ||
and only_in_testcase_transaction | ||
): | ||
connection = django_transaction.get_connection(using) | ||
callbacks = connection.run_on_commit | ||
if callbacks: | ||
raise _UnhandledCallbacks(tuple(callback for _, callback, _ in callbacks)) | ||
|
||
yield | ||
|
||
if ( | ||
# See Note [Running after-commit callbacks in tests] | ||
getattr(settings, "SUBATOMIC_RUN_AFTER_COMMIT_CALLBACKS_IN_TESTS", True) | ||
and _innermost_atomic_block_wraps_testcase(using=using) | ||
and only_in_testcase_transaction | ||
): | ||
connection = django_transaction.get_connection(using) | ||
callbacks = connection.run_on_commit | ||
|
@@ -284,6 +296,20 @@ class _UnexpectedDanglingTransaction(Exception): | |
open_dbs: frozenset[str] | ||
|
||
|
||
@attrs.frozen | ||
class _UnhandledCallbacks(Exception): | ||
""" | ||
Raised in tests when unhandled callbacks are found before opening a transaction. | ||
|
||
This happens when after-commit callbacks are registered | ||
but not run before trying to open a database transaction. | ||
|
||
The best solution is to ensure the after-commit callbacks are run. | ||
""" | ||
|
||
callbacks: tuple[Callable[[], object], ...] | ||
Comment on lines
+309
to
+310
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: I'm not sure if it's a good idea go add these callbacks to the exception. 🤔 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's fine. |
||
|
||
|
||
# Note [After-commit callbacks require a transaction] | ||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
# After-commit callbacks may only be registered when a transaction is open. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should mention here that this is a tests-only feature. Or we could check it outside tests too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This failure-mode is only possible in tests. You're right though that I should make that clearer.