Skip to content

Commit a6a2c65

Browse files
committed
[fix] Ensure VpnClient post_delete signal fires on template removal openwisp#1221
Replaced QuerySet.delete() with per-instance .delete() calls so that post_delete signals fire correctly for each VpnClient. Wrapped both deletion loops in transaction.atomic() to ensure atomicity and prevent partial deletions on failure, consistent with the pattern already used in serializers.py. Used .iterator() for memory-safe iteration over potentially large querysets. Signed-off-by: prakash-kalwaniya <kalwaniyaprakash1@gmail.com>
1 parent d203490 commit a6a2c65

File tree

2 files changed

+12
-5
lines changed

2 files changed

+12
-5
lines changed

openwisp_controller/config/api/serializers.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,10 @@ def _update_config(self, device, config_data):
202202
with transaction.atomic():
203203
vpn_list = config.templates.filter(type="vpn").values_list("vpn")
204204
if vpn_list:
205-
config.vpnclient_set.exclude(vpn__in=vpn_list).delete()
205+
for vpnclient in config.vpnclient_set.exclude(
206+
vpn__in=vpn_list
207+
).iterator():
208+
vpnclient.delete()
206209
config.templates.set(config_templates, clear=True)
207210
config.save()
208211
except ValidationError as error:

openwisp_controller/config/base/config.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,9 @@ def manage_vpn_clients(cls, action, instance, pk_set, **kwargs):
338338
if instance.is_deactivating_or_deactivated():
339339
# If the device is deactivated or in the process of deactivating, then
340340
# delete all vpn clients and return.
341-
instance.vpnclient_set.all().delete()
341+
with transaction.atomic():
342+
for vpnclient in instance.vpnclient_set.all().iterator():
343+
vpnclient.delete()
342344
return
343345

344346
vpn_client_model = cls.vpn.through
@@ -370,9 +372,11 @@ def manage_vpn_clients(cls, action, instance, pk_set, **kwargs):
370372
# signal is triggered again—after all templates, including the required
371373
# ones, have been fully added. At that point, we can identify and
372374
# delete VpnClient objects not linked to the final template set.
373-
instance.vpnclient_set.exclude(
374-
template_id__in=instance.templates.values_list("id", flat=True)
375-
).delete()
375+
with transaction.atomic():
376+
for vpnclient in instance.vpnclient_set.exclude(
377+
template_id__in=instance.templates.values_list("id", flat=True)
378+
).iterator():
379+
vpnclient.delete()
376380

377381
if action == "post_add":
378382
for template in templates.filter(type="vpn"):

0 commit comments

Comments
 (0)