[WEB-5398] fix: enhance bulk update handling for soft deletions and improve queryset management (#4722)
This commit is contained in:
@@ -47,9 +47,23 @@ class BulkOperationHooks:
|
||||
Custom update method to trigger a signal with
|
||||
all the updated objs on bulk update.
|
||||
"""
|
||||
# Check if this is a soft deletion (deleted_at is being set)
|
||||
is_soft_delete = "deleted_at" in kwargs and kwargs["deleted_at"] is not None
|
||||
|
||||
if is_soft_delete:
|
||||
# Capture PKs before update to handle soft deletion case
|
||||
# where self queryset will become empty after deleted_at is set
|
||||
deleted_pks = list(self.values_list("pk", flat=True))
|
||||
|
||||
rows = super().update(**kwargs)
|
||||
if rows:
|
||||
post_bulk_update.send(sender=self.__class__, model=self.model, objs=self)
|
||||
if is_soft_delete:
|
||||
# Use all_objects to get unfiltered queryset including soft-deleted records
|
||||
objs = self.model.all_objects.filter(pk__in=deleted_pks)
|
||||
else:
|
||||
# For regular updates, use the current queryset
|
||||
objs = self
|
||||
post_bulk_update.send(sender=self.__class__, model=self.model, objs=objs)
|
||||
return rows
|
||||
|
||||
@transaction.atomic
|
||||
|
||||
@@ -44,9 +44,7 @@ def update_index_on_bulk_create_update(sender, **kwargs):
|
||||
|
||||
# Queue all objects as a single bulk update - batch processor will drain all queued items
|
||||
obj_ids = [str(obj.id) for obj in objs_list]
|
||||
semantic_fields_changed = check_bulk_semantic_fields_changed(
|
||||
model_name, objs_list
|
||||
)
|
||||
semantic_fields_changed = check_bulk_semantic_fields_changed(model_name, objs_list)
|
||||
queue_bulk_updates_for_batch(
|
||||
model_name=model_name,
|
||||
obj_ids=obj_ids,
|
||||
@@ -84,9 +82,7 @@ class BatchedCelerySignalProcessor(CelerySignalProcessor):
|
||||
from django_opensearch_dsl.registries import registry
|
||||
|
||||
if instance.__class__ in registry._models:
|
||||
semantic_fields_changed = self._check_semantic_fields_changed(
|
||||
instance, **kwargs
|
||||
)
|
||||
semantic_fields_changed = self._check_semantic_fields_changed(instance, **kwargs)
|
||||
|
||||
# Queue update for batch processing - cascade to related documents handled during batch processing
|
||||
transaction.on_commit(
|
||||
@@ -122,9 +118,7 @@ class BatchedCelerySignalProcessor(CelerySignalProcessor):
|
||||
updated_fields = set(update_fields) if update_fields else set()
|
||||
semantic_fields_set = set(semantic_fields)
|
||||
if semantic_fields_set.intersection(updated_fields):
|
||||
logger.info(
|
||||
f"Semantic fields in update_fields for {model_name} {instance.pk}, semantic fields changed"
|
||||
)
|
||||
logger.info(f"Semantic fields in update_fields for {model_name} {instance.pk}, semantic fields changed")
|
||||
return True
|
||||
else:
|
||||
# Check if semantic fields have actually changed by comparing with original values
|
||||
@@ -134,9 +128,7 @@ class BatchedCelerySignalProcessor(CelerySignalProcessor):
|
||||
original_value = getattr(instance, original_attr)
|
||||
current_value = getattr(instance, field, None)
|
||||
if original_value != current_value:
|
||||
logger.info(
|
||||
f"Semantic field '{field}' changed for {model_name} {instance.pk}"
|
||||
)
|
||||
logger.info(f"Semantic field '{field}' changed for {model_name} {instance.pk}")
|
||||
return True
|
||||
|
||||
return False
|
||||
@@ -149,9 +141,7 @@ class BatchedCelerySignalProcessor(CelerySignalProcessor):
|
||||
|
||||
# Filter: Only process search-relevant models
|
||||
if not is_model_search_relevant(model_name):
|
||||
logger.debug(
|
||||
f"Skipping non-search-relevant model for deletion: {model_name}"
|
||||
)
|
||||
logger.debug(f"Skipping non-search-relevant model for deletion: {model_name}")
|
||||
return
|
||||
|
||||
if self.instance_requires_update(instance):
|
||||
|
||||
@@ -128,11 +128,11 @@ class IssueDocument(BaseDocument):
|
||||
|
||||
def get_instances_from_related(self, related_instance):
|
||||
if isinstance(related_instance, Project):
|
||||
qs = related_instance.project_issue(manager="objects").all()
|
||||
qs = related_instance.project_issue(manager="all_objects").all()
|
||||
elif isinstance(related_instance, ProjectMember):
|
||||
qs = related_instance.project.project_issue(manager="objects").all()
|
||||
qs = related_instance.project.project_issue(manager="all_objects").all()
|
||||
else:
|
||||
qs = self.django.model.objects.none()
|
||||
qs = self.django.model.all_objects.none()
|
||||
return self.apply_related_to_queryset(qs)
|
||||
|
||||
def prepare_project_is_archived(self, instance):
|
||||
|
||||
Reference in New Issue
Block a user