Files
insar-management-system-v2/docs/SBAS_SYSTEM_INTEGRATION_AUDIT_20260406.md
T

360 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SBAS 系统集成与数据管理审计报告
更新日期:2026-04-06
## 1. 审计范围
本次审计聚焦三件事:
- 当前 ISCE2 SBAS 实验是否已经真实读取并使用精密轨道
- 现有系统的数据管理方案是否适合承接 SBAS/PS-InSAR 生产口
- 如果后续要把实验方案嵌入系统,推荐怎样分阶段落地
本报告基于当前仓库实现与已成功的实验产物,不涉及对现有 D-InSAR 生产链的破坏性修改。
## 2. 结论摘要
- 结论 1:当前 SBAS 实验已经真实读取并使用精密轨道,不只是“数据库里有轨道路径”。
- 结论 2:当前系统可以完成 PS/SBAS 选片和实验产物生成,但还不能把 `psinsar` 产物作为正式生产结果注册、编目、健康检查和发布。
- 结论 3:当前数据管理整体偏“路径驱动”,原始数据身份、存储位置、运行产物三层边界不够清晰,因此用户会感到“数据管理比较松散”。
- 结论 4:轨道管理反而是当前较完整的一块,已经具备源目录扫描、池同步、一致性检查和数据库状态统计能力。
## 3. 审计发现
### P0 / 高优先级
#### 3.1 结果编目和发布入口仍然是 D-InSAR 专用,`psinsar` 实验产物无法直接接入系统
证据:
- `backend/app/services/result_catalog_service.py:707-713`
- `_load_manifest()` 只接受 `product_type == dinsar`
- `backend/app/services/result_catalog_service.py:750-753`
- 即使读入 manifest,也把 `product_type` 固定写成 `dinsar`
- `backend/app/routers/dinsar_products.py:107-140`
- 现有编目 API 和后台任务只暴露 `/dinsar-products/*`
- `backend/app/services/health_service.py:124-170`
- 结果目录健康检查只统计 `catalog_name == dinsar`
- `experiments/isce2_sbas_timeseries/scratch/lt1a_strip1_hh_descending_e123p3_n46p1/publish/mintpy_sbas_unified_v1/manifest.json:2-9`
- 当前实验成功产物的 manifest 是 `schema_version = psinsar.publish.v1``catalog_name = psinsar`
影响:
- 实验已经能产出发布级 bundle,但系统当前不会把它识别为正式产品
- 不能复用现有结果页、目录重建、健康检查、产品详情接口
- 后续如果直接“硬塞”进 D-InSAR 目录,会污染现有 D-InSAR 语义
建议:
- Phase 1 不要新建一套完全独立的产品表,继续复用 `result_products` / `result_assets`
- 但必须让 catalog 服务显式支持 `catalog_name = psinsar`
- 最小可行改造是新增 `psinsar` manifest 解析路径,或把当前 catalog service 抽象成多 catalog 分发器
#### 3.2 `ps_task_batches` / `ps_task_items` 目前只是选片快照,不是生产记录
证据:
- `backend/app/models/orm.py:516-550`
- `PsTaskBatchORM` / `PsTaskItemORM` 只保存批次、`file_path`、日期、极化、是否有轨道和状态
- `backend/app/routers/task_batches.py:281-320`
- 创建 `/task-batches/ps` 时只是把选中的影像元数据写入 `ps_task_items`
- `backend/app/routers/pairing.py:124-147`
- 现有 `find-ps-timeseries` 只负责找 stack
- `backend/app/services/spatial_service.py:444-481`
- `find_ps_timeseries_data()` 只返回按轨道方向分组的影像栈
- `backend/app/services/job_handlers.py:306-321`
-`PS_STACK` 的后台处理目前只是复制选中的影像路径
影响:
- 系统里没有“某次 SBAS 生产运行”的业务主记录
- 无法稳定记录 `work_dir``publish_dir`、运行环境、参数版本、DEM、轨道来源、水体掩膜来源
- 无法形成真正可追溯、可重跑、可审计的生产口
建议:
- 新增业务表 `ps_timeseries_runs`
- 保留 `ps_task_batches` 作为“输入栈定义”
- 把真正的处理运行、产物发布、失败重试、步骤状态全部挂到 `ps_timeseries_runs + workflow_runs`
#### 3.3 数据身份与存储路径耦合过深,迁移和重构成本偏高
证据:
- `backend/app/models/orm.py:22-40`
- `RadarDataORM` 直接保存 `file_path``orbit_file_path``preview_cache_path`
- `backend/app/models/orm.py:82-101`
- `ResultProductORM` 直接保存 `publish_dir``manifest_path``source_primary_path``primary_asset_path`
- `backend/app/models/orm.py:182-195`
- `ResultAssetORM` 保存 `absolute_path`
- `backend/app/services/data_service.py:621-668`
- `unique_id` 通过 `os.path.relpath()` 生成,并按 `unique_id` 做 upsert
影响:
- 数据身份会受存储根目录变化影响
- Windows 根目录变更、WSL 路径调整、NAS 迁移时,数据库主身份和存储位置语义混在一起
- 产物迁移到正式发布目录后,历史绝对路径会变成系统耦合点
建议:
- 把“数据身份”和“存储位置”拆开
- 原始影像层至少补充稳定的 `scene_uid``product_uid`
- 结果层至少补充稳定的 `run_id` / `product_id` 业务主键,把绝对路径退化为可替换的存储定位信息
### P1 / 中优先级
#### 3.4 原始影像与轨道的关联粒度偏粗,缺少轨道版本与来源追踪
证据:
- `backend/app/services/data_service.py:611-612`
- 影像是否有轨道仅按 `(satellite, imaging_date)` 关联
- `backend/app/services/data_service.py:688-692`
- 后续补关联时也是按同一键更新
影响:
- 当同一天存在多个候选轨道版本时,数据库层无法区分来源和版本
- 无法在结果层明确回答“本次 SBAS 用的是哪份轨道文件、其 checksum 是多少、来自 source 目录还是 ISCE2 pool”
建议:
- 最小可行做法:在 `RadarDataORM` 或新表中增加
- `orbit_stem`
- `orbit_checksum`
- `orbit_source_type`
- `orbit_pool_path`
- 更完整做法:单独建 `orbit_assets` / `orbit_bindings`
#### 3.5 数据扫描服务职责过重,扫描、轨道同步、预览缓存、数据库写入耦合在一起
证据:
- `backend/app/services/data_service.py:426-463`
- 扫描原始轨道并同步 ENVI / ISCE2 池
- `backend/app/services/data_service.py:568-699`
- 同一流程里完成影像元数据读取、轨道关联、数据库 upsert
- `backend/app/services/data_service.py:709-739`
- 后面又继续做缓存重建候选收集
影响:
- 这个服务变成“总装配间”,测试和回归都更困难
- 后续要引入 SBAS 生产口时,很容易继续把更多责任塞进同一个服务
建议:
- 拆分为至少四块:
- `radar_inventory_service`
- `orbit_inventory_service`
- `radar_catalog_service`
- `preview_cache_service`
#### 3.6 Windows/WSL 双路径模型是当前现实,但需要收口到专门的路径层
证据:
- `backend/app/config.py:150-186`
- 同时维护 Windows 轨道池、DEM、IDL、WSL distro、WSL Python 等配置
- `experiments/isce2_sbas_timeseries/scripts/build_lt1_stack_prep.py:140-149`
- 实验准备阶段会解析 orbit XML
- `experiments/isce2_sbas_timeseries/scripts/build_lt1_stack_prep.py:171-193`
- 同时生成 Windows 路径和 WSL 路径
- `experiments/isce2_sbas_timeseries/scripts/materialize_lt1_stack_scenes.py:98-103`
- 物化阶段直接把 orbit XML 传给 ISCE2 sensor
影响:
- 当前方案能跑通,但如果没有统一的路径转换层,后续每个服务都可能自己拼接 `/mnt/*`
- 这会继续加重“数据管理松散”的体感
建议:
- 保留当前双路径现实,不要硬回避
- 但把路径转换统一收敛到 `timeseries_paths.py` 或类似组件
- 生产口只暴露业务字段,不让上层 UI 和业务逻辑直接感知 `/mnt/z``F:\`
### P2 / 正向发现
#### 3.7 轨道管理是当前系统里相对成熟的一块
证据:
- `backend/app/services/data_service.py:426-463`
- 已有源目录扫描与 ENVI / ISCE2 轨道池同步
- `backend/app/routers/orbit.py:27-108`
- 已有数据库统计、池一致性检查、缺口汇总
结论:
- 不需要为 SBAS 重新发明一套轨道管理
- 更合理的方向是复用现有轨道池和一致性检查能力,再补生产级 provenance
## 4. 关于“现在实验读取精密轨道了吗”
答案:是,已经读取,而且已进入实际处理链。
证据链如下:
1. 轨道解析入口:
- `backend/app/isce2_pipeline/lt1_input_resolver.py:165-201`
- `ensure_lt1_orbit_xml()` 会优先取已有 XML,找不到才从 LT-1 轨道 txt 生成 XML
2. Stack 准备阶段:
- `experiments/isce2_sbas_timeseries/scripts/build_lt1_stack_prep.py:140-149`
- 每景影像都调用 `ensure_lt1_orbit_xml()`
3. Stack 物化阶段:
- `experiments/isce2_sbas_timeseries/scripts/materialize_lt1_stack_scenes.py:98-103`
- `sensor.orbitFile = orbit_xml`
4. 实验 manifest 证据:
- `experiments/isce2_sbas_timeseries/scratch/lt1a_strip1_hh_descending_e123p3_n46p1/stack_input_manifest.json:92-95`
- `experiments/isce2_sbas_timeseries/scratch/lt1a_strip1_hh_descending_e123p3_n46p1/stack_input_manifest.json:123-126`
- `experiments/isce2_sbas_timeseries/scratch/lt1a_strip1_hh_descending_e123p3_n46p1/stack_input_manifest.json:154-157`
- manifest 已明确记录 `D:\\orbit_pools\\isce2\\LT1A_GpsData_GAS_C_*.xml`
5. 运行日志证据:
- `experiments/isce2_sbas_timeseries/scratch/lt1a_strip1_hh_descending_e123p3_n46p1/stack_work/logs/run_01_reference.log:18`
- `experiments/isce2_sbas_timeseries/scratch/lt1a_strip1_hh_descending_e123p3_n46p1/stack_work/logs/run_03_geo2rdr_coarseResamp.log:6`
- 日志中已出现 `Orbit interpolation method: hermite`
结论补充:
- 当前 SBAS 实验使用的是 ISCE2 轨道池中的 XML 精轨
- 因此“精轨是否已读入”这件事在实验层已经成立
- 真正缺的不是“有没有轨道”,而是“系统如何把这次运行及其轨道 provenance 规范地登记为生产记录”
## 5. 集成设计建议
### 5.1 集成边界
当前最合理的系统集成边界不是 MintPy 运行目录,而是发布级 bundle:
- 入口文件:`manifest.json`
- 目录结构:`assets/``preview/``metadata/`
这与现有产品规范一致:
- `docs/ISCE2_SBAS_PRODUCT_SPEC.md:69-88`
因此:
- 不要直接注册 `stack_work/mintpy_sbas_*`
- 要注册 `publish/.../manifest.json` 所代表的一整个 bundle
### 5.2 推荐最小落地架构
#### 层 1:规划层,继续复用现有能力
- 继续使用 `find-ps-timeseries`
- 继续使用 `ps_task_batches` / `ps_task_items`
- 其职责只保留为“选片与栈定义”
#### 层 2:生产层,新增业务主记录
新增 `ps_timeseries_runs`,至少包含:
- `run_id`
- `batch_id`
- `catalog_name`
- `engine_code`
- `processor_code`
- `env_name`
- `wsl_distro`
- `work_dir`
- `publish_dir`
- `manifest_path`
- `reference_date`
- `direction`
- `params_json`
- `summary_json`
- `orbit_summary_json`
- `dem_path`
- `water_mask_source`
- `status`
- `error_message`
- `started_at`
- `ended_at`
#### 层 3:编目层,扩展现有结果目录
不要单独再造一套产品表,继续复用:
- `result_products`
- `result_assets`
- `result_issues`
但要新增 `psinsar` catalog 入口,支持:
- 解析 `psinsar.publish.v1`
- 注册 `catalog_name = psinsar`
- 单独的 catalog status / rebuild / health-check
#### 层 4:接口层
建议新增:
- `POST /timeseries-production/runs`
- `GET /timeseries-production/runs`
- `GET /timeseries-production/runs/{run_id}`
- `POST /timeseries-production/runs/{run_id}/retry-step`
- `GET /ps-products`
- `GET /ps-products/{product_id}`
- `POST /ps-products/rebuild-catalog`
### 5.3 与当前设计文档的一致性
当前仓库里的 SBAS 设计文档已经提前写出了这条路线:
- `docs/ISCE2_SBAS_TIMESERIES_DESIGN.md:227`
- 建议新增 `ps_timeseries_runs`
- `docs/ISCE2_SBAS_TIMESERIES_DESIGN.md:292-296`
- 建议新增 SBAS 相关 job types
- `docs/ISCE2_SBAS_TIMESERIES_DESIGN.md:306-313`
- 建议新增 `timeseries_production` / `ps_products` / `psinsar_catalog_service`
- `docs/ISCE2_SBAS_TIMESERIES_DESIGN.md:563-575`
- TODO 中已明确列出 ORM、路由、job handler、catalog 扩展和健康检查
所以本次审计的判断不是与现有设计冲突,而是说明:
- 实验层已经坐实
- 代码现实也证明下一步确实该进入“生产层与 catalog 层补齐”
## 6. 建议 TODO
### 6.1 立即做
- [ ] 新增 `ps_timeseries_runs` ORM / schema / migration
- [ ] 新增 `timeseries_production` router
- [ ] 新增 `PUBLISH_PSINSAR_PRODUCTS` 及相关 job handlers
- [ ] 让 catalog 服务支持 `psinsar.publish.v1`
- [ ]`publish/.../manifest.json` 作为唯一注册入口
### 6.2 紧接着做
- [ ]`ps_timeseries_runs` 记录 DEM、轨道、水体掩膜、运行环境版本
- [ ] 给轨道绑定补 provenance 字段或单独轨道资产表
- [ ] 把 Windows/WSL 路径转换收敛到独立路径服务
- [ ]`psinsar` 增加 catalog health-check 与 rebuild
### 6.3 暂缓做
- [ ] 不要现在就改动现有 D-InSAR 生产链
- [ ] 不要把 SBAS 运行目录直接暴露为产品目录
- [ ] 不要为了 SBAS 先拆掉现有 `result_products`
## 7. 审计结论
如果现在问“SBAS 能不能开始往系统里接”,答案是:
- 能,但应该先接“发布 bundle + 生产记录 + psinsar catalog”
- 不能直接把实验目录粗暴塞进现有 D-InSAR 产品体系
如果现在问“系统的数据管理为什么显得松散”,核心原因是:
- 原始数据身份、物理存储路径、生产产物目录三层目前还没有彻底分开
如果现在问“下一步最值得做什么”,答案是:
- 先把 `ps_timeseries_runs + psinsar catalog` 这两个缺口补上
这样既不会动坏现有 D-InSAR 生产,又能把已经验证成功的 SBAS 实验稳稳接成系统能力。