proposal.md 7.1 KB

Why

后端接口服务 02010067(src.DRG.HISData.HisDataService.GetInpatientData)在开启费用明细同步(BS_HISSyncConfig.FeeFlag='Y')后,单次调用返回 504 Gateway Timeout,同步链路不可用。

根因有两点,二者叠加才致命:

  1. 落库是逐行的,耗时随费用行数线性放大。 SaveInpatientFeeData(HisDataService.cls:658-894)对每一条费用明细都执行:1 次存在性 SQL(&sql(SELECT ID ... WHERE Adm_Dr=? AND FeedetlSn=?))+ 1 次通用 ORM 调用(src.util.operatetable.Insert/Update,内部含 %Library.ClassDefinition.%ExistsId() 类定义查找、FromDynamicObj 对约 57 个属性的反射映射、%Save() 维护 5 个索引)+ 1 次全字段 feeItem.%ToJSON();且每行都是一个独立隐式事务,即每行一次 journal 提交。实测 10 条就诊 = 681 条费用明细,折算约 50–100ms/行;生产单批次为数万行,耗时达 20–50 分钟量级,必然超出任何网关超时阈值。

  2. 整条链路挤在一个同步 HTTP 请求里。 从公司转发器 172.16.1.6:8082 到 172.16.2.15:8082 再到 IRIS,任意一跳的超时配置都会先于后端返回 504。因此单纯调大超时无法根治,必须让受理请求毫秒级返回。

此外审计中发现两个既有缺陷会进一步放大耗时:GetInpatientData:441-446 无条件重复调用 DeviceFeeWarning(DRG 时分组算两遍、DIP 时结果被覆盖);synFlag='Y' 时 GetMedicalRecord 对每个就诊串行发起一次 HIS + DRG 平台 HTTP 调用。

What Changes

采用「受理异步化(根治 504)+ 落库批量化(根治耗时)」双轨方案,分 6 个模块:

  • M1 异步任务受理与状态机:新建 User.BSHISSyncTask(BS_HISSyncTask)任务表,承载 pending/running/success/partial/failed 状态流转与进度计数。02010067 新增可选入参 asyncFlag(缺省取 BS_HISSyncConfig.AsyncFlag,再缺省 'N'):'N' 时走现有同步路径、返回结构与现状完全一致;'Y' 时落任务记录后由 IRIS JOB 启动后台进程,请求在毫秒级返回受理回执 {taskId, status}。

  • M2 任务进度查询:新增接口服务 02010089 → HisDataService.GetSyncTaskProgress,按 taskId 返回状态、阶段、已处理/总数、成功/失败数与错误摘要,供前端轮询。

  • M3 费用明细批量落库引擎:重写 SaveInpatientFeeData。① 按就诊一次性预加载已有 (FeedetlSn → ID) 到内存,行内 O(1) 判定插入/更新,消除逐行 SELECT;② 用 %SQL.Statement 一次 %Prepare 参数化 INSERT/UPDATE、循环 %Execute,替代逐行 ORM 调用;③ 分段事务(默认每 500 行 TCOMMIT+TSTART),journal 提交次数降至 1/500;④ FeeDetailJson 仅新插入时序列化,更新时沿用原值。目标:单行耗时下降一个数量级(约 50–100ms → <5ms)。

  • M4 主链路缺陷修复:删除 GetInpatientData:441-446 的重复 DeviceFeeWarning 调用并修正 DIP/DRG 分支;GetMedicalRecord 的每人次 HTTP 调用纳入异步阶段并受开关控制。

  • M5 网关与链路加固:补全 frontend/nginx.conf 8082 两个 location 缺失的 proxy_connect_timeout/proxy_send_timeout/client_max_body_size/proxy_buffering;并排查中间转发器 172.16.1.6:8082 的超时配置(504 大概率源于该跳)。

  • M6 前端进度化改造:DataSync.tsx 同步请求携带 asyncFlag:'Y' 获取 taskId,轮询 02010089 并用现有 Progress 组件展示真实百分比,完成后再调 02010075;同时移除前端 7 天切批逻辑(改由后端一次吃下整个日期范围并上报进度)。

模块间数据流转:

前端「立即同步」
  -> 02010067(asyncFlag='Y') -- 建 BS_HISSyncTask(pending) -- JOB 起后台进程 -- 立即回 {taskId}
                                                                    |
                                        +---------------------------+
                                        v
                         HIS 05900014 取数 -> SaveInpatientData(就诊/DRG参数/诊断/手术)
                                        -> SaveInpatientFeeData(M3 批量落库)
                                        -> 持续回写 BS_HISSyncTask 进度/状态
  <- 前端轮询 02010089(taskId) 读进度 -> 终态后调 02010075 拉取患者列表
  • 非 BREAKING:默认 asyncFlag='N',02010067 同步模式的返回结构逐字保持现状(result 仍为 HIS 原始数组,不做任何裁剪)——满足"保持返回结构原样"的约束;异步回执是新增的可选返回形态,仅当调用方显式传 asyncFlag='Y' 时生效。

Capabilities

New Capabilities

  • his-sync-async-task:HIS 数据同步的异步受理与任务生命周期管理。覆盖 BS_HISSyncTask 任务表、02010067 的 asyncFlag 受理分支、IRIS JOB 后台执行、并发去重与进度上报,以及 02010089 进度查询接口。
  • his-fee-batch-persistence:HIS 住院费用明细的批量化落库。覆盖去重映射预加载、预编译 SQL 落库、分段事务提交与惰性 JSON 序列化,在保持 (AdmDr, FeedetlSn) 增量 Upsert 语义与既有返回字段不变的前提下消除逐行开销。

Modified Capabilities

  • his-data-sync-consolidation:新增需求——GetInpatientData 需支持可选的异步受理模式;并修正其分组/预警调用链中 DeviceFeeWarning 被重复调用、GetDIPGroupScoreFeeWarning 结果被覆盖的既有缺陷。

Impact

  • 后端新增/改造
    • src/src/User/BSHISSyncTask.cls(新建任务表类)。
    • src/src/DRG/HISData/HisDataService.cls:SaveInpatientFeeData(重写落库内核)、GetInpatientData(新增 asyncFlag 受理分支、修复重复分组调用)、GetSyncTaskProgress(新建)、RunSyncTaskAsync(新建,JOB 入口)。
    • src/src/DRG/HISData/Interface.cls:新增 GetSyncTaskProgress(02010089)委托方法。
    • src/src/DRG/HISData/SyncTaskService.cls / src/src/User/BSHISSyncConfig.cls:AsyncFlag 配置列透传(02010079 / 02010080)。
  • 数据库:新增物理表 BS_HISSyncTask 及 (HospCode, Status)、(TaskID) 索引;BS_HISSyncConfig 增加 AsyncFlag 列并回填 'Y'。
  • 脚本/注册:新增 scripts/insert_his_sync_task_interface.sql(注册 02010089)、scripts/alter_his_sync_config_asyncflag.sql。
  • 前端:frontend/src/api/hisData.ts 增加 asyncFlag 入参与进度查询方法;frontend/src/pages/HIS/DataSync.tsx 增加受理-轮询流程(复用现有 Progress 组件)。
  • 运维配置:frontend/nginx.conf 超时与缓冲参数补全;需同步核对中间转发器 172.16.1.6:8082 的超时设置。
  • 不在本次范围:费用明细的前端查询页面;02010068 的独立调度改造(复用 M3 成果即可受益);任务历史归档与清理策略。
  • 部署要求:需重新编译 User.BSHISSyncTask、User.BSHISSyncConfig、src.DRG.HISData.* 后生效;生产 IRIS 需允许 JOB 后台进程。