fix(ai): F1-5a 沙箱 batch-run 接入 runtime_context (W1 / 阶段 A 主体)
Neo F1-5 反馈: "让沙箱起到其真正的作用. 真正的模拟日期, 仅能看到沙箱设定日期 及之前日期的数据, 并运行 AI 的各个业务." 调研发现 (4 个并行子代理): batch-run 端点 _run_batch 是空壳 stub (只 logger.info, 实际不跑 AI), GUC apply_runtime_session_vars 0 处调用 (dead code), 7 张业务表 6 张有 runtime 复合索引唯独 ai_run_logs 漏建, App2/2a 3 行 _calc_date_range 漏传 ref_date. 本 commit (F1-5a 阶段 A 主体, F1-5b 后续完整 zqyy_app RLS 视图层): 后端核心: - admin_service.py: _run_batch 真实化 (Semaphore(5)+asyncio.gather+ return_exceptions=True+ctx_snapshot 防漂移); estimate 入口抓 RuntimeContext 快照, confirm 取出传给 worker - admin_ai.py: confirm_batch_run lazy 注入 dispatcher - admin_service.retry_trigger_job: INSERT 落 runtime_mode + sandbox_instance_id 列 (用 runtime_insert_columns helper) - runtime_context.py: get_runtime_context 加 bind_to_session 参数, 激活 GUC app.current_business_date / app.current_runtime_mode - run_log_service.create_log: 启用 bind_to_session=True 试点 App2/2a 3 行 ref_date 修复: - app2_finance_prompt.py:817 储值卡余额变化板块 - app2_finance_prompt.py:841 日粒度 series + 异常检测窗口 - app2a_finance_area_prompt.py:466 区域日粒度 series DB: - migrations/20260505__ai_run_logs_runtime_index.sql: 补 (site_id, runtime_mode, sandbox_instance_id, created_at DESC) 复合索引 前端: - AIOperations.tsx: 顶部加 sandbox 模式提示条 (Alert 显示 sandbox_date + sandbox_instance_id + 影响范围 + 切回 live 入口) 未做 (留 F1-5b 完整 zqyy_app RLS 视图层一并): - B1 admin_service 6 处 CURRENT_DATE -> business_date - B2 fdw_queries 异常分支兜底 - GUC 完整传递 (fdw_queries / page_context 等) - 测试 3 套 (.gitignore:71 排除, F2-2 入仓时 commit) - P20 SPEC \xa76/\xa710/\xa711/\xa715 (F1-5b 完整收口后同步更准确) Neo 决策: docs/_overview/wave1-findings/F1-5-impl-decisions.md 详见 docs/audit/changes/2026-05-05__wave1_f1_5a_sandbox_batch_run.md
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
|
||||
import React, { useEffect, useState, useCallback } from "react";
|
||||
import {
|
||||
Card, Row, Col, Select, Input, Button, Table, Tag, Space,
|
||||
Alert, Card, Row, Col, Select, Input, Button, Table, Tag, Space,
|
||||
Checkbox, Modal, Statistic, message, Typography,
|
||||
} from "antd";
|
||||
import { ReloadOutlined } from "@ant-design/icons";
|
||||
@@ -20,6 +20,8 @@ import {
|
||||
getAlerts, ackAlert, ignoreAlert, runApp, triggerEvent,
|
||||
type AlertItem, type AppType, type BatchRunEstimate,
|
||||
} from "../api/adminAI";
|
||||
// F1-5a: sandbox 模式提示条数据源
|
||||
import { fetchRuntimeContext, type RuntimeContext } from "../api/runtimeContext";
|
||||
|
||||
const EVENT_TYPE_OPTIONS = [
|
||||
{ label: "消费事件(App3→App8→App7 [+ App4→App5])", value: "consumption" },
|
||||
@@ -213,6 +215,24 @@ const AIOperations: React.FC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
// ---- F1-5a: Sandbox 模式提示条 ----
|
||||
// 沙箱机制 P0-7 主线:让运维进入 AI 操作页前能看到当前 sandbox 状态,
|
||||
// 避免"以为 live 模式"误触发批量执行实际跑在 sandbox 数据集上的混淆。
|
||||
const [runtimeCtx, setRuntimeCtx] = useState<RuntimeContext | null>(null);
|
||||
useEffect(() => {
|
||||
// 复用 cacheSiteId 作为当前关注 site(默认 2790685415443269,与 cacheSiteId / runSiteId 一致)
|
||||
let cancelled = false;
|
||||
(async () => {
|
||||
try {
|
||||
const ctx = await fetchRuntimeContext(cacheSiteId);
|
||||
if (!cancelled) setRuntimeCtx(ctx);
|
||||
} catch {
|
||||
// 失败不阻断页面渲染(get_runtime_context 表不存在时后端降级 live)
|
||||
}
|
||||
})();
|
||||
return () => { cancelled = true; };
|
||||
}, [cacheSiteId]);
|
||||
|
||||
// ---- Card 4: 告警管理 ----
|
||||
const [alerts, setAlerts] = useState<AlertItem[]>([]);
|
||||
const [alertTotal, setAlertTotal] = useState(0);
|
||||
@@ -282,6 +302,28 @@ const AIOperations: React.FC = () => {
|
||||
<div>
|
||||
<Title level={4} style={{ marginBottom: 16 }}>AI 手动操作</Title>
|
||||
|
||||
{runtimeCtx && runtimeCtx.is_sandbox && (
|
||||
<Alert
|
||||
type="warning"
|
||||
showIcon
|
||||
style={{ marginBottom: 16 }}
|
||||
message={
|
||||
<span>
|
||||
<strong>沙箱模式</strong> · 业务日 <strong>{runtimeCtx.sandbox_date ?? "—"}</strong> ·
|
||||
实例 <code>{runtimeCtx.sandbox_instance_id ?? "—"}</code>
|
||||
</span>
|
||||
}
|
||||
description={
|
||||
<span>
|
||||
当前 site_id={cacheSiteId} 处于沙箱模式。本页所有 AI 触发(手动重跑 / 缓存失效 / 按需执行 / 批量执行)将使用
|
||||
沙箱业务日 ({runtimeCtx.sandbox_date}) 而非真实今日;ETL 视图自动按业务日上界裁剪,助教/会员消费数据仅可见
|
||||
沙箱日及之前。结果写入 ai_run_logs 时 runtime_mode=sandbox + sandbox_instance_id 隔离,
|
||||
不污染 live 数据。如需切回 live,前往 <a href="/settings/runtime-context">运行上下文</a> 页。
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Row gutter={16} style={{ marginBottom: 16 }}>
|
||||
{/* Card 1: 手动重跑 */}
|
||||
<Col span={12}>
|
||||
|
||||
Reference in New Issue
Block a user