Fixes #22812: Defer large Job payload fields during batched deletion
The batched job delete can't fast-delete (a global pre_delete receiver forces
per-instance signals), so each batch still instantiates its Job rows. Load only the PK
via only('pk') so those instances don't pull the large data/log_entries payloads,
cutting the resident set per batch. Also drop a dead `no-toggle` CSS class from the
delete-confirmation template (it is defined nowhere and, under Tabler, has no effect)
and use JobStatusChoices.STATUS_COMPLETED in the tests instead of a string literal.
This commit is contained in:
parent
be69c55a99
commit
7d46c995f7
|
|
@ -7,7 +7,7 @@ from django.db.models import QuerySet
|
|||
from django.test import TestCase, override_settings
|
||||
from django.urls import reverse
|
||||
|
||||
from core.choices import ManagedFileRootPathChoices
|
||||
from core.choices import JobStatusChoices, ManagedFileRootPathChoices
|
||||
from core.models import DataSource, Job
|
||||
from extras.models import Script, ScriptModule
|
||||
from extras.validators import CustomValidator
|
||||
|
|
@ -43,7 +43,7 @@ class ScriptDeletionTestCase(TestCase):
|
|||
object_type=object_type,
|
||||
object_id=obj.pk,
|
||||
name='testjob',
|
||||
status='completed',
|
||||
status=JobStatusChoices.STATUS_COMPLETED,
|
||||
job_id=uuid.uuid4(),
|
||||
data={'output': 'x' * 50},
|
||||
)
|
||||
|
|
@ -164,7 +164,7 @@ class ConfirmCollectorTestCase(TestCase):
|
|||
script = Script.objects.create(module=module, name=f'S{uuid.uuid4().hex[:8]}')
|
||||
ct = ContentType.objects.get_for_model(Script, for_concrete_model=False)
|
||||
Job.objects.bulk_create([
|
||||
Job(object_type=ct, object_id=script.pk, name='j', status='completed',
|
||||
Job(object_type=ct, object_id=script.pk, name='j', status=JobStatusChoices.STATUS_COMPLETED,
|
||||
job_id=uuid.uuid4(), data={'output': 'x' * 50})
|
||||
for _ in range(count)
|
||||
])
|
||||
|
|
@ -226,7 +226,10 @@ class ObjectDeleteViewCountsTestCase(ViewTestCase):
|
|||
script = Script.objects.create(module=module, name=f'S{uuid.uuid4().hex[:8]}')
|
||||
ct = ContentType.objects.get_for_model(Script, for_concrete_model=False)
|
||||
Job.objects.bulk_create([
|
||||
Job(object_type=ct, object_id=script.pk, name='j', status='completed', job_id=uuid.uuid4())
|
||||
Job(
|
||||
object_type=ct, object_id=script.pk, name='j',
|
||||
status=JobStatusChoices.STATUS_COMPLETED, job_id=uuid.uuid4(),
|
||||
)
|
||||
for _ in range(50)
|
||||
])
|
||||
|
||||
|
|
@ -249,7 +252,10 @@ class ObjectDeleteViewCountsTestCase(ViewTestCase):
|
|||
script = Script.objects.create(module=module, name=f'S{uuid.uuid4().hex[:8]}')
|
||||
ct = ContentType.objects.get_for_model(Script, for_concrete_model=False)
|
||||
Job.objects.bulk_create([
|
||||
Job(object_type=ct, object_id=script.pk, name='j', status='completed', job_id=uuid.uuid4())
|
||||
Job(
|
||||
object_type=ct, object_id=script.pk, name='j',
|
||||
status=JobStatusChoices.STATUS_COMPLETED, job_id=uuid.uuid4(),
|
||||
)
|
||||
for _ in range(50)
|
||||
])
|
||||
|
||||
|
|
|
|||
|
|
@ -464,7 +464,10 @@ def batch_delete_jobs(job_queryset):
|
|||
# Re-slice the queryset each iteration: it re-queries after each batch delete, so the
|
||||
# remaining set shrinks and the loop terminates (do not hoist this into a cursor).
|
||||
while pks := list(job_pks[:JOB_DELETE_BATCH_SIZE]):
|
||||
Job.objects.filter(pk__in=pks).delete()
|
||||
# only('pk'): the batch still can't fast-delete (a global pre_delete receiver forces
|
||||
# per-instance signals), so each Job in the batch is instantiated. Loading just the PK
|
||||
# avoids pulling the large data/log_entries payloads into those instances.
|
||||
Job.objects.filter(pk__in=pks).only('pk').delete()
|
||||
|
||||
|
||||
class JobsMixin(models.Model):
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
{# High-cardinality relations (e.g. jobs) are summarized by count and are not #}
|
||||
{# expandable, since their instances are intentionally not loaded (see #22812). #}
|
||||
{% if instances.count_only %}
|
||||
<div class="accordion-button collapsed no-toggle" style="cursor: default;">
|
||||
<div class="accordion-button collapsed" style="cursor: default;">
|
||||
{{ object_count }}
|
||||
{% if object_count == 1 %}{{ model|meta:"verbose_name" }}{% else %}{{ model|meta:"verbose_name_plural" }}{% endif %}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue