Skip to content

Commit

Permalink
Merge branch 'use_raw_delete_func' into keyring_in_database
Browse files Browse the repository at this point in the history
  • Loading branch information
aweakley committed Feb 14, 2024
2 parents 6d80c84 + 2d73b0a commit 2429a14
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 2 deletions.
20 changes: 20 additions & 0 deletions docs/getting_started/django_settings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,23 @@ own unique page in the cache, set this value to ``None`` or ``[]``.
If you feel as though the spammers have won, and want the nuclear option, you
can set this to ``[r".*"]`` which will ignore all querystrings. This is surely
a terrible idea, but it can be done.


.. _WAGTAIL_CACHE_USE_RAW_DELETE:

WAGTAIL_CACHE_USE_RAW_DELETE
----------------------------

.. versionadded:: 2.3.0

This setting will use Django's ``QuerySet._raw_delete`` method to clear
KeyringItems from the database. This is fast but means that signals are not
sent during that process. This is OFF by default.

If your cache is large, then there can be many ``KeyringItem`` objects in the
database. When you publish a Wagtail page that is high in the tree, many
of those items may be deleted.

If the delete process is too slow, then you can change this setting to use
Django's ``QuerySet._raw_delete`` method. That runs significantly faster than
``QuerySet.delete`` but it means that signals are not sent during that process.
29 changes: 29 additions & 0 deletions testproject/home/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,35 @@ def test_bulk_delete(self):
self.assertTrue(KeyringItem.objects.filter(key=key).exists())
self.assertTrue(self.cache.get(key))

@override_settings(WAGTAIL_CACHE_USE_RAW_DELETE=True)
def test_bulk_delete_raw_delete(self):
"""
You can optionally use Django's `_raw_delete`
for speed with many cache keys.
"""
timeout = 10
expiry = now() + datetime.timedelta(seconds=timeout)
keys = [f"key-{counter}" for counter in range(8)]

for key in keys:
url = "https://example.com/"
KeyringItem.objects.set(
expiry=expiry,
key=key,
url=url,
)
self.cache.set(key, url, timeout)

KeyringItem.objects.bulk_delete_cache_keys(keys[:4])

for key in keys[:4]:
self.assertFalse(KeyringItem.objects.filter(key=key).exists())
self.assertFalse(self.cache.get(key))

for key in keys[4:]:
self.assertTrue(KeyringItem.objects.filter(key=key).exists())
self.assertTrue(self.cache.get(key))

def test_active_for_url_regexes(self):
past_expiry = now() - datetime.timedelta(seconds=1)
future_expiry = now() + datetime.timedelta(seconds=1)
Expand Down
8 changes: 6 additions & 2 deletions wagtailcache/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,12 @@ def bulk_delete_cache_keys(self, keys: List[str]) -> None:
wagtailcache_settings.WAGTAIL_CACHE_BATCH_SIZE,
):
self._wagcache.delete_many(key_batch)
# Delete from database
existing_keys.delete()
# Delete from database, optionally use `_raw_delete`
# for speed with many cache keys.
if wagtailcache_settings.WAGTAIL_CACHE_USE_RAW_DELETE:
existing_keys._raw_delete(using=self.db)
else:
existing_keys.delete()

def clear_expired(self) -> None:
"""
Expand Down
1 change: 1 addition & 0 deletions wagtailcache/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class _DefaultSettings:
r"^trk_.*$", # Listrak
r"^utm_.*$", # Google Analytics
]
WAGTAIL_CACHE_USE_RAW_DELETE = False

def __getattribute__(self, attr: Text):
# First load from Django settings.
Expand Down

0 comments on commit 2429a14

Please sign in to comment.