101 lines
4.3 KiB
Python
101 lines
4.3 KiB
Python
# =============================================================================
|
|
# 企微IT智能服务台 — 超时提醒定时任务
|
|
# =============================================================================
|
|
# 说明:定时检查超时未回复的会话,发送企微提醒消息
|
|
# 运行频率:每 30 秒执行一次
|
|
# 超时逻辑:
|
|
# 1. 坐席回复后 3 分钟员工未回复 -> 发送企微提醒(只发 1 次)
|
|
# 2. 坐席回复后 10 分钟员工未回复 -> 标记会话为 pending_close
|
|
# =============================================================================
|
|
|
|
import logging
|
|
from datetime import datetime, timedelta
|
|
|
|
from sqlalchemy import select
|
|
|
|
from app.models.conversation import Conversation
|
|
from app.services.reminder_service import send_reminder_message
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
# 超时配置(分钟)
|
|
REMINDER_TIMEOUT_MINUTES = 3 # 未回复超时时间
|
|
CLOSE_TIMEOUT_MINUTES = 10 # 自动待关闭时间
|
|
|
|
|
|
async def check_unreplied_sessions():
|
|
"""检查超时未回复的会话,发送提醒并标记待关闭。
|
|
|
|
此函数由 APScheduler 定时调用(每 30 秒)。
|
|
执行流程:
|
|
1. 查找需要发送提醒的会话(坐席回复超过3分钟,员工未回复且未发送过提醒)
|
|
2. 发送企微提醒消息
|
|
3. 标记已发送提醒
|
|
4. 查找需要标记待关闭的会话(坐席回复超过10分钟)
|
|
5. 更新会话状态为 pending_close
|
|
"""
|
|
# 导入数据库 session 工厂
|
|
from app.database import _get_session_factory
|
|
|
|
async_session_factory = _get_session_factory()
|
|
|
|
async with async_session_factory() as db:
|
|
try:
|
|
# 1. 查找需要发送提醒的会话
|
|
# 条件:active 状态 + 有坐席回复 + 超过3分钟未回复 + 未发送过提醒
|
|
reminder_threshold = datetime.now() - timedelta(minutes=REMINDER_TIMEOUT_MINUTES)
|
|
|
|
reminder_stmt = select(Conversation).where(
|
|
Conversation.status == "serving",
|
|
Conversation.last_agent_reply_at.isnot(None),
|
|
Conversation.last_agent_reply_at < reminder_threshold,
|
|
Conversation.reminder_sent == False,
|
|
)
|
|
result = await db.execute(reminder_stmt)
|
|
sessions_to_remind = result.scalars().all()
|
|
|
|
logger.info(f"发现 {len(sessions_to_remind)} 个需要发送提醒的会话")
|
|
|
|
# 2. 发送企微提醒消息
|
|
for session in sessions_to_remind:
|
|
try:
|
|
success = await send_reminder_message(session.employee_id)
|
|
if success:
|
|
# 3. 标记已发送提醒
|
|
session.reminder_sent = True
|
|
session.reminder_sent_at = datetime.now()
|
|
logger.info(f"会话 {session.id} 已发送提醒: employee_id={session.employee_id}")
|
|
else:
|
|
logger.warning(f"会话 {session.id} 提醒发送失败,跳过")
|
|
except Exception as e:
|
|
logger.error(f"会话 {session.id} 发送提醒异常: {e}")
|
|
continue
|
|
|
|
# 4. 查找需要标记待关闭的会话
|
|
# 条件:active 状态 + 有坐席回复 + 超过10分钟未回复
|
|
close_threshold = datetime.now() - timedelta(minutes=CLOSE_TIMEOUT_MINUTES)
|
|
|
|
close_stmt = select(Conversation).where(
|
|
Conversation.status == "serving",
|
|
Conversation.last_agent_reply_at.isnot(None),
|
|
Conversation.last_agent_reply_at < close_threshold,
|
|
)
|
|
result = await db.execute(close_stmt)
|
|
sessions_to_close = result.scalars().all()
|
|
|
|
logger.info(f"发现 {len(sessions_to_close)} 个需要标记待关闭的会话")
|
|
|
|
# 5. 更新会话状态为 pending_close
|
|
for session in sessions_to_close:
|
|
session.status = "pending_close"
|
|
logger.info(f"会话 {session.id} 已标记为待关闭: employee_id={session.employee_id}")
|
|
|
|
# 提交数据库变更
|
|
await db.commit()
|
|
logger.info("超时检查任务执行完成")
|
|
|
|
except Exception as e:
|
|
await db.rollback()
|
|
logger.error(f"超时检查任务执行异常: {e}")
|
|
raise
|