Prevent memory exhaustion when purging a large number of revisions

Optimise determining whether a revision is the latest

This no longer attempts to load the entire revision into memory to compare. Instead, we just check if any revisions created after this one exist (that aren't this one).
pull/9868/head
Jake Howard 2023-01-12 11:47:17 +00:00 zatwierdzone przez LB (Ben Johnston)
rodzic 529d2feb49
commit c8c1870c97
4 zmienionych plików z 9 dodań i 6 usunięć

Wyświetl plik

@ -70,6 +70,7 @@ Changelog
* Fix: Prevent obstructing the outline around rich text fields (Thibaud Colas)
* Fix: Page editor dropdowns now use indigo backgrounds like elsewhere in the admin interface (Thibaud Colas)
* Fix: Allow parsing of multiple key/value pairs from string in `wagtail.search.utils.parse_query_string` (Beniamin Bucur)
* Fix: Prevent memory exhaustion when purging a large number of revisions (Jake Howard)
* Docs: Add custom permissions section to permissions documentation page (Dan Hayden)
* Docs: Add documentation for how to get started with contributing translations for the Wagtail admin (Ogunbanjo Oluwadamilare)
* Docs: Officially recommend `fnm` over `nvm` in development documentation (LB (Ben) Johnston)

Wyświetl plik

@ -107,6 +107,7 @@ This feature was developed by Matt Westcott, and sponsored by [YouGov](https://y
* Prevent obstructing the outline around rich text fields (Thibaud Colas)
* Page editor dropdowns now use indigo backgrounds like elsewhere in the admin interface (Thibaud Colas)
* Allow parsing of multiple key/value pairs from string in `wagtail.search.utils.parse_query_string` (Beniamin Bucur)
* Prevent memory exhaustion when purging a large number of revisions (Jake Howard)
### Documentation

Wyświetl plik

@ -60,7 +60,7 @@ def purge_revisions(days=None):
deleted_revisions_count = 0
for revision in purgeable_revisions:
for revision in purgeable_revisions.iterator():
# don't delete the latest revision for any page
if not revision.is_latest_revision():
revision.delete()

Wyświetl plik

@ -2835,15 +2835,16 @@ class Revision(models.Model):
# special case: a revision without an ID is presumed to be newly-created and is thus
# newer than any revision that might exist in the database
return True
latest_revision = (
Revision.objects.filter(
return (
not Revision.objects.filter(
base_content_type_id=self.base_content_type_id,
object_id=self.object_id,
created_at__gte=self.created_at,
)
.order_by("-created_at", "-id")
.first()
.exclude(id=self.id)
.exists()
)
return latest_revision == self
def delete(self):
# Update revision_created fields for comments that reference the current revision, if applicable.