13 KiB
13 KiB
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
- 即使读入 manifest,也把
backend/app/routers/dinsar_products.py:107-140- 现有编目 API 和后台任务只暴露
/dinsar-products/*
- 现有编目 API 和后台任务只暴露
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
- 当前实验成功产物的 manifest 是
影响:
- 实验已经能产出发布级 bundle,但系统当前不会把它识别为正式产品
- 不能复用现有结果页、目录重建、健康检查、产品详情接口
- 后续如果直接“硬塞”进 D-InSAR 目录,会污染现有 D-InSAR 语义
建议:
- Phase 1 不要新建一套完全独立的产品表,继续复用
result_products/result_assets - 但必须让 catalog 服务显式支持
catalog_name = psinsar - 最小可行改造是新增
psinsarmanifest 解析路径,或把当前 catalog service 抽象成多 catalog 分发器
3.2 ps_task_batches / ps_task_items 目前只是选片快照,不是生产记录
证据:
backend/app/models/orm.py:516-550PsTaskBatchORM/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-481find_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-40RadarDataORM直接保存file_path、orbit_file_path、preview_cache_path
backend/app/models/orm.py:82-101ResultProductORM直接保存publish_dir、manifest_path、source_primary_path、primary_asset_path
backend/app/models/orm.py:182-195ResultAssetORM保存absolute_path
backend/app/services/data_service.py:621-668unique_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_stemorbit_checksumorbit_source_typeorbit_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_serviceorbit_inventory_serviceradar_catalog_servicepreview_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. 关于“现在实验读取精密轨道了吗”
答案:是,已经读取,而且已进入实际处理链。
证据链如下:
- 轨道解析入口:
backend/app/isce2_pipeline/lt1_input_resolver.py:165-201ensure_lt1_orbit_xml()会优先取已有 XML,找不到才从 LT-1 轨道 txt 生成 XML
- Stack 准备阶段:
experiments/isce2_sbas_timeseries/scripts/build_lt1_stack_prep.py:140-149- 每景影像都调用
ensure_lt1_orbit_xml()
- Stack 物化阶段:
experiments/isce2_sbas_timeseries/scripts/materialize_lt1_stack_scenes.py:98-103sensor.orbitFile = orbit_xml
- 实验 manifest 证据:
experiments/isce2_sbas_timeseries/scratch/lt1a_strip1_hh_descending_e123p3_n46p1/stack_input_manifest.json:92-95experiments/isce2_sbas_timeseries/scratch/lt1a_strip1_hh_descending_e123p3_n46p1/stack_input_manifest.json:123-126experiments/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
- 运行日志证据:
experiments/isce2_sbas_timeseries/scratch/lt1a_strip1_hh_descending_e123p3_n46p1/stack_work/logs/run_01_reference.log:18experiments/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_idbatch_idcatalog_nameengine_codeprocessor_codeenv_namewsl_distrowork_dirpublish_dirmanifest_pathreference_datedirectionparams_jsonsummary_jsonorbit_summary_jsondem_pathwater_mask_sourcestatuserror_messagestarted_atended_at
层 3:编目层,扩展现有结果目录
不要单独再造一套产品表,继续复用:
result_productsresult_assetsresult_issues
但要新增 psinsar catalog 入口,支持:
- 解析
psinsar.publish.v1 - 注册
catalog_name = psinsar - 单独的 catalog status / rebuild / health-check
层 4:接口层
建议新增:
POST /timeseries-production/runsGET /timeseries-production/runsGET /timeseries-production/runs/{run_id}POST /timeseries-production/runs/{run_id}/retry-stepGET /ps-productsGET /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_runsORM / schema / migration - 新增
timeseries_productionrouter - 新增
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 实验稳稳接成系统能力。