545 lines
20 KiB
Python
545 lines
20 KiB
Python
|
|
from fastapi import APIRouter, Depends
|
|||
|
|
from fastapi.responses import JSONResponse
|
|||
|
|
from sqlalchemy import select, update
|
|||
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|||
|
|
|
|||
|
|
from loveace.database.auth.user import ACEUser
|
|||
|
|
from loveace.database.creator import get_db_session
|
|||
|
|
from loveace.database.isim.room import RoomBind
|
|||
|
|
from loveace.router.dependencies.auth import get_user_by_token
|
|||
|
|
from loveace.router.endpoint.isim.model.protect_router import ISIMRouterErrorToCode
|
|||
|
|
from loveace.router.endpoint.isim.model.room import (
|
|||
|
|
BindRoomRequest,
|
|||
|
|
BindRoomResponse,
|
|||
|
|
BuildingInfo,
|
|||
|
|
BuildingListResponse,
|
|||
|
|
CacheRoomsData,
|
|||
|
|
CurrentRoomResponse,
|
|||
|
|
FloorRoomsResponse,
|
|||
|
|
ForceRefreshResponse,
|
|||
|
|
RoomDetailResponse,
|
|||
|
|
)
|
|||
|
|
from loveace.router.endpoint.isim.utils.isim import ISIMClient, get_isim_client
|
|||
|
|
from loveace.router.endpoint.isim.utils.lock_manager import get_refresh_lock_manager
|
|||
|
|
from loveace.router.schemas.uniresponse import UniResponseModel
|
|||
|
|
|
|||
|
|
isim_room_router = APIRouter(
|
|||
|
|
prefix="/room",
|
|||
|
|
responses=ISIMRouterErrorToCode.gen_code_table(),
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
|
|||
|
|
@isim_room_router.get(
|
|||
|
|
"/list",
|
|||
|
|
summary="[完整数据] 获取所有楼栋、楼层、房间的完整树形结构",
|
|||
|
|
response_model=UniResponseModel[CacheRoomsData],
|
|||
|
|
)
|
|||
|
|
async def get_rooms(
|
|||
|
|
isim_conn: ISIMClient = Depends(get_isim_client),
|
|||
|
|
) -> UniResponseModel[CacheRoomsData] | JSONResponse:
|
|||
|
|
"""
|
|||
|
|
获取完整的寝室列表(所有楼栋、楼层、房间的树形结构)
|
|||
|
|
|
|||
|
|
⚠️ 数据量大:包含所有楼栋的完整数据,适合需要完整数据的场景
|
|||
|
|
💡 建议:移动端或需要部分数据的场景,请使用其他精细化查询接口
|
|||
|
|
"""
|
|||
|
|
try:
|
|||
|
|
rooms = await isim_conn.get_cached_rooms()
|
|||
|
|
if not rooms:
|
|||
|
|
return ISIMRouterErrorToCode().null_response.to_json_response(
|
|||
|
|
isim_conn.client.logger.trace_id
|
|||
|
|
)
|
|||
|
|
return UniResponseModel[CacheRoomsData](
|
|||
|
|
success=True,
|
|||
|
|
data=rooms,
|
|||
|
|
message="获取寝室列表成功",
|
|||
|
|
error=None,
|
|||
|
|
)
|
|||
|
|
except Exception as e:
|
|||
|
|
isim_conn.client.logger.error(f"获取寝室列表异常: {str(e)}")
|
|||
|
|
return ISIMRouterErrorToCode().server_error.to_json_response(
|
|||
|
|
isim_conn.client.logger.trace_id
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
|
|||
|
|
@isim_room_router.get(
|
|||
|
|
"/list/buildings",
|
|||
|
|
summary="[轻量级] 获取所有楼栋列表(仅楼栋信息,不含楼层和房间)",
|
|||
|
|
response_model=UniResponseModel[BuildingListResponse],
|
|||
|
|
)
|
|||
|
|
async def get_all_buildings(
|
|||
|
|
isim_conn: ISIMClient = Depends(get_isim_client),
|
|||
|
|
) -> UniResponseModel[BuildingListResponse] | JSONResponse:
|
|||
|
|
"""
|
|||
|
|
获取所有楼栋列表(仅楼栋的代码和名称)
|
|||
|
|
|
|||
|
|
✅ 数据量小:只返回楼栋列表,不包含楼层和房间
|
|||
|
|
💡 使用场景:
|
|||
|
|
- 楼栋选择器
|
|||
|
|
- 第一级导航菜单
|
|||
|
|
- 需要快速获取楼栋列表的场景
|
|||
|
|
"""
|
|||
|
|
logger = isim_conn.client.logger
|
|||
|
|
try:
|
|||
|
|
# 从Hash缓存获取完整数据
|
|||
|
|
full_data = await isim_conn.get_cached_rooms()
|
|||
|
|
|
|||
|
|
if not full_data or not full_data.data:
|
|||
|
|
logger.warning("楼栋数据不存在")
|
|||
|
|
return ISIMRouterErrorToCode().null_response.to_json_response(
|
|||
|
|
logger.trace_id
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 提取楼栋信息
|
|||
|
|
buildings = [
|
|||
|
|
{"code": building.code, "name": building.name}
|
|||
|
|
for building in full_data.data
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
result = BuildingListResponse(
|
|||
|
|
buildings=[BuildingInfo(**b) for b in buildings],
|
|||
|
|
building_count=len(buildings),
|
|||
|
|
datetime=full_data.datetime,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
logger.info(f"成功获取楼栋列表,共 {len(buildings)} 个楼栋")
|
|||
|
|
return UniResponseModel[BuildingListResponse](
|
|||
|
|
success=True,
|
|||
|
|
data=result,
|
|||
|
|
message=f"获取楼栋列表成功,共 {len(buildings)} 个楼栋",
|
|||
|
|
error=None,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"获取楼栋列表异常: {str(e)}")
|
|||
|
|
return ISIMRouterErrorToCode().server_error.to_json_response(logger.trace_id)
|
|||
|
|
|
|||
|
|
|
|||
|
|
@isim_room_router.get(
|
|||
|
|
"/list/building/{building_code}",
|
|||
|
|
summary="[按楼栋查询] 获取指定楼栋的所有楼层和房间",
|
|||
|
|
response_model=UniResponseModel[CacheRoomsData],
|
|||
|
|
)
|
|||
|
|
async def get_building_rooms(
|
|||
|
|
building_code: str, isim_conn: ISIMClient = Depends(get_isim_client)
|
|||
|
|
) -> UniResponseModel[CacheRoomsData] | JSONResponse:
|
|||
|
|
"""
|
|||
|
|
获取指定楼栋及其所有楼层和房间的完整数据
|
|||
|
|
|
|||
|
|
✅ 数据量适中:只返回单个楼栋的数据,比完整列表小90%+
|
|||
|
|
💡 使用场景:
|
|||
|
|
- 用户选择楼栋后,展示该楼栋的所有楼层和房间
|
|||
|
|
- 楼栋详情页
|
|||
|
|
- 减少移动端流量消耗
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
building_code: 楼栋代码(如:01, 02, 11等)
|
|||
|
|
"""
|
|||
|
|
logger = isim_conn.client.logger
|
|||
|
|
try:
|
|||
|
|
# 使用Hash精细化查询,只获取指定楼栋
|
|||
|
|
building_data = await isim_conn.get_building_with_floors(building_code)
|
|||
|
|
|
|||
|
|
if not building_data:
|
|||
|
|
logger.warning(f"楼栋 {building_code} 不存在或无数据")
|
|||
|
|
return ISIMRouterErrorToCode().null_response.to_json_response(
|
|||
|
|
logger.trace_id
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 构造响应数据
|
|||
|
|
import datetime
|
|||
|
|
|
|||
|
|
result = CacheRoomsData(
|
|||
|
|
datetime=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
|||
|
|
data=[building_data],
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
logger.info(
|
|||
|
|
f"成功获取楼栋 {building_code} 信息,"
|
|||
|
|
f"楼层数: {len(building_data.floors)}, "
|
|||
|
|
f"房间数: {sum(len(f.rooms) for f in building_data.floors)}"
|
|||
|
|
)
|
|||
|
|
return UniResponseModel[CacheRoomsData](
|
|||
|
|
success=True,
|
|||
|
|
data=result,
|
|||
|
|
message=f"获取楼栋 {building_code} 信息成功",
|
|||
|
|
error=None,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"获取楼栋 {building_code} 信息异常: {str(e)}")
|
|||
|
|
return ISIMRouterErrorToCode().server_error.to_json_response(logger.trace_id)
|
|||
|
|
|
|||
|
|
|
|||
|
|
@isim_room_router.get(
|
|||
|
|
"/list/floor/{floor_code}",
|
|||
|
|
summary="[按楼层查询] 获取指定楼层的所有房间列表",
|
|||
|
|
response_model=UniResponseModel[FloorRoomsResponse],
|
|||
|
|
)
|
|||
|
|
async def get_floor_rooms(
|
|||
|
|
floor_code: str, isim_conn: ISIMClient = Depends(get_isim_client)
|
|||
|
|
) -> UniResponseModel[FloorRoomsResponse] | JSONResponse:
|
|||
|
|
"""
|
|||
|
|
获取指定楼层的所有房间信息
|
|||
|
|
|
|||
|
|
✅ 数据量最小:只返回单个楼层的房间列表,极小数据量
|
|||
|
|
💡 使用场景:
|
|||
|
|
- 用户选择楼层后,展示该楼层的所有房间
|
|||
|
|
- 房间选择器的第三级
|
|||
|
|
- 移动端分页加载
|
|||
|
|
- 需要最快响应速度的场景
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
floor_code: 楼层代码(如:0101, 0102, 1101等)
|
|||
|
|
"""
|
|||
|
|
logger = isim_conn.client.logger
|
|||
|
|
try:
|
|||
|
|
# 获取楼层信息
|
|||
|
|
floor_info = await isim_conn.get_floor_info(floor_code)
|
|||
|
|
|
|||
|
|
if not floor_info:
|
|||
|
|
logger.warning(f"楼层 {floor_code} 不存在")
|
|||
|
|
return ISIMRouterErrorToCode().null_response.to_json_response(
|
|||
|
|
logger.trace_id
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 获取房间列表(从Hash直接查询,非常快速)
|
|||
|
|
rooms = await isim_conn.get_rooms_by_floor(floor_code)
|
|||
|
|
|
|||
|
|
# 从楼层代码提取楼栋代码(前2位)
|
|||
|
|
building_code = floor_code[:2] if len(floor_code) >= 2 else ""
|
|||
|
|
|
|||
|
|
result = FloorRoomsResponse(
|
|||
|
|
floor_code=floor_info.code,
|
|||
|
|
floor_name=floor_info.name,
|
|||
|
|
building_code=building_code,
|
|||
|
|
rooms=rooms,
|
|||
|
|
room_count=len(rooms),
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
logger.info(
|
|||
|
|
f"成功获取楼层 {floor_code} ({floor_info.name}) 的房间信息,共 {len(rooms)} 个房间"
|
|||
|
|
)
|
|||
|
|
return UniResponseModel[FloorRoomsResponse](
|
|||
|
|
success=True,
|
|||
|
|
data=result,
|
|||
|
|
message=f"获取楼层 {floor_code} 的房间信息成功,共 {len(rooms)} 个房间",
|
|||
|
|
error=None,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"获取楼层 {floor_code} 房间信息异常: {str(e)}")
|
|||
|
|
return ISIMRouterErrorToCode().server_error.to_json_response(logger.trace_id)
|
|||
|
|
|
|||
|
|
|
|||
|
|
@isim_room_router.get(
|
|||
|
|
"/info/{room_code}",
|
|||
|
|
summary="[房间详情] 获取单个房间的完整层级信息",
|
|||
|
|
response_model=UniResponseModel[RoomDetailResponse],
|
|||
|
|
)
|
|||
|
|
async def get_room_info(
|
|||
|
|
room_code: str, isim_conn: ISIMClient = Depends(get_isim_client)
|
|||
|
|
) -> UniResponseModel[RoomDetailResponse] | JSONResponse:
|
|||
|
|
"""
|
|||
|
|
获取指定房间的完整信息(包括楼栋、楼层、房间的完整层级结构)
|
|||
|
|
|
|||
|
|
✅ 功能强大:一次性返回房间的完整上下文信息
|
|||
|
|
💡 使用场景:
|
|||
|
|
- 房间详情页展示
|
|||
|
|
- 显示完整的 "楼栋/楼层/房间" 路径
|
|||
|
|
- 房间搜索结果展示
|
|||
|
|
- 需要房间完整信息的场景
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
room_code: 房间代码(如:010101, 110627等)
|
|||
|
|
"""
|
|||
|
|
logger = isim_conn.client.logger
|
|||
|
|
try:
|
|||
|
|
# 提取层级代码
|
|||
|
|
if len(room_code) < 4:
|
|||
|
|
logger.warning(f"房间代码 {room_code} 格式错误")
|
|||
|
|
return ISIMRouterErrorToCode().null_response.to_json_response(
|
|||
|
|
logger.trace_id
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
building_code = room_code[:2]
|
|||
|
|
floor_code = room_code[:4]
|
|||
|
|
|
|||
|
|
# 并发获取所有需要的信息
|
|||
|
|
import asyncio
|
|||
|
|
|
|||
|
|
building_info, floor_info, room_info = await asyncio.gather(
|
|||
|
|
isim_conn.get_building_info(building_code),
|
|||
|
|
isim_conn.get_floor_info(floor_code),
|
|||
|
|
isim_conn.query_room_info_fast(room_code),
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
if not room_info:
|
|||
|
|
logger.warning(f"房间 {room_code} 不存在")
|
|||
|
|
return ISIMRouterErrorToCode().null_response.to_json_response(
|
|||
|
|
logger.trace_id
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 构造显示文本
|
|||
|
|
building_name = building_info.name if building_info else "未知楼栋"
|
|||
|
|
floor_name = floor_info.name if floor_info else "未知楼层"
|
|||
|
|
display_text = f"{building_name}/{floor_name}/{room_info.name}"
|
|||
|
|
|
|||
|
|
result = RoomDetailResponse(
|
|||
|
|
room_code=room_info.code,
|
|||
|
|
room_name=room_info.name,
|
|||
|
|
floor_code=floor_code,
|
|||
|
|
floor_name=floor_name,
|
|||
|
|
building_code=building_code,
|
|||
|
|
building_name=building_name,
|
|||
|
|
display_text=display_text,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
logger.info(f"成功获取房间 {room_code} 的详细信息: {display_text}")
|
|||
|
|
return UniResponseModel[RoomDetailResponse](
|
|||
|
|
success=True,
|
|||
|
|
data=result,
|
|||
|
|
message=f"获取房间 {room_code} 的详细信息成功",
|
|||
|
|
error=None,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"获取房间 {room_code} 详细信息异常: {str(e)}")
|
|||
|
|
return ISIMRouterErrorToCode().server_error.to_json_response(logger.trace_id)
|
|||
|
|
|
|||
|
|
|
|||
|
|
@isim_room_router.post(
|
|||
|
|
"/bind",
|
|||
|
|
summary="[用户操作] 绑定寝室到当前用户",
|
|||
|
|
response_model=UniResponseModel[BindRoomResponse],
|
|||
|
|
)
|
|||
|
|
async def bind_room(
|
|||
|
|
bind_request: BindRoomRequest,
|
|||
|
|
isim_conn: ISIMClient = Depends(get_isim_client),
|
|||
|
|
db: AsyncSession = Depends(get_db_session),
|
|||
|
|
) -> UniResponseModel[BindRoomResponse] | JSONResponse:
|
|||
|
|
"""
|
|||
|
|
绑定寝室到当前用户(存在即更新)
|
|||
|
|
|
|||
|
|
💡 使用场景:
|
|||
|
|
- 用户首次绑定寝室
|
|||
|
|
- 用户更换寝室
|
|||
|
|
- 修改绑定信息
|
|||
|
|
"""
|
|||
|
|
logger = isim_conn.client.logger
|
|||
|
|
try:
|
|||
|
|
exist = await db.execute(
|
|||
|
|
select(RoomBind).where(RoomBind.user_id == isim_conn.client.userid)
|
|||
|
|
)
|
|||
|
|
exist = exist.scalars().first()
|
|||
|
|
if exist:
|
|||
|
|
if exist.roomid == bind_request.room_id:
|
|||
|
|
return UniResponseModel[BindRoomResponse](
|
|||
|
|
success=True,
|
|||
|
|
data=BindRoomResponse(success=True),
|
|||
|
|
message="宿舍绑定成功",
|
|||
|
|
error=None,
|
|||
|
|
)
|
|||
|
|
else:
|
|||
|
|
# 使用快速查询方法(从Hash直接获取,无需遍历完整树)
|
|||
|
|
room_info = await isim_conn.query_room_info_fast(bind_request.room_id)
|
|||
|
|
roomtext = room_info.name if room_info else None
|
|||
|
|
|
|||
|
|
# 如果Hash中没有,回退到完整查询
|
|||
|
|
if not roomtext:
|
|||
|
|
roomtext = await isim_conn.query_room_name(bind_request.room_id)
|
|||
|
|
|
|||
|
|
await db.execute(
|
|||
|
|
update(RoomBind)
|
|||
|
|
.where(RoomBind.user_id == isim_conn.client.userid)
|
|||
|
|
.values(roomid=bind_request.room_id, roomtext=roomtext)
|
|||
|
|
)
|
|||
|
|
await db.commit()
|
|||
|
|
logger.info(f"更新寝室绑定成功: {roomtext}({bind_request.room_id})")
|
|||
|
|
return UniResponseModel[BindRoomResponse](
|
|||
|
|
success=True,
|
|||
|
|
data=BindRoomResponse(success=True),
|
|||
|
|
message="宿舍绑定成功",
|
|||
|
|
error=None,
|
|||
|
|
)
|
|||
|
|
else:
|
|||
|
|
# 使用快速查询方法(从Hash直接获取,无需遍历完整树)
|
|||
|
|
room_info = await isim_conn.query_room_info_fast(bind_request.room_id)
|
|||
|
|
roomtext = room_info.name if room_info else None
|
|||
|
|
|
|||
|
|
# 如果Hash中没有,回退到完整查询
|
|||
|
|
if not roomtext:
|
|||
|
|
roomtext = await isim_conn.query_room_name(bind_request.room_id)
|
|||
|
|
|
|||
|
|
new_bind = RoomBind(
|
|||
|
|
user_id=isim_conn.client.userid,
|
|||
|
|
roomid=bind_request.room_id,
|
|||
|
|
roomtext=roomtext,
|
|||
|
|
)
|
|||
|
|
db.add(new_bind)
|
|||
|
|
await db.commit()
|
|||
|
|
logger.info(f"新增寝室绑定成功: {roomtext}({bind_request.room_id})")
|
|||
|
|
return UniResponseModel[BindRoomResponse](
|
|||
|
|
success=True,
|
|||
|
|
data=BindRoomResponse(success=True),
|
|||
|
|
message="宿舍绑定成功",
|
|||
|
|
error=None,
|
|||
|
|
)
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"绑定寝室异常: {str(e)}")
|
|||
|
|
return ISIMRouterErrorToCode().server_error.to_json_response(
|
|||
|
|
isim_conn.client.logger.trace_id
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
|
|||
|
|
@isim_room_router.get(
|
|||
|
|
"/current",
|
|||
|
|
summary="[用户查询] 获取当前用户绑定的宿舍信息",
|
|||
|
|
response_model=UniResponseModel[CurrentRoomResponse],
|
|||
|
|
)
|
|||
|
|
async def get_current_room(
|
|||
|
|
user: ACEUser = Depends(get_user_by_token),
|
|||
|
|
isim_conn: ISIMClient = Depends(get_isim_client),
|
|||
|
|
db: AsyncSession = Depends(get_db_session),
|
|||
|
|
) -> UniResponseModel[CurrentRoomResponse] | JSONResponse:
|
|||
|
|
"""
|
|||
|
|
获取当前用户绑定的宿舍信息,返回 room_code 和 display_text
|
|||
|
|
|
|||
|
|
💡 使用场景:
|
|||
|
|
- 个人中心显示已绑定宿舍
|
|||
|
|
- 查询当前用户的寝室信息
|
|||
|
|
- 验证用户是否已绑定寝室
|
|||
|
|
"""
|
|||
|
|
logger = isim_conn.client.logger
|
|||
|
|
try:
|
|||
|
|
# 查询用户绑定的房间
|
|||
|
|
result = await db.execute(
|
|||
|
|
select(RoomBind).where(RoomBind.user_id == user.userid)
|
|||
|
|
)
|
|||
|
|
room_bind = result.scalars().first()
|
|||
|
|
|
|||
|
|
if not room_bind:
|
|||
|
|
logger.warning(f"用户 {user.userid} 未绑定宿舍")
|
|||
|
|
return UniResponseModel[CurrentRoomResponse](
|
|||
|
|
success=True,
|
|||
|
|
data=CurrentRoomResponse(
|
|||
|
|
room_code="",
|
|||
|
|
display_text="",
|
|||
|
|
),
|
|||
|
|
message="获取宿舍信息成功,用户未绑定宿舍",
|
|||
|
|
error=None,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 优先从Hash缓存快速获取房间显示文本
|
|||
|
|
display_text = await isim_conn.get_room_display_text(room_bind.roomid)
|
|||
|
|
if not display_text:
|
|||
|
|
# 如果缓存中没有,使用数据库中存储的文本
|
|||
|
|
display_text = room_bind.roomtext
|
|||
|
|
logger.debug(
|
|||
|
|
f"Hash缓存中未找到房间 {room_bind.roomid},使用数据库存储的文本"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
logger.info(f"成功获取用户 {user.userid} 的宿舍信息: {display_text}")
|
|||
|
|
return UniResponseModel[CurrentRoomResponse](
|
|||
|
|
success=True,
|
|||
|
|
data=CurrentRoomResponse(
|
|||
|
|
room_code=room_bind.roomid,
|
|||
|
|
display_text=display_text,
|
|||
|
|
),
|
|||
|
|
message="获取宿舍信息成功",
|
|||
|
|
error=None,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"获取当前宿舍异常: {str(e)}")
|
|||
|
|
return ISIMRouterErrorToCode().server_error.to_json_response(logger.trace_id)
|
|||
|
|
|
|||
|
|
|
|||
|
|
@isim_room_router.post(
|
|||
|
|
"/refresh",
|
|||
|
|
summary="[管理操作] 强制刷新房间列表缓存",
|
|||
|
|
response_model=UniResponseModel[ForceRefreshResponse],
|
|||
|
|
)
|
|||
|
|
async def force_refresh_rooms(
|
|||
|
|
isim_conn: ISIMClient = Depends(get_isim_client),
|
|||
|
|
) -> UniResponseModel[ForceRefreshResponse] | JSONResponse:
|
|||
|
|
"""
|
|||
|
|
强制刷新房间列表缓存(从ISIM系统重新获取数据)
|
|||
|
|
|
|||
|
|
⚠️ 限制:
|
|||
|
|
- 使用全局锁确保同一时间只有一个请求在执行刷新操作
|
|||
|
|
- 刷新完成后有30分钟的冷却时间
|
|||
|
|
|
|||
|
|
💡 使用场景:
|
|||
|
|
- 发现数据不准确时手动刷新
|
|||
|
|
- 管理员更新缓存数据
|
|||
|
|
- 调试和测试
|
|||
|
|
"""
|
|||
|
|
logger = isim_conn.client.logger
|
|||
|
|
lock_manager = get_refresh_lock_manager()
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
# 尝试获取锁
|
|||
|
|
acquired, remaining_cooldown = await lock_manager.try_acquire()
|
|||
|
|
|
|||
|
|
if not acquired:
|
|||
|
|
if remaining_cooldown is not None:
|
|||
|
|
# 在冷却期内
|
|||
|
|
minutes = int(remaining_cooldown // 60)
|
|||
|
|
seconds = int(remaining_cooldown % 60)
|
|||
|
|
message = f"刷新操作冷却中,请在 {minutes} 分 {seconds} 秒后重试"
|
|||
|
|
logger.warning(f"刷新请求被拒绝: {message}")
|
|||
|
|
return UniResponseModel[ForceRefreshResponse](
|
|||
|
|
success=False,
|
|||
|
|
data=ForceRefreshResponse(
|
|||
|
|
success=False,
|
|||
|
|
message=message,
|
|||
|
|
remaining_cooldown=remaining_cooldown,
|
|||
|
|
),
|
|||
|
|
message=message,
|
|||
|
|
error=None,
|
|||
|
|
)
|
|||
|
|
else:
|
|||
|
|
# 有其他人正在刷新
|
|||
|
|
message = "其他用户正在刷新房间列表,请稍后再试"
|
|||
|
|
logger.warning(message)
|
|||
|
|
return UniResponseModel[ForceRefreshResponse](
|
|||
|
|
success=False,
|
|||
|
|
data=ForceRefreshResponse(
|
|||
|
|
success=False,
|
|||
|
|
message=message,
|
|||
|
|
remaining_cooldown=0.0,
|
|||
|
|
),
|
|||
|
|
message=message,
|
|||
|
|
error=None,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 成功获取锁,执行刷新操作
|
|||
|
|
try:
|
|||
|
|
logger.info("开始强制刷新房间列表缓存")
|
|||
|
|
await isim_conn.force_refresh_room_cache()
|
|||
|
|
logger.info("房间列表缓存刷新完成")
|
|||
|
|
|
|||
|
|
return UniResponseModel[ForceRefreshResponse](
|
|||
|
|
success=True,
|
|||
|
|
data=ForceRefreshResponse(
|
|||
|
|
success=True,
|
|||
|
|
message="房间列表刷新成功",
|
|||
|
|
remaining_cooldown=0.0,
|
|||
|
|
),
|
|||
|
|
message="房间列表刷新成功",
|
|||
|
|
error=None,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
finally:
|
|||
|
|
# 释放锁并设置冷却时间
|
|||
|
|
lock_manager.release()
|
|||
|
|
logger.info("刷新锁已释放,冷却时间已设置")
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"强制刷新房间列表异常: {str(e)}")
|
|||
|
|
# 确保异常时也释放锁
|
|||
|
|
if lock_manager.is_refreshing():
|
|||
|
|
lock_manager.release()
|
|||
|
|
return ISIMRouterErrorToCode().server_error.to_json_response(logger.trace_id)
|