Files
fastapi-best-architecture/backend/app/admin/utils/cache.py
T
Wu Clan 2b56168ad0 Refactor foreign keys and relationships to pure logic (#901)
* Refactor foreign keys and relationships to pure logic

* Revert of some changes

* More revert

* Update the user paginate

* Update user create and update

* Update dept select and delete

* Rename the join query functions

* Update select_join_serialize doc and README

* Fix typo in README

* Update the user delete

* Update the user social

* Update the dict plugin crud

* Update the dict plugin version

* Bump dependencies and pre-commits

* Update the code generator plugin crud

* Update the menu crud

* Update the role crud

* Update the data scope and rule crud

* Restore get_paginated to get_select

* Update the code generator plugin version

* Add the py version in pre-commit

* Remove the plugin include parameter config

* Add more cache cleaning TODO

* Rename get_with_relation to get_join

* Add the user cache clear

* Fix known compatibility issues

* Update the version number to 1.11.0

* Fix lint

* Optimize select_join_serialize logic

* Delete cache cleanup comments

* Update the oauth2 plugin version

* Fix user-role table cleanup when user update
2025-11-12 13:06:26 +08:00

99 lines
3.1 KiB
Python

from collections.abc import Sequence
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from backend.app.admin.model.m2m import data_scope_rule, role_data_scope, role_menu, user_role
from backend.core.conf import settings
from backend.database.redis import redis_client
class UserCacheManager:
"""用户缓存管理"""
@staticmethod
async def clear(user_ids: Sequence[int]) -> None:
"""
清理用户缓存
:param user_ids: 用户 ID 列表
:return:
"""
if user_ids:
await redis_client.delete(*[f'{settings.JWT_USER_REDIS_PREFIX}:{user_id}' for user_id in user_ids])
async def clear_by_role_id(self, db: AsyncSession, role_ids: list[int]) -> None:
"""
通过角色 ID 清理用户缓存
:param db: 数据库会话
:param role_ids: 角色 ID 列表
:return:
"""
stmt = select(user_role.c.user_id).where(user_role.c.role_id.in_(role_ids)).distinct()
result = await db.execute(stmt)
user_ids = result.scalars().all()
await self.clear(user_ids)
async def clear_by_menu_id(self, db: AsyncSession, menu_ids: list[int]) -> None:
"""
通过菜单 ID 清理用户缓存
:param db: 数据库会话
:param menu_ids: 菜单 ID 列表
:return:
"""
stmt = (
select(user_role.c.user_id)
.join(role_menu, user_role.c.role_id == role_menu.c.role_id)
.where(role_menu.c.menu_id.in_(menu_ids))
.distinct()
)
result = await db.execute(stmt)
user_ids = result.scalars().all()
await self.clear(user_ids)
async def clear_by_data_scope_id(self, db: AsyncSession, scope_ids: list[int]) -> None:
"""
通过数据范围 ID 清理用户缓存
:param db: 数据库会话
:param scope_ids: 数据范围 ID 列表
:return:
"""
stmt = (
select(user_role.c.user_id)
.join(role_data_scope, user_role.c.role_id == role_data_scope.c.role_id)
.where(role_data_scope.c.data_scope_id.in_(scope_ids))
.distinct()
)
result = await db.execute(stmt)
user_ids = result.scalars().all()
await self.clear(user_ids)
async def clear_by_data_rule_id(self, db: AsyncSession, rule_ids: list[int]) -> None:
"""
通过数据规则 ID 清理用户缓存
:param db: 数据库会话
:param rule_ids: 数据规则 ID 列表
:return:
"""
stmt = (
select(user_role.c.user_id)
.join(role_data_scope, user_role.c.role_id == role_data_scope.c.role_id)
.join(data_scope_rule, role_data_scope.c.data_scope_id == data_scope_rule.c.data_scope_id)
.where(data_scope_rule.c.data_rule_id.in_(rule_ids))
.distinct()
)
result = await db.execute(stmt)
user_ids = result.scalars().all()
await self.clear(user_ids)
user_cache_manager: UserCacheManager = UserCacheManager()