P0-1: 删除 docker-compose-override.yml + deploy-server 两份 workers=2→1(预防性修复,服务器根 compose 已是 workers=1)
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
会话归档脚本
|
||||
|
||||
功能:将会话结束超过90天的会话标记为已归档
|
||||
|
||||
运行方式:
|
||||
cd backend
|
||||
python scripts/archive_sessions.py
|
||||
|
||||
定时任务配置(crontab):
|
||||
# 每天凌晨3点执行
|
||||
0 3 * * * cd /opt/wecom-it-desk/backend && python scripts/archive_sessions.py >> /var/log/itdesk-archive.log 2>&1
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
# 添加 backend 目录到 Python 路径
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from sqlalchemy import create_engine, select, update
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.config import settings
|
||||
from app.models.conversation import Conversation
|
||||
|
||||
|
||||
# 归档阈值:会话结束后多少天开始归档(可配置)
|
||||
ARCHIVE_DAYS = 90
|
||||
|
||||
|
||||
def archive_sessions():
|
||||
"""将会话结束超过 ARCHIVE_DAYS 天的会话标记为已归档"""
|
||||
|
||||
print(f"[{datetime.now()}] 开始执行会话归档任务...")
|
||||
print(f"归档阈值: {ARCHIVE_DAYS} 天")
|
||||
|
||||
# 使用配置中的数据库 URL
|
||||
# 注意:本地开发使用 aiosqlite 异步驱动,但脚本是同步的
|
||||
# 需要将 sqlite+aiosqlite:// 替换为 sqlite://
|
||||
db_url = settings.database_url.replace("sqlite+aiosqlite://", "sqlite://")
|
||||
engine = create_engine(db_url)
|
||||
|
||||
# 计算归档截止时间:当前时间 - ARCHIVE_DAYS 天
|
||||
# 只有 resolved_at 早于此时间的会话才会被归档
|
||||
cutoff_date = datetime.now(timezone.utc) - timedelta(days=ARCHIVE_DAYS)
|
||||
|
||||
with Session(engine) as session:
|
||||
# 查找需要归档的会话:
|
||||
# 1. 状态为 resolved(已结单)
|
||||
# 2. 已结单时间(resolved_at 或 updated_at)早于截止时间
|
||||
# 3. 尚未被归档
|
||||
stmt = select(Conversation).where(
|
||||
Conversation.status == "resolved",
|
||||
Conversation.is_archived == False,
|
||||
# 使用 updated_at 作为参考(resolved 状态的会话 updated_at 即为结单时间)
|
||||
Conversation.updated_at < cutoff_date
|
||||
)
|
||||
|
||||
sessions_to_archive = session.execute(stmt).scalars().all()
|
||||
count = len(sessions_to_archive)
|
||||
|
||||
if count == 0:
|
||||
print(f"[{datetime.now()}] 没有需要归档的会话")
|
||||
return
|
||||
|
||||
print(f"[{datetime.now()}] 找到 {count} 个需要归档的会话")
|
||||
|
||||
# 标记为已归档
|
||||
now = datetime.now(timezone.utc)
|
||||
for session_obj in sessions_to_archive:
|
||||
session_obj.is_archived = True
|
||||
session_obj.archived_at = now
|
||||
|
||||
# 提交更改
|
||||
session.commit()
|
||||
|
||||
print(f"[{datetime.now()}] 成功归档 {count} 个会话")
|
||||
print(f"归档时间: {now.isoformat()}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
archive_sessions()
|
||||
Reference in New Issue
Block a user