feat: 累积功能变更 — 聊天集成、租户管理、小程序更新、ETL 增强、迁移脚本

包含多个会话的累积代码变更:
- backend: AI 聊天服务、触发器调度、认证增强、WebSocket、调度器最小间隔
- admin-web: ETL 状态页、任务管理、调度配置、登录优化
- miniprogram: 看板页面、聊天集成、UI 组件、导航更新
- etl: DWS 新任务(finance_area_daily/board_cache)、连接器增强
- tenant-admin: 项目初始化
- db: 19 个迁移脚本(etl_feiqiu 11 + zqyy_app 8)
- packages/shared: 枚举和工具函数更新
- tools: 数据库工具、报表生成、健康检查
- docs: PRD/架构/部署/合约文档更新

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Neo
2026-04-06 00:03:48 +08:00
parent 70324d8542
commit 6f8f12314f
515 changed files with 76604 additions and 7456 deletions

View File

@@ -424,6 +424,10 @@ class TaskQueue:
# 被吞掉后_update_queue_status_from_log 读到的 execution_log 仍是
# running导致 task_queue 永远卡住,后续任务全部排队。
self._ensure_not_stuck_running(queue_id)
# CHANGE 2026-03-22 | P16: 回写 scheduled_tasks.last_status
# 成功时同时更新 last_success_at失败时不更新
if schedule_id:
self._update_schedule_status(queue_id, schedule_id)
def _get_pending_site_ids(self) -> list[int]:
@@ -533,6 +537,73 @@ class TaskQueue:
finally:
conn.close()
def _update_schedule_status(self, queue_id: str, schedule_id: str) -> None:
"""回写 scheduled_tasks.last_status成功时同时更新 last_success_at。
CHANGE 2026-03-22 | P16: 任务完成回调区分成功/失败
- 成功completed→ last_status='completed', last_success_at=NOW()
- 失败failed 等)→ last_status='failed'last_success_at 不变)
"""
conn = get_connection()
try:
with conn.cursor() as cur:
# 从 task_queue 读取最终状态
cur.execute(
"SELECT status FROM task_queue WHERE id = %s",
(queue_id,),
)
row = cur.fetchone()
if not row:
return
final_status = row[0]
if final_status == "completed":
cur.execute(
"""
UPDATE scheduled_tasks
SET last_status = 'completed',
last_success_at = NOW(),
updated_at = NOW()
WHERE id = %s
""",
(schedule_id,),
)
elif final_status in ("failed", "error"):
cur.execute(
"""
UPDATE scheduled_tasks
SET last_status = 'failed',
updated_at = NOW()
WHERE id = %s
""",
(schedule_id,),
)
else:
# 其他状态(如 running 兜底后仍未变)不更新
logger.warning(
"调度任务 [%s] 回写跳过task_queue [%s] 最终状态=%s",
schedule_id, queue_id, final_status,
)
return
conn.commit()
logger.info(
"调度任务 [%s] 状态回写:%squeue_id=%s",
schedule_id, final_status, queue_id,
)
except Exception:
logger.exception(
"_update_schedule_status 异常 schedule_id=%s queue_id=%s",
schedule_id, queue_id,
)
try:
conn.rollback()
except Exception:
pass
finally:
conn.close()
def _recover_zombie_tasks(self, max_running_minutes: int = 180) -> None:
"""恢复僵尸 running 任务:超过阈值时间仍为 running 的任务强制标记 failed。