Files
starRiverProperty/docs/architecture/对外接口不变-走查任务与状态.md
hpd840321 7b2bd307f1 Initial commit: reorganized source tree
- backend/: 13 Maven modules (cw-elevator-application, cloudwalk-cloud, intelligent-cwoscomponent, ninca-crk, etc.)
- frontend/: 4 Vue projects (elevator-front, cwos-portal, alarm-front, front_acs) + decompiled + scripts
- scripts/: build, test-env, tools (Docker Compose, service templates, API parity)
- docs/: AGENTS.md, superpowers specs, architecture docs
- .gitignore: standard Java/Maven exclusions

Moved from legacy maven-*/ root layout to backend/ organized structure.
2026-05-09 09:56:45 +08:00

21 KiB
Raw Permalink Blame History

对外接口不变:走查任务与状态

依据对外接口不变-远程调用与性能优化约定(§2 总原则、§3 场景、§4 优先级)。
走查代码根maven-cw-elevator-application/cw-elevator-application-service2026-04-24 静态走查)。
说明:下表「子任务数」指与约定相关的 RPC/可优化循环次数上界(随运行时数据规模变化);状态表示在不扩展 Feign/HTTP 契约前提下是否建议动代码。
排期(2026-04frontend/ 暂无可用前端工程;凡需改前端、登记页、物业管理端 UI 的迭代,暂跳过(详见 docs/README 当前排期与范围)。本文档仅跟踪电梯等服务端在约定下的走查与修正。


1. 总览表(子任务量 + 可修正 / 不可修正)

约定 § 代码锚点 子任务数(上界) 下一可修正动作(建议顺序) 不可修正或须前置确认
§3.1 ImageRuleRefServiceImpl#delete(约 575598 行) N = param.getIds().size()updateGroupPersonRef(每规则删后各 1 次) P0:全部 deleteById 完成后,对本轮涉及的 labelIdsorganizationIds 去重并集,调用 1 次 updateGroupPersonRef;为每次 RPC 增加 isSuccess 校验(与 §2.2 一致) 须图库/通行确认:合并调用是否为「刷新引用」语义、是否等价于当前 N 次效果;若不能确认则不得合并,仅可补返回值校验与日志(工作区走查与方案审核见 §6
§3.2 AcsPersonServiceImpl#delete P = param.getPersonIds().size()imageStorePersonService.delete P1 首轮已实施§8):elevatorRemoteBoundedExecutor 按批 invokeAll(默认并发 6),子线程 FeignThreadLocalUtil.callWithContext;遇失败整批后即返回 CloudwalkResult.fail(与原先顺序循环遇错即停一致,单条失败即取消同批其它在途 RPC 无批量 delete;同批内并行语义见 §8.1
§3.3 AcsPassRuleServiceImpl#listFloor F = passRuleResults.size()acsPersonService.page P1 首轮已实施§8):楼层 page 有界并行(默认 6),personTotals[] 按下标写回,列表顺序不变 禁止本地 count 替代 totalRowsRPC 上界仍为 F
§3.4 AcsPassRuleServiceImpl#addImageStore 内设备绑图库 D = deviceList.size()bindDeviceAndImageStore P1 首轮已实施§8):bind 有界并行;失败仍 rollbackImageStoreAfterBindFailure 后抛 ServiceException(与同批已绑设备竞态与顺序循环同类 无批量 bind
§3.5 AcsDeviceTaskServiceImpl#updateFloors 增删楼层远程调用墙钟上界仍分别为 AD 次;有界并行可缩短多楼层场景耗时(迭代 5,见 §9 内层 imageRuleRefService.delete 仍受 §3.1 冻结 时的 RPC 上界与语义约束;@Async("updateFloorsExecutor") 下背压与 catch 细粒度见 §7.3 / §9

2. 数量小结(便于排期)

类型 计数符号 含义
§3.1 可合并 RPC 由 N 降为 1(在语义确认后) 规则批量删除场景收益最大
§3.2 并行度 P 人员多 ID 删除
§3.3 并行度 F 楼层列表人数统计
§3.4 并行度 D 设备绑图库
§3.5 A + D 异步任务按层调用

3. 迭代规划与下一迭代范围(不改 HTTP/Feign 签名)

冻结范围(2026-04-25

说明
约定 §3.1 全范围 未取得图库/通行对 updateGroupPersonRef 语义确认前,不进行与该约定相关的任何代码修正与优化(含 合并 N→1 及 §6.4 所述isSuccess 校验小步),避免在无确认期分散实现与回滚成本。
恢复条件 图库书面或接口说明确认 + 在 约定文档 §3.1 文末回填对接人、日期;再按 §1 表拆分 PR(合并与返回值校验可分步)。
前端相关 仓库暂无可用前端;所有需改前端 / 登记页 / 物业端页面的迭代暂不排期、不执行(与本文服务端走查无冲突;产品方案中 UI 类阶段见 docs/README)。

迭代 3§3.5 updateFloors

字段 内容
状态 走查与首轮修正已完成(见 §7):getById 空防护、步骤级 CloudwalkResult 校验、keepAliveSeconds 绑定线程池。
约定锚点 §3.5 AcsDeviceTaskServiceImpl#updateFloors
暂缓项 楼层有界并行§9AbortPolicycatch 语义、其它见 §7.3

迭代 4P1:§3.2 / §3.3 / §3.4 + 统一有界池

字段 内容
状态 已实施(实现说明与语义边界见 §8)。
线程池 Bean elevatorRemoteBoundedExecutorElevatorRemoteIoExecutorConfig),配置前缀 ninca.elevator.remote-io.pool(默认 core=max=6queue=512CallerRunsPolicy)。updateFloorsExecutor 合并,避免异步任务与同步 RPC 抢同池。
公共能力 FeignThreadLocalUtil.callWithContextcw-elevator-application-common):子线程执行 Feign 前绑定/恢复 ThreadLocal 请求头。

迭代 5§3.5 updateFloors 楼层有界并行

字段 内容
状态 已实施(见 §9):增楼列表、删楼列表在各自阶段内以最多 6并发执行 add / addOnlyRule / delete 等;BIND_DEVICES 仍按原列表顺序、每层成功仍 +1 重读任务行,与纯串行「进度语义」一致;子线程 Feign 经 FeignThreadLocalUtilruleMapzoneId 时用 getOrDefault(…, "") 防 NPE。
不变更 §3.1 全冻结 期间未改 ImageRuleRefServiceImpl#deleteupdateGroupPersonRef 次数。

迭代 6 及以后(可选)

  • 调参 / 观测ninca.elevator.remote-io.pool 按环境压测;必要时为 updateFloors 批处理增加指标/耗时日志(不扩展 HTTP 响应)。
  • §3.1:图库确认后再评估合并 N→1 与(若允许)updateGroupPersonRefisSuccess 小步。

已完成回顾:迭代 1 — §5;迭代 2 — §6(§3.1 冻结);迭代 3 — §7;迭代 4 — §8;迭代 5 — §9


4. 文档维护

项目 内容
更新触发 ImageRuleRefServiceImpl#deleteAcsPersonServiceImpl#deleteAcsPassRuleServiceImpl#listFloor / #addImageStoreAcsDeviceTaskServiceImpl#updateFloors 任一处重构或签契约变更
结论回填 图库对 §3.1 的确认结论请写回 约定文档 §3.1 文末建议行(对接人 + 日期)

5. 迭代 1AcsPassRuleServiceImpl#listFloor 走查结论(§3.3 / §2.2

走查日期2026-04-25
代码位置maven-cw-elevator-application/.../passrule/impl/AcsPassRuleServiceImpl.java 方法 listFloor

检查项 现状 结论
zoneService.tree 返回值 已校验 zoneTree.isSuccess(),失败抛 ServiceException 通过
acsPersonService.page 返回值 循环内校验 page.isSuccess(),直接 page.getData()totalRows 不通过:违反约定 §2.2Feign 失败时 getData() 可能为 null,存在 NPE 风险,且可能把失败误当「0 人」
page.getData() 空指针 未防护 不通过:与上项合并修正
rowsOfPage 当前为 10,仅使用 totalRows 建议:改为 1(约定 §3.3:仅取总数,略减负载),不改变 HTTP 响应字段

评估结论(是否允许进入代码修正)通过进入修正 — 仅补充与 zoneTree 分支一致的失败处理及空数据防护,改变对外 JSON 字段语义;rowsOfPage=1 与现逻辑(只读 totalRows)等价。

代码修正(已应用,2026-04-25)AcsPassRuleServiceImpl#listFloor — 增加 page.isSuccess() 失败抛错、page.getData() 为空时 personNumber=0CloudwalkPageInfo(1,1) 仅取总数。

修正实施后:提交 e652eb3(分支 v0.11)。


6. 迭代 2ImageRuleRefServiceImpl#delete 与 §3.1 方案走查(仅评估,未改代码)

走查日期2026-04-25
目标:在全工作区定位**图库(intelligent 图库人员服务)通行规则(电梯应用本地)**相关代码,审核「合并 updateGroupPersonRef」方案是否需图库侧语义确认后方可实施。

6.1 图库 / 通行相关代码位置(工作区)

层级 路径/符号 职责
Feign 契约 maven-intelligent-cwoscomponent/intelligent-cwoscomponent-rest/.../feign/ImageStorePersonFeignClient.java POST .../updateGroupPersonRef,请求体 UpdateGroupPersonRefParam
DTO maven-intelligent-cwoscomponent/intelligent-cwoscomponent-interface/.../param/UpdateGroupPersonRefParam.java businessIdimageStoreIdpersonIdslabelIdsorganizationIds(可同时只填部分字段)
客户端封装 .../service/RestImageStorePersonServiceImpl.java 透传 Feign
电梯侧 §3.1 锚点 maven-cw-elevator-application/.../passrule/impl/ImageRuleRefServiceImpl.java 方法 delete(约 571605 行) param.getIds() 循环:listByParentRule → 收集子规则 includeLabels / includeOrganizationsdeleteByIdimageStorePersonService.updateGroupPersonRef(每删一条父规则 1 次 RPC
同文件其它 updateGroupPersonRef addOnlyRule(约 434439)、update 内分支(约 556562 新增/编辑规则后刷新;同样未校验 CloudwalkResult.isSuccess()
人员通行规则 maven-cw-elevator-application/.../person/impl/PersonRuleServiceImpl.java add / addVisitor / delete 末尾各 1 次 updateGroupPersonRef,入参以 personIds 为主(与 deletelabel/org 为主不同)
HTTP 入口 cw-elevator-application-web/.../AcsPassRuleController.java imageRuleRefService.delete
异步任务调用 AcsDeviceTaskServiceImpl#updateFloors 删楼层时多构造 deleteParam.setIds(Collections.singletonList(ruleId)) 逐层imageRuleRefService.delete;单次 delete 内仍可能 1 次或多次 updateGroupPersonRef(视该层 ids 数量)

说明:本仓库 intelligent 图库服务端的 updateGroupPersonRef 业务实现源码,仅能依据 DTO 与调用方推断语义;与图库/通行团队确认仍属 §3.1 前置条件。

6.2 当前 delete 行为摘要(与合并相关)

  • imageStoreId 来自 deviceImageStoreDao.getByBuildingId(param.getParentId()),整次批量删除共用同一图库。
  • 对每个待删父规则 id:先读该父规则下子规则的 label/org(子行若带 label 则 continue同一子行不会同时写入 org,与数据模型一致),再删父规则,再带着本轮 includeLabels / includeOrganizations 调图库刷新。
  • updateGroupPersonRef 的返回值未做 isSuccess 校验(违反约定 §2.2;与 getImageStorePerson 等分支不一致)。

6.3 约定中的「合并」方案审核

维度 结论
与现网 N 次调用的等价性 若图库侧语义为:在给定 imageStoreId 下,对传入的 labelIds / organizationIds 集合增量刷新或按维度重算引用(各维度独立、与顺序无关),则「删库前汇总所有待删父规则的子维度 → 去重并集 → 删库完成后 1 次 updateGroupPersonRef」与「每删一条父规则刷新其维度子集」在最终一致上通常等价。
必须向图库确认的风险 若远端实现为「以本次入参覆盖/裁剪图库可见范围」或依赖调用顺序产生副作用,则合并后的单次并集与 N 次子集递进可能不等价。约定文档 §3.1 所述「非破坏性刷新」即针对此。
personIdslabelIds/organizationIds 混用 PersonRuleServiceImplpersonIds 路径;ImageRuleRefServiceImpl#delete 走 label/org。合并方案不改变 delete 仅设 label/org 的现状;但若图库服务在未传 personIds 时对空列表有特殊含义,仍须一并确认。
空列表仍 RPC 当前循环在子规则为空时仍调用 updateGroupPersonRef(两列表皆空)。合并后是否跳过空并集可减少无效 RPC,但属于行为微调,若图库依赖「空刷」触发全量重算,须图库确认后再定。
不合并时的安全增量 在未获图库书面确认前,可为每次 updateGroupPersonRef 增加 isSuccess 校验 + 失败抛 ServiceException(及可选日志),不改变 RPC 次数;与约定「退化为循环调用 + 返回值校验」一致。

6.4 评估结论(是否允许进入 §3.1「合并」类代码修正)

  • 合并 N→1不允许在图库/通行确认前实施 — 与 §1 表及约定 §3.1 前置条件一致。
  • 仅返回值校验(及可选空并集跳过,若产品同意)允许作为独立小步 — 不依赖远端语义新假设,符合 §2.2。

图库确认建议提问(可复制):「对同一 imageStoreIdupdateGroupPersonRef 在仅设置 labelIdsorganizationIdspersonIds 为空)时,是否为按这些维度刷新人员引用不会将图库维度裁剪为仅等于本次入参?多次调用子集与单次调用并集是否在业务上等价?」

实施后回填:确认结论、对接人、日期写入 约定文档 §3.1 文末(见约定 §5)。

排期决策(2026-04-25:在取得图库确认前,冻结约定 §3.1 相关全部代码变更;下一迭代转 §3.5(见上文 「迭代 3」)。


7. 迭代 3AcsDeviceTaskServiceImpl#updateFloors 走查结论(§3.5

走查日期2026-04-25
代码位置cw-elevator-application-service/.../device/impl/AcsDeviceTaskServiceImpl.java 方法 updateFloors;线程池 .../common/UpdateFloorsTaskExecutor.java;配置 UpdateFloorsPoolPropertiesninca.update.floor.pool.*,默认 core=3、max=5、queue=100、AbortPolicy)。

7.1 调用链与 RPC 上界(与 §1 表对齐)

分支 行为 上界
增楼层 personRuleService.add imageRuleRefService.addOnlyRule,成功后 updateBingDevices addFloors.size()
删楼层 personRuleService.delete imageRuleRefService.delete(单 id 仅 DAO deleteByOrgAndLabel,成功后 updateBingDevices delFloorIds.size()
内层放大 imageRuleRefService.delete 仍受约定 §3.1 冻结影响(updateGroupPersonRef 多次);本迭代改该内层。 不变

入口AcsElevatorDeviceServiceImpl#bindingFloors / #bindingPerson 在插入任务行后同步调用 updateFloors;方法带 @Async,实际在 updateFloorsExecutor 线程执行;HTTP 已返回 taskId 后,异步内失败不会回写该 HTTP 响应(现网行为保持;运维依赖任务进度与日志)。

7.2 检查项与结论

检查项 现状(走查时) 结论
acsDeviceTaskDao.getById 未判空即 task.getIsStop(),存在 NPE 风险(数据异常或竞态) 不通过 → 已修正:空则记录并 ServiceException
personRuleService.add/deleteimageRuleRefService.addOnlyRule/delete 返回值 未校验 CloudwalkResult.isSuccess(),失败时仍 updateBingDevices,进度与真实绑定不一致 不通过(违反 §2.2)→ 已修正:统一 requireTaskStepSuccess,失败抛错且递增
catchServiceException(e.getMessage()) 丢失根因类型与栈信息到调用方;异步场景仅日志含 {} 与异常 记录:是否改为 ServiceException(code, msg)initCause 属产品/运维范围,本轮不改
线程池 keepAliveSeconds UpdateFloorsPoolProperties 有字段,Bean 未 setKeepAliveSeconds,配置项无效 缺陷 → 已在 UpdateFloorsTaskExecutor 绑定
RejectedExecutionHandler AbortPolicy,队列满时拒绝提交 记录:与背压策略相关,本轮不改(须与运维对齐)
删楼 ruleMap.get(delFloorId) listZoneInfoByIds 未覆盖某 delFloorId 可能 null 拼接 ruleName 记录:数据正常时风险低;本轮未改(可后续与 DAO 对齐)

7.3 评估结论(是否允许进入代码修正)

  • 允许并已实施(本轮)task 空指针防护;对 personRuleService.add / deleteimageRuleRefService.addOnlyRule / deleteCloudwalkResult 成功校验(约定 §2.2);updateFloorsExecutor 绑定 keepAliveSeconds
  • 暂缓(须单独评审):拒绝策略、catch 异常语义增强;楼层有界并行ruleMap 缺键防护§9

修正实施后:提交 0ddeedc(分支 v0.11)。


8. 迭代 4P1 有界并行(§3.2 / §3.3 / §3.4

实施日期2026-04-25

8.1 行为与约定对齐说明

说明
并发度 代码常量与默认池 corePoolSize=maxPoolSize=6(约定 48 区间内),可通过 ninca.elevator.remote-io.pool.core-pool-size / max-pool-size 覆盖。
§3.2 delete personId 时按批 ThreadPoolExecutor.invokeAll;单 ID 仍走主线程(无 Feign 子线程问题)。失败时返回 76260407 风格 CloudwalkResult.fail,与改造前一致同批内若某 RPC 失败,invokeAll 仍会等本批其它任务结束后再统一 get() 抛出/返回,与**严格单线程「第一条失败即不再发起后续」**在「已发起请求数」上略有差异,属典型有界并行取舍。
§3.3 listFloor 设备数仍顺序 DAOacsPersonService.page 按批并行,结果写入 personTotals[idx] 后顺序 setPersonNumber响应楼层顺序不变
§3.4 addImageStore bindAppImageStoreDevice 仍顺序执行;仅 bindDeviceAndImageStore 按批并行;任一批次中失败则 rollbackImageStoreAfterBindFailure(抽方法)后抛 ServiceException,与原先 try/catch 回滚路径一致。
Feign ThreadLocal 所有子线程 RPC 经 FeignThreadLocalUtil.callWithContext,避免池化线程串请求头。

实施后提交fe571aa(分支 v0.11)。


9. 迭代 5updateFloors 楼层有界并行(§3.5

实施日期2026-04-24(工作区)

9.1 设计要点

说明
并发度 与 §8 一致使用 elevatorRemoteBoundedExecutorThreadPoolExecutor#invokeAll,批大小 UPDATE_FLOORS_FLOOR_PARALLEL = 6(与 AcsPassRuleServiceImpl 等处一致)。
bind 推进 同批内各楼层 RPC 可并发Future#get() 按列表下标顺序 等待;每遇返回值 1 则主线程 getByIdBIND_DEVICES+1,与旧实现「每层成功后立即 +1」的终态一致。
停任务 每层子步骤开头仍 getByIdisStop != 0 时该层贡献 0、不推进 bind。
DAO 异常 删楼分支中 getByRuleName / deleteByOrgAndLabelDataAccessException 在子步内转 ServiceException,以配合 CallableinvokeAll 的异常链。
§3.1 未改 imageRuleRefService.delete 实现,内层 updateGroupPersonRef 行为与冻结前一致。

9.2 同批多楼层与「遇错即停」

§8.1 类似:同批中若一 Floor 的 RPC 失败,同批其它在途 Floor 的 RPC 可能已执行完毕;get() 按顺序在首败时抛出。与严格串行「前一层失败则后层不再发起」在已发出请求可存在差异,属有界并行常见取舍。

9.3 代码位置

  • AcsDeviceTaskServiceImpl#updateFloors#runAddFloorsInBoundedParallel / #runDelFloorsInBoundedParallel#addOneFloorStep / #delOneFloorStep#advanceBindProgressOne