|
| 1 | +# Features |
| 2 | + |
| 3 | +## Intentional transaction management |
| 4 | + |
| 5 | +Django Subatomic grants precise control over: |
| 6 | + |
| 7 | +- the creation of database [transactions and savepoints](transactions-savepoints-and-atomic.md), |
| 8 | +- requirements for [atomicity and durability][acid]. |
| 9 | + |
| 10 | +### Unambiguous transactions |
| 11 | + |
| 12 | +Subatomic's [`transaction`][django_subatomic.db.transaction] |
| 13 | +unambiguously starts a new database transaction, |
| 14 | +unlike Django's [`atomic`][atomic] which sometimes creates a savepoint. |
| 15 | + |
| 16 | +The exact behaviour of `atomic` can be tricky to reason about, |
| 17 | +and can lead to [subtle bugs](why.md). |
| 18 | +By using Subatomic to explicitly express desired behaviour, |
| 19 | +developers are empowered to avoid these bugs. |
| 20 | + |
| 21 | +### Require atomicity separately from transaction management |
| 22 | + |
| 23 | +Subatomic's [`transaction_required`][django_subatomic.db.transaction_required] decorator |
| 24 | +allows developers to decouple code which must be run in a transaction |
| 25 | +from code which is responsible for the management of that transaction. |
| 26 | + |
| 27 | +Using this instead of an [`atomic`][atomic] decorator also |
| 28 | +prevents the [accidental creation of unnecessary savepoints](why.md) |
| 29 | +when a transaction is already open. |
| 30 | +Subatomic provides the [`savepoint`][django_subatomic.db.savepoint] context manager |
| 31 | +for when savepoints _are_ necessary. |
| 32 | + |
| 33 | +### Require durability without creating a transaction |
| 34 | + |
| 35 | +Subatomic provides the [`durable`][django_subatomic.db.durable] decorator |
| 36 | +to ensure that a function is called [durably][durable] |
| 37 | +without starting a database transaction at the same time. |
| 38 | + |
| 39 | +## No immediate "after-commit" callbacks |
| 40 | + |
| 41 | +Subatomic's [`run_after_commit`][django_subatomic.db.run_after_commit] will ensure that |
| 42 | +after-commit callbacks are only registered when a transaction is open. |
| 43 | +If no transaction is open, an error will be raised. |
| 44 | +This can expose that a transaction is missing or open on a different database, |
| 45 | +and prevents code from reading as though a callback will be deferred when it won't be. |
| 46 | + |
| 47 | +This is in contrast to the default behaviour of Django's [`on_commit`][on_commit] function, |
| 48 | +where after-commit callbacks outside of transactions are run immediately. |
| 49 | + |
| 50 | +## More realistic tests |
| 51 | + |
| 52 | +Usually, |
| 53 | +Django tests are each wrapped in a transaction |
| 54 | +which is rolled back when the test completes, |
| 55 | +meaning after-commit callbacks are not run. |
| 56 | + |
| 57 | +To simulate realistic production behaviour, |
| 58 | +Subatomic runs after-commit callbacks when exiting the |
| 59 | +outermost [`transaction`][django_subatomic.db.transaction] |
| 60 | +(or [`transaction_if_not_already`][django_subatomic.db.transaction_if_not_already]) context. |
| 61 | +This emulates how the application will behave when deployed |
| 62 | +and means that tests reproduce realistic application behaviour |
| 63 | +without resorting to [other more costly or error-prone testing strategies](testing-after-commit-callbacks.md). |
| 64 | + |
| 65 | +## Progressive integration support |
| 66 | + |
| 67 | +The larger your project is, |
| 68 | +the more likely you are to benefit from |
| 69 | +the guardrails offered by Django Subatomic's strict features. |
| 70 | +Paradoxically, the larger your project is, |
| 71 | +the more difficult it may be to enable them all. |
| 72 | + |
| 73 | +Integrating Django Subatomic all at once |
| 74 | +could be a daunting task for larger projects, |
| 75 | +so we provide some [settings to ease the process](reference/settings.md). |
| 76 | +These allow you to progressively roll out strict behaviour |
| 77 | +on a per-test or per-feature basis. |
| 78 | + |
| 79 | + |
| 80 | +[acid]: https://en.wikipedia.org/wiki/ACID |
| 81 | +[atomic]: https://docs.djangoproject.com/en/stable/topics/db/transactions/#django.db.transaction.atomic |
| 82 | +[durable]: https://en.wikipedia.org/wiki/ACID#Durability |
| 83 | +[on_commit]: https://docs.djangoproject.com/en/stable/topics/db/transactions/#django.db.transaction.on_commit |
| 84 | +[override_settings]: https://docs.djangoproject.com/en/stable/topics/testing/tools/#django.test.override_settings |
| 85 | +[TransactionTestCase]: https://docs.djangoproject.com/en/stable/topics/testing/tools/#transactiontestcase |
0 commit comments