From 10626e5abfba74093084bdbe56f33f1a6f6080a0 Mon Sep 17 00:00:00 2001 From: pranithreddym Date: Tue, 12 May 2026 09:00:01 -0500 Subject: [PATCH] Fix task_deindex_instance crash when object deleted before task runs When a document is deleted (e.g. emptied from Trash), Celery may not execute task_deindex_instance until after the DELETE has committed. The task called Model.objects.get(pk=object_id) without guarding for DoesNotExist, causing an unhandled exception and a CRITICAL traceback in the worker logs on every trash-empty operation. task_index_instance already handles this case with a retry; for de-indexing a non-existent object, a retry makes no sense since there is nothing to de-index. The fix catches DoesNotExist, logs a WARNING, and returns cleanly. Also adds a regression test: test_task_deindex_instance_object_already_deleted Fixes GitLab issue #1185. --- mayan/apps/dynamic_search/tasks.py | 10 ++++++- mayan/apps/dynamic_search/tests/test_tasks.py | 27 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/mayan/apps/dynamic_search/tasks.py b/mayan/apps/dynamic_search/tasks.py index 35c24ddf27e..6d43b6aa647 100644 --- a/mayan/apps/dynamic_search/tasks.py +++ b/mayan/apps/dynamic_search/tasks.py @@ -28,7 +28,15 @@ def task_deindex_instance(self, app_label, model_name, object_id): logger.info('Executing') Model = apps.get_model(app_label=app_label, model_name=model_name) - instance = Model._meta.default_manager.get(pk=object_id) + + try: + instance = Model._meta.default_manager.get(pk=object_id) + except Model.DoesNotExist: + logger.warning( + 'Object %s with pk=%s no longer exists; ' + 'skipping de-indexing.', Model, object_id + ) + return try: SearchBackend.get_instance().deindex_instance(instance=instance) diff --git a/mayan/apps/dynamic_search/tests/test_tasks.py b/mayan/apps/dynamic_search/tests/test_tasks.py index d5b13a14ca0..db4d649836a 100644 --- a/mayan/apps/dynamic_search/tests/test_tasks.py +++ b/mayan/apps/dynamic_search/tests/test_tasks.py @@ -3,6 +3,7 @@ from mayan.apps.testing.tests.base import BaseTestCase from ..classes import SearchBackend, SearchModel +from ..tasks import task_deindex_instance from .mixins import SearchTaskTestMixin, SearchTestMixin @@ -60,3 +61,29 @@ def test_task_reindex_backend(self): search_terms=self._test_objects[0].test_field ) self.assertTrue(self._test_objects[0] in queryset) + + def test_task_deindex_instance_object_already_deleted(self): + """ + task_deindex_instance must not crash when the object no longer exists. + + This is a race condition that occurs when a document is deleted (e.g. + from the trash) and the de-index task executes after the DELETE has + already committed. Before this fix the task raised DoesNotExist and + logged a CRITICAL traceback; now it logs a warning and returns cleanly. + Regression test for GitLab issue #1185. + """ + obj = self._test_objects[0] + app_label = obj._meta.app_label + model_name = obj._meta.model_name + pk = obj.pk + + obj.delete() + + # Must complete without raising any exception. + task_deindex_instance.apply_async( + kwargs={ + 'app_label': app_label, + 'model_name': model_name, + 'object_id': pk, + } + ).get()