Использование аннулирования кэша для пользовательского разрешения django

В настоящее время я работаю над кэшем для пользовательских разрешений в Django. Структура для предоставления пользователям/организациям доступа к определенным областям приложения выглядит следующим образом: enter image description here

Имеется в виду, что пользователь может иметь доступ к функции либо через свою организацию, либо как сам пользователь. Мне нужен кэш с ключами-значениями, который хранит все функции, к которым пользователь/организация имеет доступ в виде строки. Таким образом, когда пользователь запрашивает доступ к определенному представлению, класс разрешения сначала извлекает все функции для этого пользователя из кэша. Я реализовал это следующим образом:

class UserPermissionCache:
    def __init__(self):
        self.redis = StrictRedis(
            host=settings.REDIS_RATE_LIMITING_URL,
            port=settings.REDIS_RATE_LIMITING_PORT,
            db=settings.REDIS_RATE_LIMITING_DB,
        )
        self.validation = datetime.now().strftime("%m%d%Y%H%M%S")

    def status_key(self, member):
        return f"user:features:{self.validation}:{member.uuid}"

    def set_user_features(self, user, key):

        features = Feature.objects.filter(
            Q(enabled_for_all=True)
            | Q(enabled_for_users=user)
            | Q(enabled_for_organizations=user.only_organization)
        )

        result = FEATURE_STRING_SEPERATOR.join(
            feature.code for feature in features
        )

        if not self.redis.set(key, result, settings.USER_FEATURES_TIMEOUT):
            logging.warning(f"Couldn't set features for user: {user.uuid}")

        return result

    def get_user_features(self, member):

        key = self.status_key(member)

        try:
            result = self.redis.get(key)
        except ConnectionError:
            logger.error(
                "ConnectionError, Failed to fetch feature permission for user",
                extra={"member": member.uuid},
            )
            return None

        if result is None:
            result = self.set_user_features(member, key)
            result = result.split(FEATURE_STRING_SEPERATOR)
        else:
            result = result.decode("utf-8").split(FEATURE_STRING_SEPERATOR)

        return result

    def reset_user_features(self, sender, **kwargs):
        for member in organization_members:
            key = self.status_key(member)
            self.redis.delete(key)

    def update_validation_key(self, sender, instance, **kwargs):
        self.validation = datetime.now().strftime("%m%d%Y%H%M%S")


user_permission_cache = UserPermissionCache()

m2m_changed.connect(user_permission_cache.reset_user_features, sender=Feature.enabled_for_organizations.through)
post_save.connect(user_permission_cache.update_validation_key, sender=Feature)

Моя проблема заключается в проверке кэша. Я установил таймаут для записи в кэше на 15 минут. Всякий раз, когда я хочу добавить функции организациям или изменить функцию как администратор, я хочу, чтобы кэш также обновлялся, чтобы каждый пользователь получал немедленный доступ. Я попытался решить эту проблему, добавив время к ключу. Всякий раз, когда функция обновляется, я изменяю и ключ, что означает, что кэш больше не может найти старую пару ключ-значение и просто создает новую запись с обновленной функцией. Я просто не знаю, что делать, когда представление вызывается для добавления характеристик в организацию. Для этого я использую сигнал m2m_changed Signal. Я надеялся, что есть лучшее решение, чем это.

Вернуться на верх