Skip to content

refactor(api): 审计报告整改 #11/#12/#13 — ProcessUtils 拆分、null 收敛、Vos 改名 - #14

Merged
88fantasy merged 49 commits into
mainfrom
refactor/ui-v2
Jun 13, 2026
Merged

refactor(api): 审计报告整改 #11/#12/#13 — ProcessUtils 拆分、null 收敛、Vos 改名#14
88fantasy merged 49 commits into
mainfrom
refactor/ui-v2

Conversation

@88fantasy

Copy link
Copy Markdown
Owner

Summary

  • feat(cli): create node 支持配置模式(-c)与条件化 DAG #11 ProcessUtils god class 拆分:按职责拆为 5 个静态工具类(ServiceConfigUtils / ServiceCommandUtils / ServiceLifecycleUtils / ServiceAlertUtils / WorkerFanOutUtils),getExceptionMessage 并入 CommonUtils,原 ProcessUtils.java 删除。
  • refactor: 清除后端 Java 代码告警(5 模块 / 8 类告警) #12 return null 收敛:将可安全改造的子集(ServletUtils / UniEngineServiceImpl / UploadTempFileService / ClusterUserGroupServiceImpl / AlertHistoryGateway / K8sServiceInstanceService)改为返回 Optional<T> 或空集合。REST 信封契约、Map.get 语义、Void lambda 等不纳入。
  • fix(security): 优化 CsrfTokenInterceptor 校验逻辑 #13 Vos 历史命名统一:7 个类改名(VosDdLServiceMeta→PhysicalDdlServiceMetaVosProductService/Impl→PhysicalProductService/ImplExtRepoVosInstallController→ExtRepoPhysicalInstallControllerVosProductDeployDAGBuildContext→ProductDeployDAGBuildContextVosProductCmdSrvMappingContext→ProductCmdSrvMappingContext);方法/字段名同步改为 Physical 对应名;2 个 bean 名字符串同步改。外部契约(URL path、${ROOT.VosManager.*} 占位符、x-vos-* 鉴权头、vos_ddl 目录、用户文案、SQL、前端)零改动。

所有改动均为行为不变的结构重构,10 个独立 commit,每个均通过编译 + 37 单元测试。

Commits (本 PR 新增,截至审计整改相关)

commit 内容
70a3f5d5 拆 ProcessUtils — ServiceConfigUtils (#11)
d56562c0 拆 ProcessUtils — ServiceCommandUtils (#11)
774ec79d 拆 ProcessUtils — ServiceLifecycleUtils (#11)
12d9bafb 拆 ProcessUtils — ServiceAlertUtils (#11)
7e4eda0e 拆 ProcessUtils 完成并删除原类 (#11)
1aa8b679 ServletUtils → Optional (#12)
f2c6de69 其余 5 文件 null 收敛 (#12)
baaf4ab8 Vos 类改名 7 类 + 2 bean 名 (#13)
de15a766 Vos 方法/字段名统一 (#13)
9a788ef7 审计报告勾选 #11/#12/Vos 完成状态

Test plan

  • JAVA_HOME=$JH17 ./mvnw -pl datasophon-api -am compile -s ~/.m2/setting.xml -Dfrontend.skip=true — BUILD SUCCESS
  • ./mvnw -pl datasophon-api -am test ... -Dtest='!DataSophonMySQLStartupTest,!MetaUtilsTaskTest,!NexusUtilsTaskTest' — 37 tests, 0 failures
  • rg -i '\bvos[A-Z]' 及方法级守卫 grep — 白名单外 0 残留
  • rg 'ProcessUtils\.' datasophon-api/src — 0 代码引用

88fantasy and others added 30 commits June 6, 2026 21:22
- 新增 FrameV2Controller,暴露框架+嵌套服务列表、删除、DDL 读写 4 个 V2 接口
- 新增 Frame 页面:按 frameCode 分 Tab,物理机/K8s Segmented 切换,支持删除与 DDL 在线编辑(react-simple-code-editor + highlight.js)
- 集群框架作为顶级菜单与集群管理并列,不再是二级子菜单
- 同步新增 Cluster(主机/服务/服务实例)、User 管理页及对应 V2 接口

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…p + OpenAI SSE)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ai-agent:
- 从 @anthropic-ai/sdk 直接调用切换为 @anthropic-ai/claude-agent-sdk query()
- 新增 types.ts 统一 ChatMessage 类型
- 支持自定义 gateway(ANTHROPIC_BASE_URL + ANTHROPIC_AUTH_TOKEN)
- 新增 /debug 端点验证 gateway 连通性
- 默认模型改为 qwen3.7-plus

api:
- CsrfTokenInterceptor 从有状态 Map 改为无状态 HMAC-SHA256 token
  省去 ConcurrentHashMap,支持多实例部署不共享内存
- ChatbotV2Controller 支持 AI agent 地址配置
- AiProperties 新增 agentUrl 字段

ui-v2:
- service.ts 新增 listConfigVersions / getServiceConfig / saveServiceConfig 接口
- typings.d.ts 补充 ConfigField 等类型声明
- ServiceInstance Setting 页面完善配置版本切换逻辑
- chatbot service/index 接入新 API 参数
- Frame 布局样式调整
- agent.ts: mkdirSync 确保 WORKDIR 存在,修复 spawn ENOENT 导致的 "failed to launch" 错误
- agent.ts: 监听 assistant/user message 事件,提取 tool_use/tool_result,以 base64 嵌入 SSE chunk 传给前端
- agent.ts: 新增 WebFetch 到 allowedTools;默认模型改回 claude-sonnet-4-6
- ui-v2 chatbot: 新增 ToolCalls.tsx 组件,展示工具调用名称、参数、结果与耗时
- ui-v2 chatbot: index.tsx 解析 <tool-call> base64 片段,拆分 text/tool 消息片段渲染
- AiProperties: 补充默认模型配置
后端:
- 新增 ClusterK8sV2Controller (GET namespace 列表/实例列表/资源类型/资源列表)
- 新增 ClusterK8sConfigV2Controller (GET versions/getById, POST update)
- Spotless 重排 CsrfTokenInterceptor import 顺序

前端:
- ClusterLayout: archType=k8s 时渲染 namespace→实例两层菜单 + 3s 轮询
- ServiceInstance: K8s 时渲染动态资源 Tab (listK8sResourceTypes)
- K8sResource.tsx: 5 类 K8s 资源 ProTable (Pod/Service/Deployment/Ingress/ConfigMap)
- HelmEditor.tsx: Monaco 双栏编辑器 (左 deltaValues 可编辑 + 右合并预览只读)
- SettingTab: 提取 PhysicalSettingContent, 按 archType 分流到 HelmEditor/物理 ProForm
- yamlMerge.ts: Helm values 深合并 (js-yaml + structuredClone, 数组替换语义)
- yamlMerge.test.ts: 5 单测全绿
- 新增 K8s 类型定义 (K8sNamespace/K8sServiceInstanceVO/K8sInstanceValues) 和 7 个 API 函数
- 引入 @monaco-editor/react 4.7.0 + monaco-editor 0.55.1 + js-yaml 4.2.0
- Monaco 由 utoopack 打包为 1.5MB 异步 chunk, 无需 CDN 配置

验证: lint 预存 SVG err (非本切片引入), test 50/50 全绿, build 无错
后端:
- ClusterServiceRoleInstanceV2Controller 新增角色组列表、添加/分配角色组接口
- ClusterYarnQueueV2Controller 新增 Yarn 队列 CRUD 接口

前端:
- ServiceInstance/index.tsx 增加日志按钮、跳转 Queue 页
- ServiceInstance/Instance.tsx 重构角色实例列表,接入添加/分配角色组弹窗
- 新增 AddRoleGroupModal / AssignRoleGroupModal / LogModal 组件
- 新增 Queue/index.tsx + Queue/BuildOrEditModal.tsx 队列管理页
- service.ts / typings.d.ts 补充对应 API 封装与类型定义

docs: 更新 ui-v2-migration-plan.md 进度表(4b Step 5-6 完成)
5a: ClusterAlertV2Controller(11 端点) + AlarmManage Tabs 容器/Group/Metric ProTable + 路由 /cluster/:clusterId/alarm
5b: ClusterNodeLabelV2Controller(4 端点) + AssignLabelModal/LabelManageModal + HostManage 工具栏「标签管理」按钮 + 批量「分配标签」
… + 侧栏入口)

后端: ClusterDagV2Controller(command/list + dag/{dagId}/graph + dag/{dagId}/redeploy)
前端: dag.ts(3 API) + DagCommand/DagGraph 类型 + Cluster/Command ProTable(8列+2s轮询) + 路由+侧栏「命令历史」菜单项
- 新增 Cluster/DagGraph/ 页面(layout:false 全屏,window.open 新窗口)
  - DataProcessingDagNode: x6-react-shape 节点,物理/K8s 双渲染分支
    节点级日志由多源多 Tab → 单文本 Modal(getHostCommandLog)
  - antvUtils / dagEvent / dagStatus: 从旧版迁移的共享工具
  - index.tsx: Graph 初始化 + LR 拓扑布局 + 3s 轮询 + redeploy/调度日志按钮
- 路由 /cluster/:clusterId/dag/:dagId 移出 ClusterLayout,设 layout:false
- 顺带修复 tsc 全量错误:
  - AlarmManage/index.tsx ClusterContext 默认导入
  - useRef<ActionType>() → useRef<ActionType|undefined>(undefined)
  - insert-css / lodash-es 补模块声明
  - login/Logo 无障碍 title + analyze 参数类型
  - app.tsx PageLoading 本地定义
  - User/Manage 路径大小写对齐
- 新增 ClusterDeployV2Controller(3 端点: tempfile/upload, valid-deployment-file, deploy)
- 新增 deploy.ts(uploadDeployFile / validateDeploymentFile / deployManifest)
- 新增 UploadManifestModal: ModalForm 上传清单 + 密码 + 校验 → 部署 → 跳 DAG 图
- 新增 ChunkedUploader.ts: spark-md5 同步 hash + 分批上传 + 秒传(uploadType=2) + 断点续传(is-chunk-uploaded)
- 新增 UploadPackageModal: 3 步 StepsForm(上传配置文件 → 分片上传部署包 → 导入进度轮询)
…AddServiceModal)

- 新增 ClusterAddServiceV2Controller: list-newest / check-dependency / service-roles /
  non-master-roles / hosts / role-host-mapping / config-from-ddl / save-config / install
  (install 合并 v1 两段式 generateGenericInstallCommand + redeploy,一次返回 dagId)
- 新增 addService.ts(9 API 封装) + typings.d.ts 新增 ManifestContext / FrameService /
  FrameServiceRole / RoleHostMapping
- 新增 AddServiceModal(6 步 StepsForm) + StepManifest / StepSelectService / StepRoleAssign /
  StepConfig(forceRender=true) / StepInstall
- ClusterLayout "添加服务" 按钮从 disabled 占位改为打开向导
- fix: package.json 显式加 vite@^7 修复 vitest 4 启动失败(Umi peer 拉入 vite 4.5.2 而
  vitest 4 需要 vite ≥6 的 module-runner 导出)
88fantasy added 19 commits June 11, 2026 16:34
后端:将 /v2/logout 加入 CsrfTokenInterceptor 豁免列表。
登出不携带敏感写操作,session 已由 LoginHandlerInterceptor 验证,
即使 CSRF 攻击仅能强制登出用户,无数据泄露风险,豁免是业界惯例。

前端:loginOut 包裹 try-catch 并传 skipErrorHandler: true,
确保服务端请求失败(如旧 session 缺少 XSRF-TOKEN cookie)时
客户端状态仍被清理并跳转到登录页。
- #1 GlobalVariables.getVariables 返回锁内快照,putValue 与 put 统一互斥,
  堵住 live map 逃逸进 gRPC 序列化导致的 CME/半填充脏读;附并发单测
- #2 巡检解耦:checkServiceRoles/checkHosts 的阻塞 gRPC/Prometheus 调用
  fan-out 到有界 masterExecutor,池满退化为调用线程串行;statusRunner
  巡检 deadline 由 90s 收紧为 30s(executeCmd 新增可指定 deadline 重载)
- #3 角色实例分页列表 N+1:roleGroup 去重后 listByIds 一次查回
- #4 ServletUtils/ClusterNodeLabelServiceImpl 吞异常改 logger.error

验证:GlobalVariablesTest 3/3;datasophon-api 单测除
DataSophonMySQLStartupTest(套件内 18081 端口互抢的既有问题,单跑 4/4 通过)
外全部通过
- #5 generateClusterVariable 注册事务回滚补偿:正常路径立即写内存
  (同事务内读取依赖新值),回滚时恢复写前值,DB 与内存重新对齐
  (未采用报告建议的 afterCommit 推迟写——strategy 类存在同事务写后读依赖)
- #6 hdfsEcMethond/syncUserGroupToHosts 逐主机 gRPC 改 masterExecutor
  fan-out 并行,池满退化为调用线程串行
- #7 saveDAG 复用入口 serviceList 消除逐节点查询,ServiceInfo 每节点
  解析一次;doGenerateInstallCmd 角色实例一次查回替代角色×主机查询;
  setHosts/K8s doGenerateExecCmd 消除重复查询;顺带修复 saveDAG 中
  hostCommands 排序结果被丢弃的问题
- #8 getStub 改 compute 校验 Channel 状态,失效原子重建;
  onWorkerOffline 补 awaitTermination + shutdownNow 兜底
- #9 抽 invokeCommandsAfterCommit 模板,消除三处复制粘贴
- #10 四大 Impl(Physical/ServiceInstall/HostInstall/RoleInstance)
  转 @requiredargsconstructor 构造器注入;新增 lombok.config 复制
  @Qualifier/@lazy 到构造器参数;环上依赖以 @lazy 打破
  (rackService→roleInstance→frameService→ddlMeta 等多条既有环)
- #11(拆 ProcessUtils)暂缓:40+ 调用文件的纯结构重构,留待单独 PR

验证:DataSophonApplicationServerTest 上下文启动 3/3(覆盖新装配),
全量单测除既有端口互抢问题(单跑 4/4)外全部通过
- JschUtils.execForStr 轮询加 10 分钟超时上限,远端命令不结束时
  不再永久阻塞调用线程(消除 H2 的放大器)
- K8sServiceImpl 的 nexus-registry-secret 改为命名静态常量
- 暂缓项已在审计报告标注理由:return null 改 Optional 涉及公共 API
  契约;Vos 改名 93 处含 bean 名字符串引用;#14 ProblemDetail 属
  架构选择(报告自评优先级最低)
- 勘误:decideEnableKerberos 仍被 8 个 strategy 引用,非死代码

验证:全量单测与前两批基线一致(仅既有端口互抢测试失败,单跑通过)
7 个历史 Vos 命名的类改名(行为不变,仅 Java 内部标识符):
- VosDdLServiceMeta → PhysicalDdlServiceMeta(并修正 DdL 大小写畸形)
- VosProductService/Impl → PhysicalProductService/Impl
- ExtRepoVosInstallController → ExtRepoPhysicalInstallController
- VosProductDeployDAGBuildContext → ProductDeployDAGBuildContext
- VosProductCmdSrvMappingContext → ProductCmdSrvMappingContext
- bean 名 vosProductService → physicalProductService
- bean 名 vosProductInstallService → physicalProductInstallService

外部契约保持不变:@RequestMapping path、SQL、meta、前端均未动。
编译 + 37 测试通过。
方法名(Java 标识符,外部 path/契约不变):
- getServiceVosDdl/updateServiceVosDdl → getServicePhysicalDdl/updateServicePhysicalDdl
- validVosDdlDependency/parseVosDdlServiceMeta/addVosService → Physical 对应名
- getVosDdlServices(Lombok getter)→ getPhysicalDdlServices(字段 vosDdlServices → physicalDdlServices)
- getVosServiceRoleRuntimeLog → getPhysicalServiceRoleRuntimeLog(@PostMapping path 保留)
- MetaStorage.removeVosMeta → removePhysicalMeta(worker 零引用,已核查)

字段/局部变量:
- vosProductActionService → physicalProductActionService(4 文件)
- vosProductService/vosExtRepoInstallService → physical 对应名
- MetaUtils 局部变量 vosDdlDir → physicalDdlDir;同名 vosDdLServiceMeta 按分支拆为
  physicalDdlServiceMetas / k8sDdlServiceMetas

白名单保留:${ROOT.VosManager.*} 占位符、x-vos-* 鉴权头、vos_ddl 目录、
NAMESPACE="vos"、Swagger @Tag/title、用户文案、URL path、VOS DDL javadoc 术语。
编译 + 37 测试通过。
- #11 拆分 ProcessUtils:[-]→[x],注明 5 个静态工具类拆分结果
- #12 return null 收敛:[-]→[x],注明纳入/排除清单
- #13 杂项:Vos 改名从暂缓改为已完成,注明白名单
- 计划文件 Phase C1/C2/D 勾选完成
@88fantasy
88fantasy merged commit 0b58b5c into main Jun 13, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant