Выполнение обратного вызова при превышении таймаута django.cache.set
Я использую Django cache с django-redis==5.0.0 следующим образом:
cache.set(f'clean_me_up_{id}', timeout=10)
Сохранение записи в кэше, которая будет очищена после таймаута, отлично работает для меня.
Что я пытаюсь достичь, так это выполнить некоторый код очистки (в качестве обратного вызова?), когда кэш удаляется.
Есть ли какой-нибудь простой способ сделать это, так как это было бы очень полезно.
Кэш не контролируется Django: Django просит Redis вставить ключ с указанным таймаутом. Таким образом, Redis управляет ключами и принимает решение об их удалении. Django также не знает, когда Redis это делает, поэтому вы не можете подключить к нему обратный вызов. Большинство из этих хранилищ ключевых значений также не проактивно удаляют ключи: они не ждут определенного времени, чтобы затем удалить ключ: по сути, когда они читают ключ, они проверяют, не истек ли таймаут, и если да, то удаляют его. Или когда им нужно выделить больше места, они сначала смотрят, могут ли они удалить ключи, срок действия которых истек, чтобы уменьшить пространство и таким образом предотвратить выделение большего пространства. Создается впечатление, что redis удаляет ключи в определенное время, но он не устанавливает для этого таймер.
Если вам это нужно, то, вероятно, следует составить таблицу элементов для очистки, то есть, по сути, сделать модель Trigger
, которая затем создается, и периодически проверяет, какие триггеры должны выполняться, и удаляет их из базы данных. Действительно, вы можете работать с моделью:
from datetime import timedelta
from django.utils.timezone import now
class Trigger(models.Model):
value = models.IntegerField()
when = models.DateTimeField()
@classmethod
def add_trigger(cls, value, timeout):
Trigger.objects.create(
value=value, when=now() + timedelta(seconds=timeout)
)
@classmethod
def check_triggers(cls, handler):
items = Trigger.objects.filter(when__lte=now())
Trigger.objects.filter(pk__in=[item.pk for item in items])
for item in items:
handler(item.value)
Таким образом, вы можете установить триггер с помощью:
Trigger.add_trigger(my_id, 10)
и затем периодически проверять, не истек ли срок годности предметов, и запускать обработчик с:
def my_handler(item):
print(item)
Trigger.check_triggers(my_handler)
и, например, запланировать это в cronjob.