Skip to content

Commit 82f0f1f

Browse files
committed
Link to Django's docs where we discuss Django's API
1 parent 9ca8861 commit 82f0f1f

File tree

2 files changed

+21
-17
lines changed

2 files changed

+21
-17
lines changed

docs/transactions-savepoints-and-atomic.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ which can be used as both a decorator and a context manager.
2323

2424
SQL does not support nested transactions,
2525
so nesting is not supported by `transaction`.
26-
It acts like [Django's `atomic` with `durable=True`](https://docs.djangoproject.com/en/5.0/topics/db/transactions/#controlling-transactions-explicitly).
26+
It acts like [Django's `atomic` with `durable=True`][django-atomic]
2727

2828
See [_Atomic code_](#atomic-code)
2929
for code which requires a transaction, but doesn't require partial rollback.

docs/why.md

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
# Django's Atomic
22

3-
This doc will discuss the behaviours available through Django's `atomic`
3+
This doc will discuss the behaviours available through [Django's `atomic`][atomic]
44
and the outcomes people are usually trying to achieve with it.
5-
It goes on to outline some pitfalls that can result from using `atomic`
5+
It goes on to outline some pitfalls that can result from using [`atomic`][atomic]
66
and how Subatomic avoids them.
77

8-
Django's `atomic` ensures database changes are committed together-or-not-at-all.
8+
Django's [`atomic`][atomic] ensures database changes are committed together-or-not-at-all.
99
It creates a savepoint or a transaction depending on two factors:
1010

1111
- The arguments passed to it (`durable=` and `savepoint=`).
1212
- If a database transaction is already open.
1313

1414
## Behaviours
1515

16-
The *Behaviours* which `atomic` exhibits are:
16+
The *Behaviours* which [`atomic`][atomic] exhibits are:
1717

1818
| `savepoint=` | `durable=False` (default) | `durable=True` |
1919
| --- | --- | --- |
@@ -22,7 +22,7 @@ The *Behaviours* which `atomic` exhibits are:
2222

2323
## Outcomes
2424

25-
When people use `atomic`,
25+
When people use [`atomic`][atomic],
2626
they're generally trying to achieve one of three *Outcomes*:
2727

2828
1. to create a *transaction*
@@ -39,9 +39,9 @@ they're generally trying to achieve one of three *Outcomes*:
3939

4040
Ideally, we should be able to look at a line of code and say what it will do.
4141

42-
Because `atomic`'s behaviour depends on whether a transaction is already open,
42+
Because [`atomic`][atomic]'s behaviour depends on whether a transaction is already open,
4343
one must know the full call stack
44-
to know what any particular `atomic` will do.
44+
to know what any particular [`atomic`][atomic] will do.
4545
If it is called in multiple code paths,
4646
developers must know that it will do different database operations
4747
depending on who calls it.
@@ -57,7 +57,7 @@ but cannot know if it is part of a larger suite of changes
5757
managed by higher-level code
5858
which must also be committed together.
5959

60-
When low-level code uses `atomic`
60+
When low-level code uses [`atomic`][atomic]
6161
to indicate that its changes should be atomic (*Outcome* **3**),
6262
this can have one of two effects:
6363

@@ -81,11 +81,11 @@ rather than run the risk of creating a transaction with the wrong scope.
8181

8282
### Savepoints by default
8383

84-
`atomic` defaults to *Behaviour* **A**
84+
[`atomic`][atomic] defaults to *Behaviour* **A**
8585
which creates savepoints by default
8686
when there is already an open transaction.
8787

88-
It's common to decorate functions with `atomic`
88+
It's common to decorate functions with [`atomic`][atomic]
8989
to indicate that code should be atomic (*Outcome* **3**),
9090
but neglect to pass `savepoint=False`.
9191
This results in more database queries than necessary.
@@ -102,7 +102,7 @@ a safe place to continue from after a failure within a transaction.
102102
Ideally then, the logic for catching the failure and continuing a transaction
103103
should be adjacent to the logic which creates the savepoint.
104104

105-
When we use `atomic` as a decorator,
105+
When we use [`atomic`][atomic] as a decorator,
106106
we separate the savepoint creation from the error handling logic.
107107
The decorated function will not be within a `try:...except...:`.
108108

@@ -111,7 +111,7 @@ can make it difficult to know
111111
where continuing after rolling back a savepoint is intended to be handled,
112112
or even if it is handled at all.
113113
This is compounded by the fact that
114-
because `atomic`'s API is ambiguous,
114+
because [`atomic`][atomic]'s API is ambiguous,
115115
it can be hard to know the intended *Outcome*.
116116

117117
To encourage putting rollback logic alongside savepoint creation,
@@ -120,16 +120,16 @@ Subatomic's `savepoint` cannot be used as a decorator.
120120
### Tests without after-commit callbacks
121121

122122
To avoid leaking state between tests,
123-
Django's `TestCase` runs each test within a transaction
123+
Django's [`TestCase`][TestCase] runs each test within a transaction
124124
which gets rolled back at the end of the test.
125125
As a result,
126-
`atomic` blocks encountered during the test
126+
[`atomic`][atomic] blocks encountered during the test
127127
will not create transactions
128128
so no after-commit callbacks will be run.
129129

130130
Even if Django wanted to simulate after-commit callbacks in tests,
131131
it has no way to know which *Outcome* was intended
132-
when it encounters an `atomic` block.
132+
when it encounters an [`atomic`][atomic] block.
133133
It might be running a high-level test where a transaction is intended
134134
and callbacks should be run,
135135
or a low-level test where an open transaction is assumed
@@ -138,9 +138,13 @@ and callbacks should _not_ be run.
138138
Without Subatomic,
139139
developers must either manually run after-commit callbacks in tests,
140140
which is prone to error and omission,
141-
or run the test using `TransactionTestCase`,
141+
or run the test using [`TransactionTestCase`][TransactionTestCase],
142142
which can be very slow.
143143

144144
Subatomic's `transaction()` function
145145
will run after-commit callbacks automatically in tests
146146
so that code behaves the same in tests as it does in production.
147+
148+
[atomic]: https://docs.djangoproject.com/en/stable/topics/db/transactions/#django.db.transaction.atomic
149+
[TestCase]: https://docs.djangoproject.com/en/stable/topics/testing/tools/#django.test.TestCase
150+
[TransactionTestCase]: https://docs.djangoproject.com/en/stable/topics/testing/tools/#django.test.TransactionTestCase

0 commit comments

Comments
 (0)