Export: the archive runs queries per application, per contact and per sent document while holding the write lock #557
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
performance
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo#557
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found on 2026-09-29 in a read-only review of postulo at
95348908d, by readingcore/export.py:build_documentand counting its queries as the data grows.Related to #247.
Checked again on 2026-10-01 against
mainat0a5cad587: still present.build_documentprefetches most of what it walks but not all of it, so an export makes several queries per application, four per contact and one per sent document.write_archiveruns it insidetransaction.atomic(), which on SQLite isBEGIN IMMEDIATE, and on the default install the export errand runs inline, so the whole build holds the instance's write lock.core/export.py:638-650(the prefetch list),core/export.py:703(application.tags.all()),core/export.py:722(application.offers.all()),core/export.py:479-487_contact(contact.department,phone_numbers,postal_addresses,web_linksthrough:397-419),core/export.py:659(company.parent),core/export.py:624-631(the contacts at no company, with no prefetch),core/export.py:777(RenderedDocumentwithoutprefetch_related("copies"), read by_copiesat:916-933),core/export.py:958-975write_archive.core_phonenumber,core_postaladdress,core_weblinkandjobs_departmentonce per contact,core_tagandapplications_offeronce per application, anddocuments_documentcopyonce per sent document. The other reviewer measured a large account (800 companies, 1,500 applications, 266 contacts) at about 3,830 queries and 6 to 12 s, against 39 queries and 2.9 s with five prefetches added, with an identical manifest. Other requests to the instance wait for that time.postings__applications__tags,postings__applications__offers,contacts__phone_numbers,contacts__postal_addresses,contacts__web_linksand aPrefetch("contacts", queryset=Contact.objects.select_related("department"))to the companies query;select_related("parent")on it; the same channel prefetches andselect_related("department")on the company-less contacts; andprefetch_related("copies")on the rendered documents.Done when
tests/test_export.pybuilds the document for an account and for one with ten times as many companies, applications and contacts, and asserts the query counts are equal; it fails today.Landed on main with a green Forgejo CI run. Its entry in the CHANGELOG's Unreleased section ends in (#557).