回收站,软删除(三天自动清空),以及默认链接三十分钟失效

This commit is contained in:
amb
2026-09-02 18:59:42 +08:00
parent bfb7a1a8a2
commit ff3e2a7273
16 changed files with 797 additions and 38 deletions
+24 -5
View File
@@ -15,6 +15,7 @@ from app.api.categories import router as cat_router
from app.api.documents import router as doc_router
from app.api.health import router as health_router
from app.api.knowledge_bases import router as kb_router
from app.api.recycle_bin import router as recycle_router
from app.public.routes import router as public_router
from app.core.config import get_settings
from app.core.db import dispose_engine, get_session_factory
@@ -65,16 +66,29 @@ def _cleanup_access_logs() -> int:
return count
async def _periodic_log_cleanup() -> None:
""" 24 小时清理一次过期访问日志(在线程池执行同步 DB 操作)"""
async def _periodic_cleanup() -> None:
"""小时执行一次数据清理:访问日志 + 回收站过期内容"""
import asyncio
while True:
await asyncio.sleep(24 * 3600)
await asyncio.sleep(3600)
try:
await asyncio.to_thread(_cleanup_access_logs)
except Exception: # noqa: BLE001
logger.exception("定期清理访问日志失败")
try:
await asyncio.to_thread(_purge_recycle_bin)
except Exception: # noqa: BLE001
logger.exception("定期清理回收站失败")
def _purge_recycle_bin() -> int:
"""彻底删除回收站中超过保留期的内容。"""
from app.services.recycle_bin_service import RecycleBinService
factory = get_session_factory()
with factory() as session:
return RecycleBinService(session).purge_expired()
@asynccontextmanager
@@ -90,14 +104,18 @@ async def lifespan(app: FastAPI):
# Seed:确保 free plan 存在
_seed_free_plan()
# 启动时清理过期访问日志(不阻塞启动)
# 启动时清理过期数据:访问日志 + 回收站(不阻塞启动)
import asyncio
cleanup_task = asyncio.create_task(_periodic_log_cleanup())
cleanup_task = asyncio.create_task(_periodic_cleanup())
try:
await asyncio.wait_for(asyncio.to_thread(_cleanup_access_logs), timeout=15)
except Exception: # noqa: BLE001
logger.warning("启动时清理访问日志未完成(首次部署属正常)")
try:
await asyncio.wait_for(asyncio.to_thread(_purge_recycle_bin), timeout=15)
except Exception: # noqa: BLE001
logger.warning("启动时清理回收站未完成(首次部署属正常)")
yield
@@ -138,6 +156,7 @@ def create_app() -> FastAPI:
app.include_router(kb_router, prefix="/api", tags=["knowledge-bases"])
app.include_router(doc_router, prefix="/api", tags=["documents"])
app.include_router(cat_router, prefix="/api", tags=["categories"])
app.include_router(recycle_router, prefix="/api", tags=["recycle-bin"])
app.include_router(public_router, tags=["public"])
return app