Skip to content

Commit dcec087

Browse files
committed
[change] Invalidate checksum cache on save operation
1 parent 088a981 commit dcec087

File tree

4 files changed

+39
-30
lines changed

4 files changed

+39
-30
lines changed

openwisp_controller/config/apps.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -285,14 +285,6 @@ def enable_cache_invalidation(self):
285285
DeviceChecksumView.invalidate_get_device_cache_on_config_deactivated,
286286
dispatch_uid="config_deactivated_invalidate_get_device_cache",
287287
)
288-
config_deactivating.connect(
289-
DeviceChecksumView.invalidate_checksum_cache,
290-
dispatch_uid="config_deactivated_invalidate_get_device_cache",
291-
)
292-
config_modified.connect(
293-
DeviceChecksumView.invalidate_checksum_cache,
294-
dispatch_uid="invalidate_checksum_cache",
295-
)
296288
# VPN cache invalidation
297289
post_save.connect(
298290
GetVpnView.invalidate_get_vpn_cache,

openwisp_controller/config/base/config.py

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ def bulk_invalidate_get_cached_checksum(cls, query_params):
183183
for instance in cls.objects.only("id").filter(**query_params).iterator():
184184
has_changed = instance.update_status_if_checksum_changed()
185185
if has_changed:
186-
instance.get_cached_checksum.invalidate(instance)
186+
instance.invalidate_checksum_cache()
187187

188188
@classmethod
189189
def get_template_model(cls):
@@ -573,10 +573,10 @@ def clean(self):
573573
def save(self, *args, **kwargs):
574574
created = self._state.adding
575575
# check if config has been modified (so we can emit signals)
576-
if not created:
576+
if created:
577+
self.checksum_db = self.checksum
578+
else:
577579
self._check_changes()
578-
self._invalidate_backend_instance_cache()
579-
self.checksum_db = self.checksum
580580
self._just_created = created
581581
result = super().save(*args, **kwargs)
582582
# add default templates if config has just been created
@@ -620,17 +620,12 @@ def _check_changes(self):
620620
if self.backend != current.backend:
621621
# storing old backend to send backend change signal after save
622622
self._old_backend = current.backend
623-
self._invalidate_backend_instance_cache()
624-
if self.checksum != current.checksum:
625-
if self.status != "modified":
626-
self.set_status_modified(save=False)
627-
else:
628-
# config modified signal is always sent
629-
# regardless of the current status
630-
self._send_config_modified_after_save = True
623+
self.update_status_if_checksum_changed(
624+
save=False,
625+
)
631626

632627
def update_status_if_checksum_changed(
633-
self, save=True, send_config_modified_signal=True
628+
self, save=True, update_checksum_db=True, send_config_modified_signal=True
634629
):
635630
"""
636631
Updates the instance status if its checksum has changed.
@@ -649,7 +644,11 @@ def update_status_if_checksum_changed(
649644
extra_update_fields=["checksum_db"],
650645
)
651646
else:
652-
self._update_checksum_db(new_checksum=self.checksum_db)
647+
if update_checksum_db:
648+
self._update_checksum_db(new_checksum=self.checksum_db)
649+
if send_config_modified_signal:
650+
self._send_config_modified_after_save = True
651+
self.invalidate_checksum_cache()
653652
return checksum_changed
654653

655654
def _has_configuration_checksum_changed(self):
@@ -758,7 +757,7 @@ def set_status_modified(
758757
):
759758
if send_config_modified_signal:
760759
self._send_config_modified_after_save = True
761-
self._set_status("modified", save, extra_update_fields)
760+
self._set_status("modified", save, extra_update_fields=extra_update_fields)
762761

763762
def set_status_applied(self, save=True):
764763
self._set_status("applied", save)
@@ -790,12 +789,14 @@ def deactivate(self):
790789
# otherwise, the "enforce_required_templates" and "add_default_templates"
791790
# methods would re-add required/default templates.
792791
# The "templates_changed" receiver skips post_clear action. Thus,
793-
# we need to update the checksum_db field manually.
792+
# we need to update the checksum_db field manually and invalidate
793+
# the cache.
794794
self.config = {}
795795
self.set_status_deactivating(save=False)
796796
self.templates.clear()
797797
self._invalidate_backend_instance_cache()
798798
self.checksum_db = self.checksum
799+
self.invalidate_checksum_cache()
799800
self.save()
800801
if old_checksum == self.checksum_db:
801802
# Accelerate deactivation if the configuration remains

openwisp_controller/config/tests/test_config.py

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ def test_get_cached_checksum(self):
250250
del c.backend_instance
251251
self.assertNotEqual(c.checksum, old_checksum)
252252
self.assertEqual(c.get_cached_checksum(), c.checksum)
253-
mocked_debug.assert_not_called()
253+
mocked_debug.assert_called_once()
254254

255255
with self.subTest("test cache invalidation when config templates are changed"):
256256
with patch.object(base_config_logger, "debug") as mocked_debug:
@@ -260,7 +260,16 @@ def test_get_cached_checksum(self):
260260
del c.backend_instance
261261
self.assertNotEqual(c.checksum, old_checksum)
262262
self.assertEqual(c.get_cached_checksum(), c.checksum)
263-
mocked_debug.assert_not_called()
263+
mocked_debug.assert_called_once()
264+
265+
with self.subTest('cache invalidation works when config is deactivated'):
266+
with patch.object(base_config_logger, "debug") as mocked_debug:
267+
old_checksum = c.checksum
268+
c.deactivate()
269+
del c.backend_instance
270+
self.assertNotEqual(c.checksum, old_checksum)
271+
self.assertEqual(c.get_cached_checksum(), c.checksum)
272+
mocked_debug.assert_called_once()
264273

265274
def test_backend_import_error(self):
266275
"""
@@ -828,8 +837,15 @@ def test_config_modified_sent(self):
828837

829838
def test_check_changes_query(self):
830839
config = self._create_config(organization=self._get_org())
831-
with self.assertNumQueries(10):
832-
config._check_changes()
840+
with self.subTest('No changes made to the config object'):
841+
with self.assertNumQueries(3):
842+
config._check_changes()
843+
844+
with self.subTest('Changes made to the config object'):
845+
config.templates.add(self._create_template())
846+
config.config = {"general": {"description": "test"}}
847+
with self.assertNumQueries(4):
848+
config._check_changes()
833849

834850
def test_config_get_system_context(self):
835851
config = self._create_config(
@@ -962,7 +978,7 @@ def test_certificate_renew_invalidates_checksum_cache(self):
962978
vpnclient_cert.renew()
963979
# An additional call from cache invalidation of
964980
# DeviceGroupCommonName View
965-
self.assertEqual(mocked_delete.call_count, 2)
981+
self.assertEqual(mocked_delete.call_count, 3)
966982
del config.backend_instance
967983
self.assertNotEqual(config.get_cached_checksum(), old_checksum)
968984
config.refresh_from_db()

openwisp_controller/config/tests/test_controller.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ def test_get_cached_checksum(self):
240240
del d.config.backend_instance
241241
self.assertNotEqual(d.config.checksum, old_checksum)
242242
self.assertEqual(d.config.get_cached_checksum(), d.config.checksum)
243-
mocked_debug.assert_not_called()
243+
mocked_debug.assert_called_once()
244244

245245
def test_device_checksum_requested_signal_is_emitted(self):
246246
d = self._create_device_config()

0 commit comments

Comments
 (0)