|
|
42466363c7
|
feat(iot): Wave 4 Round 1 — B12/B4/B5 告警状态机 + 规则引擎 SPI
主会话 Opus:
- B12 iot_alarm_record 正交状态机(ack_state + clear_state + archived)
* V2.0.4__iot_alarm_record.sql:主表 + iot_alarm_propagation 关联表
* 评审 C1 正交三字段(替代线性 4 枚举,表达"已清除未确认")
* 评审 C2 联合 UK (device_id, alarm_config_id, tenant_id, deleted)
* 评审 C3 传播关联表(替代 propagated_to JSON 查询)
* Service 5 方法:triggerAlarm / ackAlarm / unackAlarm / clearAlarm / archiveAlarm
* 幂等 upsert(trigger_count++)+ 归档后禁止修改
* 13 单元测试全绿
* TODO B14 分布式锁 / B15 传播 / B16 通知
Sonnet subagent B4:TriggerProvider SPI + 5 内置触发器
* spi/TriggerProvider + TriggerProviderManager(@Component + getType 索引,fail-fast 重复 type)
* trigger/DeviceState / DeviceProperty / DeviceEvent / DeviceService / Timer(Spring TaskScheduler)
* 评审 A3 落地:禁 ServiceLoader / @SPI
* 44 单元测试全绿
Sonnet subagent B5:ConditionEvaluator SPI + 3 条件 + 统一模板变量
* spi/ConditionEvaluator + condition/Manager
* condition/Expression(Aviator + LRU(256) 编译缓存)
* condition/TimeRange(跨午夜支持)
* condition/DeviceState(Redis 查询,空值按 offline)
* template/TemplateResolver:\${namespace.key},拒绝 \$[...] 旧语法(评审 B5)
* TODO B44 完整 8 层 Aviator 沙箱
* 50 单元测试全绿(TemplateResolver 16 + 条件 3x ≈ 34)
测试汇总:rule 136 全绿 / server 13 新增全绿
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet (subagent) <noreply@anthropic.com>
|
2026-04-24 00:35:14 +08:00 |
|
|
|
1f87d599c0
|
feat(iot): B11 iot_device.subsystem_id + 设备归属绑定 API(一期允许 NULL)
- 新增 sql/iot/V2.0.3__iot_device_add_subsystem.sql(ALTER + idx_subsystem)
- 新增 sql/iot/V2.1.0__iot_device_subsystem_not_null.sql(二期预留,带 "勿执行" 注释)
- IotDeviceDO 加 subsystemId(一期可 NULL,二期改 NOT NULL)
- IotDeviceService 加 bindDeviceToSubsystem / batchBind / unbind / selectCountBySubsystemId
- IotDeviceServiceImpl.createDevice 强校验 subsystemId + 同租户 + Redis HINCRBY +1
- 绑定变更按 TransactionSynchronizationManager afterCommit 同步 Redis(-1 / +1,避免脏状态)
- IotDeviceMapper 加 selectCountBySubsystemId / updateSubsystemId 等
- IotSubsystemServiceImpl 加 incrementDeviceCount/decrementDeviceCount;deleteSubsystem 改用 DB 计数兜底(更可靠)
- IotDeviceController 加 PUT /bindSubsystem + /batchBindSubsystem(@PreAuthorize iot:device:update)
- IotDevicePageReqVO 加 subsystemId 过滤参数(null 可走 IS NULL 查未归属)
- api ErrorCodeConstants 加 DEVICE_SUBSYSTEM_REQUIRED / DEVICE_SUBSYSTEM_CROSS_TENANT(1_050_003_009/010)
- 测试:IotDeviceServiceImplTest 8/8 + B10 IotSubsystemServiceImplTest 补 mock deviceMapper 后 8/8 全绿
- Known Pitfalls 落地:
⚠️ 评审 A2:一期允许 NULL,V2.1.0 预留二期 NOT NULL
⚠️ Redis 计数:事务提交后同步(TransactionSynchronizationManager.afterCommit)
⚠️ 跨租户:校验 subsystem 属于当前租户,不然抛 DEVICE_SUBSYSTEM_CROSS_TENANT
⚠️ 索引 idx_subsystem (tenant_id, subsystem_id, deleted) 最左匹配;IS NULL 查询走全表扫,文档已提示
Co-Authored-By: Claude Sonnet (B11 subagent) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context, orchestrator) <noreply@anthropic.com>
|
2026-04-24 00:03:57 +08:00 |
|
|
|
962e69290b
|
feat(iot): B2 RuleChain/Node/Link 数据模型 + CRUD(单 Trigger/DAG 无环/乐观锁)
- 新增 sql/iot/V2.0.1__iot_rule_chain.sql(iot_rule_chain/node/link 三表 + idx_binding 索引)
- 新增 rule 模块 dal/(3 个 DO + 4 个封闭枚举 + 3 个 Mapper)
- 新增 rule 模块 service/(CRUD + 单 Trigger 校验 + DAG DFS 无环 + 乐观锁 + 级联软删)
- 新增 rule 模块 controller/admin/(7 REST 端点 + @PreAuthorize + VO)
- 新增 resources/mapper/rule/(3 个 MyBatis XML)
- api 模块 ErrorCodeConstants 新增规则链段(1-050-030-xxx)
- **补 B1 遗漏依赖**:rule/pom.xml 追加 viewsh-spring-boot-starter-{web,security,biz-tenant}
- 测试:8 个单元用例全绿(BaseMockitoUnitTest)
- Known Pitfalls 落地:
⚠️ 评审 B4:relation_type VARCHAR + 应用层 RuleLinkRelationType.isValid 校验
⚠️ 评审 B9:updateWithVersion 乐观锁原子 SQL + idx_update_time 索引支撑 B9 拉模式兜底扫描
⚠️ 评审 B10:单 Trigger 校验在 Service 层(validateSingleTrigger)
⚠️ 评审 A4:name UK(name, tenant_id, deleted)
⚠️ 评审 §十一-B:idx_binding (tenant_id, subsystem_id, product_id, device_id) 最左匹配
Co-Authored-By: Claude Sonnet (B2 subagent) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context, orchestrator) <noreply@anthropic.com>
|
2026-04-23 21:09:54 +08:00 |
|
|
|
6649e1abb6
|
feat(iot): B10 iot_subsystem 表 + CRUD + Redis 设备计数聚合
- 新增 sql/iot/V2.0.2__iot_subsystem.sql(iot_project + iot_subsystem)
- 新增 server 模块 subsystem/ 下 DO + Mapper + Service + Controller + VO(7 端点)
- 新增 IotSubsystemDeviceCountRedisDAO(HINCRBY + rebuild + ApplicationReadyEvent 触发)
- api 模块 ErrorCodeConstants 新增子系统段(1-050-020-xxx)
- server 模块 RedisKeyConstants 新增 SUBSYSTEM_DEVCOUNT
- 测试:8 个单元用例全绿(mvn test IotSubsystemServiceImplTest)
- Known Pitfalls 落地:
⚠️ 评审 A4:UK(name, tenant_id, project_id, deleted) + 应用层 existsByNameAndProject 兜底 NULL
⚠️ 评审 A6:device-stats 走 Redis Hash,避免 GROUP BY
⚠️ 评审 A7:simple-list 权限码 iot:device:query,返回字段仅 id/name/code
⚠️ 删除校验:Redis 计数 > 0 抛 SUBSYSTEM_HAS_DEVICES
⚠️ Redis 重建:ApplicationReadyEvent + try/catch + log.warn 不阻塞启动
说明:iot_device 当前无 subsystem_id 列(rebuild 逻辑标 TODO B11),
待 B11 加列后启用 DB 重建查询。
Co-Authored-By: Claude Sonnet (B10 subagent) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context, orchestrator) <noreply@anthropic.com>
|
2026-04-23 21:08:00 +08:00 |
|