mirror of
https://github.com/hpd840321/starRiverProperty.git
synced 2026-06-09 08:20:31 +08:00
elevator(listFloor): validate acsPersonService.page result per §2.2
- Throw ServiceException when page RPC fails (align with zoneTree branch) - Guard null page data; rowsOfPage=1 for totalRows-only reads - Document walkthrough sign-off and status in 走查任务与状态 §5 Made-with: Cursor
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
|--------|----------|------------------|----------------------------|------------------------|
|
||||
| **§3.1** | `ImageRuleRefServiceImpl#delete`(约 575~598 行) | **`N = param.getIds().size()`** 次 `updateGroupPersonRef`(每规则删后各 1 次) | **P0**:全部 `deleteById` 完成后,对本轮涉及的 `labelIds`、`organizationIds` **去重并集**,调用 **1 次** `updateGroupPersonRef`;为每次 RPC 增加 **`isSuccess` 校验**(与 §2.2 一致) | **须图库/通行确认**:合并调用是否为「刷新引用」语义、是否等价于当前 N 次效果;若不能确认则**不得合并**,仅可补返回值校验与日志 |
|
||||
| **§3.2** | `AcsPersonServiceImpl#delete`(约 165~175 行) | **`P = param.getPersonIds().size()`** 次 `imageStorePersonService.delete` | **P1**:**有界并行**(并发度 4~8)调用 `delete`,失败聚合与现网「遇错即停」一致;已具备 `isSuccess` 分支,保持语义 | **无批量 delete**:无法改为单次 RPC,除非将来扩展契约(约定 §4 远期) |
|
||||
| **§3.3** | `AcsPassRuleServiceImpl#listFloor`(约 109~121 行) | **`F = passRuleResults.size()`** 次 `acsPersonService.page`(仅取 `totalRows`) | **P1**:按楼层 **有界并行** `page`(如 `rowsOfPage=1`);**合并结果顺序**与树遍历一致;**立即修正**:循环内对 **`page.isSuccess()`** 校验(当前缺失,违反 §2.2) | **禁止**用本地 `countPersonIdByZoneId` 等替代 `page.totalRows`(与 `PersonRuleServiceImpl#page` 路径过滤**不等价**,见约定 §3.3);**无多 zone 一次统计 API** 时无法单 RPC 消除 N |
|
||||
| **§3.3** | `AcsPassRuleServiceImpl#listFloor` | **`F = passRuleResults.size()`** 次 `acsPersonService.page`(仅取 `totalRows`) | **首轮已完成**:`page.isSuccess()`、`getData()` 空防护、`rowsOfPage=1`。**P1 后续**:按楼层 **有界并行** `page`(保持结果顺序) | **禁止**用本地 `countPersonIdByZoneId` 等替代 `page.totalRows`;**无多 zone 一次统计 API** 时无法单 RPC 消除 N |
|
||||
| **§3.4** | `AcsPassRuleServiceImpl#addImageStore`(约 195~201 行) | **`D = deviceList.size()`** 次 `bindDeviceAndImageStore` | **P1**:**有界并行** `bind`;并行失败时与现有 **回滚删图库** 逻辑一致(注意竞态与顺序) | **无批量 bind**:不能合并为 1 次 RPC(契约不扩展时) |
|
||||
| **§3.5** | `AcsDeviceTaskServiceImpl#updateFloors`(约 46~119 行) | 增:**`A = addFloors.size()`** 次 `personRuleService.add` 或 `imageRuleRefService.addOnlyRule`;删:**`D = delFloorIds.size()`** 次 `personRuleService.delete` / `imageRuleRefService.delete` / DAO | **P1**:删层在 §3.1 落地后可减少「内层 refresh」放大;可对**楼层维度**做有界并行(与限流/异步线程池策略一致) | **`@Async("updateFloorsExecutor")`** 下线程池与背压须单独评估;错误现为 `throw new ServiceException(e.getMessage())` 信息较粗,是否属「接口不变」范畴由产品/运维定义 |
|
||||
|
||||
@@ -32,9 +32,9 @@
|
||||
|
||||
## 3. 建议下一迭代(不改 HTTP/Feign 签名)
|
||||
|
||||
1. **小改快赢**:`AcsPassRuleServiceImpl#listFloor` 增加 **`zoneTree` / `page` 的 `isSuccess` 与空数据防护**(满足 §2.2,避免失败当 0)。
|
||||
1. ~~**小改快赢**~~:`AcsPassRuleServiceImpl#listFloor` 已增加 **`page` 的 `isSuccess` 与空数据防护**、`rowsOfPage=1`(见 **§5**)。
|
||||
2. **P0 阻塞项**:与图库团队确认 **`updateGroupPersonRef`** 在「多 label/org 一次传入」下的语义 → 通过后实施 **§3.1 合并**。
|
||||
3. **P1 工程项**:为 §3.2 / §3.3 / §3.4 引入**统一有界线程池**(或复用现有异步池策略),并在 PR 中写明失败策略与超时。
|
||||
3. **P1 工程项**:为 §3.2 / §3.3(并行 `page`)/ §3.4 引入**统一有界线程池**(或复用现有异步池策略),并在 PR 中写明失败策略与超时。
|
||||
|
||||
---
|
||||
|
||||
@@ -44,3 +44,29 @@
|
||||
|------|------|
|
||||
| 更新触发 | `ImageRuleRefServiceImpl#delete`、`AcsPersonServiceImpl#delete`、`AcsPassRuleServiceImpl#listFloor` / `#addImageStore`、`AcsDeviceTaskServiceImpl#updateFloors` 任一处重构或签契约变更 |
|
||||
| 结论回填 | 图库对 §3.1 的确认结论请写回 [约定文档 §3.1](对外接口不变-远程调用与性能优化约定.md) 文末建议行(对接人 + 日期) |
|
||||
|
||||
---
|
||||
|
||||
## 5. 迭代 1:`AcsPassRuleServiceImpl#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.2**;Feign 失败时 `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=0`、`CloudwalkPageInfo(1,1)` 仅取总数。
|
||||
|
||||
**修正实施后**:提交 **`251fc86`**(分支 `v0.11`)。
|
||||
|
||||
---
|
||||
|
||||
## 6. 迭代 2 起(占位)
|
||||
|
||||
- **§3.1** 待图库确认后再改代码;确认前不在此文档标记为「已实施」。
|
||||
|
||||
+11
-2
@@ -114,10 +114,19 @@ public class AcsPassRuleServiceImpl extends AbstractAcsPassService implements Ac
|
||||
passRuleResult.setDeviceNumber(Integer.valueOf(deviceList.size()));
|
||||
AcsPersonQueryParam personParam = new AcsPersonQueryParam();
|
||||
personParam.setZoneId(passRuleResult.getId());
|
||||
CloudwalkPageInfo pageInfo = new CloudwalkPageInfo(1, 10);
|
||||
CloudwalkPageInfo pageInfo = new CloudwalkPageInfo(1, 1);
|
||||
CloudwalkResult<CloudwalkPageAble<AcsPersonResult>> page =
|
||||
this.acsPersonService.page(personParam, pageInfo, context);
|
||||
passRuleResult.setPersonNumber(Long.valueOf(((CloudwalkPageAble)page.getData()).getTotalRows()));
|
||||
if (!page.isSuccess()) {
|
||||
this.logger.info("远程调用查询通行人员分页失败,原因:" + page.getMessage());
|
||||
throw new ServiceException(page.getCode(), page.getMessage());
|
||||
}
|
||||
if (ObjectUtils.isEmpty(page.getData())) {
|
||||
passRuleResult.setPersonNumber(Long.valueOf(0L));
|
||||
} else {
|
||||
passRuleResult.setPersonNumber(
|
||||
Long.valueOf(((CloudwalkPageAble)page.getData()).getTotalRows()));
|
||||
}
|
||||
}
|
||||
return CloudwalkResult.success(passRuleResults);
|
||||
} catch (DataAccessException e) {
|
||||
|
||||
Reference in New Issue
Block a user