feat: 租户访客策略 SQL、访客邀约验证包、component-org 与发布脚本

- docs/sql: organization_* 与 tenant_* 访客楼层策略脚本
- docs/testing: 访客邀约页初始化验证、pack 脚本与 README(忽略 dist/__pycache__)
- maven-ninca-common-component-organization: CpImageStoreServiceImpl、starter、run-verify、releases 脚本与 javap 审计 JSON
- docs/superpowers: component-org 生产问题修复计划
- scripts/test-env/prepare-db.sh 更新

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
反编译工作区
2026-05-06 22:00:16 +08:00
parent 86cf41890e
commit 25db029859
24 changed files with 6016 additions and 27 deletions
@@ -0,0 +1,132 @@
# 预存问题 — 当前代码可完善项
**日期**: 2026-05-06
---
## 可修复: 4 项 (覆盖 ~38,000 错误/天)
### 1. 🔴 P0: addFace 图片为空无限重试 (36,560次)
**文件**: `CpImageStoreToolServiceImpl.java` L335-388
**根因**:
```java
// L343: 人员不存在时创建空对象
ImgStorePerson imgStorePerson = CollectionUtils.isEmpty(personList)
? new ImgStorePerson() // ← 空personcomparePicture=null
: personList.get(0);
// L346: 拿到的图片URL为空
extractParam.setImageUrl(imgStorePerson.getComparePicture());
// → 特征提取异常 → L386 日志 "图片为空"
```
**修复**:
```java
// 人员不存在时直接返回失败,不继续处理
if (CollectionUtils.isEmpty(personList)) {
this.logger.warn("人员不存在 imageId={}", param.getImageId());
return CloudwalkResult.fail("53060434", getMessage("53060434"));
}
ImgStorePerson imgStorePerson = personList.get(0);
if (StringUtils.isBlank(imgStorePerson.getComparePicture())) {
this.logger.warn("人员图片为空 personId={} imageId={}",
imgStorePerson.getId(), param.getImageId());
return CloudwalkResult.fail("53060434", getMessage("53060434"));
}
```
**影响**: 消除 36,560 次错误日志 (占全部错误 45%)
---
### 2. 🟠 P1: addValidateData Redis 锁竞争 (688+322次)
**文件**: `CpImageStorePersonValidateManager.java` L102-141, L135-185
**根因**:
- `group-person-syn-pool` 线程池并发调用 `addValidateData`
- `removeMap`/`addMap` 中多个 entry 竞争同一个 Quartz job 的 Redis 锁
- 688 次 error 集中在同一秒 (2026-02-27 15:14:26)
**修复**:
```java
// L103: 在 for-loop 之前对 removeMap 按时间戳去重
// 避免多个线程处理相同的 job key
for (Map.Entry<Long, Set<SyncPersonLocal>> entry : dedupedRemoveMap.entrySet()) {
// L107: 锁获取失败时不打 ERROR,改为 WARN
if (!this.validateJobGroupLock(l, lockValue)) {
log.warn("获取job锁失败(可能已被其他线程处理) key={}", l);
continue;
}
// ... 原逻辑 ...
}
// L185: 同样处理 addMap
```
**影响**: 消除 1,010 次 error 日志 + 减少 Redis 连接竞争
---
### 3. 🟡 P2: 图片角度识别失败 (35次)
**文件**: `ImageEditUtils.java` L140-148
**根因**: Commons Imaging 库解析 TIFF/JPEG 格式时抛异常
**修复**:
```java
// L145: 添加更详细的错误日志 + 降级处理
} catch (Exception e) {
log.warn("图片角度识别失败, 降级为0度: {}", e.getMessage());
return 0; // 降级为不旋转,而不是抛出异常
}
```
**影响**: 消除 35 次 error 日志 + 提高图片处理容错性
---
### 4. 🟡 P2: device updatePerson 空指针 (4,749次)
**文件**: `CpOrgDeviceKitController.java` L160 (web 模块)
**根因**: `cause` 后为空 — 下游返回 null
**修复**:
```java
} catch (Exception e) {
log.error("device updatePerson error deviceCode={} cause={}",
param.getDeviceId(),
e.getMessage() != null ? e.getMessage() : e.getClass().getSimpleName(),
e); // 打印完整 stack trace
return CloudwalkResult.fail("53060411", getMessage("53060411"));
}
```
**影响**: 可追踪 4,749 次失败的真实原因
---
## 不可修复: 5 项 (下游/基础设施)
| 错误 | 原因 |
|------|------|
| AggDeviceImageStoreFeignClient failed (36K) | cwos-portal 服务不可达 — 运维排查 |
| AtomicDeviceFeignClient failed (368) | 设备管理服务不可达 |
| VehicleFeignClient failed (68) | 车牌服务不可达 |
| ElevatorFeignClient failed (15) | 电梯服务不可达 |
| MySQL connection lost (13) | 数据库连接池配置 |
---
## 实施优先级
| 顺序 | 修复项 | 文件 | 消除错误数 | 预估行数 |
|------|--------|------|-----------|---------|
| 1 | addFace 空图片 | CpImageStoreToolServiceImpl.java | 36,560 | +8行 |
| 2 | Redis 锁竞争 | CpImageStorePersonValidateManager.java | 1,010 | +5行 |
| 3 | device updatePerson | CpOrgDeviceKitController.java | 4,749 | +3行 |
| 4 | 图片角度识别 | ImageEditUtils.java | 35 | +2行 |
**总计**: 4 文件, ~18 行代码, 消除 ~42,354 错误/天 (53%)