Skip to content

Commit 3c1d5df

Browse files
author
Mickaël Guérin
authored
Merge pull request #3 from peopledoc/readme
README
2 parents 58f7264 + ec7301c commit 3c1d5df

File tree

1 file changed

+78
-1
lines changed

1 file changed

+78
-1
lines changed

README.md

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,79 @@
11
# django-postgres-hot-upgrade
2-
Django app that resets django.contrib.postgres caches that stores postgres extensions OIDs
2+
3+
Let Django clear its PostgreSQL extensions OIDs cache, making it possible to update
4+
the PostgreSQL version to a new major version on the fly.
5+
6+
## The how
7+
```console
8+
$ pip install django-postgres-hot-upgrade
9+
```
10+
```python
11+
INSTALLED_APPS = [
12+
...,
13+
# Warning: django_postgres_hot_upgrade requires to be placed before
14+
# django.contrib.postgres otherwise it will not work.
15+
'django_postgres_hot_upgrade',
16+
'django.contrib.postgres',
17+
...,
18+
]
19+
```
20+
21+
## The why
22+
23+
PostgreSQL keeps internal ids of for various objects
24+
([OIDs](https://www.postgresql.org/docs/current/datatype-oid.html)). This includes
25+
loaded extentions. In order to interact with those extensions, Django needs to know
26+
these IODs, so it loads them and, in order to avoid [unneeded
27+
requests](https://code.djangoproject.com/ticket/28334?), it caches them in memory for
28+
the duration of the process.
29+
30+
Several PostgreSQL servers running the same version of PostgreSQL will have consistent
31+
OIDs but when you upgrade, OIDs can change. If one uses a PostgreSQL load balancer such
32+
as [pgbouncer](https://www.pgbouncer.org/) or [pgpool](https://www.pgpool.net), one
33+
could be tempted to migrate between major PostgreSQL versions on the fly, avoinding
34+
downtime. Indeed, for sufficiently recent versions of PostgreSQL, this would work, apart
35+
from the OID problem: if OIDs change, Django needs to update its cache.
36+
37+
`django_postgres_hot_upgrade` memorizes the postgres version of the server after each
38+
connection. When the version is updated, it clears the internal Django OIDs cache,
39+
forcing Django to fetch the new values.
40+
41+
42+
## The rest
43+
44+
**Compatibility**: Please refer to versions of Python and Django tested in
45+
[tox.ini](tox.ini).
46+
47+
**License**: [MIT](LICENSE)
48+
49+
**Code of Conduct**: This project is placed under the [Contributor
50+
Coveneant](https://www.contributor-covenant.org/version/2/0/code_of_conduct/). Please
51+
report any abuse to `joachim.jablon at people-doc.com`.
52+
53+
54+
## [Maintainers] The ugly part
55+
56+
Apart from its unit tests, this package has an integration test. In order to test the
57+
feature, we need to simulate a change of OIDs caused by a live update from PG10 to PG12
58+
in a controlled CI environment. This is the most fragile part of the lib, and the most
59+
likely to break in the future. Here's what you need to know:
60+
61+
- `docker-compose.yml` define two databases `postgres10` and `postgres12` listening on
62+
5432 and 5433 respectively.
63+
- `tests/django_settings.py` define a `default` database using libpq envvars. Note that
64+
in the settings, we requests the tests to run on the normal database instead of
65+
dedicated `test_<foo>` database.
66+
- The OIDs are created by Postgres when installing the extensions. This happens in
67+
`tests/migrations/0001_initial.py`. The `DJANGO_REVERSE_OPERATIONS` env var controls
68+
the order of the 2 extensions creation. Running the PG10 migration in normal order
69+
and the PG12 migration in reverse order ensures the OIDs will be different.
70+
- The `runtests` script ensure the migrations run on both databases in the decided
71+
order, then launches the test. Without this, the integration test would likely fail
72+
because the OIDs would be the same in the two databases.
73+
- `tox` calls `runtests`.
74+
- GitHub Actions call `tox`.
75+
76+
The following work to launch tests locally:
77+
78+
- run `tox` or `runtests` on fresh databases
79+
- run `pytests` if you know the OIDs are already properly set on the 2 databases

0 commit comments

Comments
 (0)