Files
aiot-platform-cloud/viewsh-module-iot/viewsh-module-iot-rule/pom.xml
lzh ae74b4752a feat(iot): B3 RuleEngine 执行器(DAG + 链级隔离 + 三层匹配去重)
rule 模块 engine/ 新增 14 个核心类 + 4 个测试:

- RuleEngine / DefaultRuleEngine:对外入口,链级 try-catch 隔离(决议 #3)
- DagExecutor:BFS 遍历,按 relation_type 选 outgoing links,RuntimeException 转 FAILURE
- ChainIndex:三层绑定(subsystem/product/device)4 种 key 匹配 + LinkedHashMap 去重 + priority ASC 排序
- RuleChainCompiler:DO → CompiledRuleChain,含单 Trigger + DAG 无环 + 非法枚举兜底
- NodeProvider / NodeProviderRegistry:SPI + Spring @Component 路由(禁用 ServiceLoader/@SPI)
- RuleContext / NodeResult / CompiledRuleChain/Node/Link / RuleEngineResult / RuleChainException

测试覆盖(42/42 全绿):
- DagExecutorTest: 线性链 / 分支(TRUE/FALSE)/ 并行动作 / 异常转 FAILURE / metadata 传递 / SKIP 截断 / 缺 Trigger
- ChainIndexTest: 4 种 wildcard 组合 / 去重 / priority 排序 / 租户隔离 / evict
- RuleChainCompilerTest: 正常编译 / 单 Trigger 兜底 / DAG 无环 / 非法 category & relation_type / 连线 sortOrder
- DefaultRuleEngineTest: 链级异常隔离(chain1+chain3 成功,chain2 失败,counters 各 1 次)

补齐依赖:
- rule/pom.xml 加 io.micrometer:micrometer-core(节点执行 Timer + 失败 Counter)
- RuleNodeCategory 加 of(String) 静态查找方法(配合 RuleLinkRelationType.of 一致风格)

Known Pitfalls 落地:
  ⚠️ 评审 B1:ShakeLimit 节点 hook 留在 DagExecutor(B48 补)
  ⚠️ 评审 B3:LinkedHashMap 去重保留顺序(ChainIndex.match)
  ⚠️ 评审 B4:relation_type 严格封闭 6 值(RuleLinkRelationType + isValid)
  ⚠️ 评审 A5:chains 顺序 for 循环 + try-catch;不使用 Reactor flatMap 并发
  ⚠️ 评审 B10:单 Trigger 兜底在 Compiler 层(Service 层 + Compiler 双重保障)
  ⚠️ Metrics 基数:tag 含 chainId + nodeType + outcome;规则链 ≤ 500 控制
  ⚠️ DAG 兜底 MAX_NODES_PER_EXECUTION=1000 防脏数据绕过无环校验

未实现(留给后续任务):
- 具体 Provider(B4/B5/B6 Trigger/Condition/Action 实现)
- 全量缓存加载 + Pub/Sub 驱逐(B8)
- JMH Benchmark(任务卡 §6.4 + AC9 p99 < 50ms,第二期补)
- @SpringBootTest 集成测试(B9 Handler 就位后补)

Co-Authored-By: Claude Opus 4.7 (1M context, main session) <noreply@anthropic.com>
2026-04-23 23:58:48 +08:00

81 lines
2.9 KiB
XML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>viewsh-module-iot</artifactId>
<groupId>com.viewsh</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>viewsh-module-iot-rule</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>IoT 规则引擎独立模块DAG + SPI + 抖动抑制 + Aviator 脚本)</description>
<dependencies>
<!-- 内部模块:只依赖 apiDTO/枚举)和 core消息总线/影子接口) -->
<dependency>
<groupId>com.viewsh</groupId>
<artifactId>viewsh-module-iot-api</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.viewsh</groupId>
<artifactId>viewsh-module-iot-core</artifactId>
<version>${revision}</version>
</dependency>
<!-- 【关键】Aviator 表达式引擎 -->
<dependency>
<groupId>com.googlecode.aviator</groupId>
<artifactId>aviator</artifactId>
<version>5.3.3</version>
</dependency>
<!-- Web / Validation / Swagger支持 Controller + @Valid + @Operation -->
<dependency>
<groupId>com.viewsh</groupId>
<artifactId>viewsh-spring-boot-starter-web</artifactId>
</dependency>
<!-- Security支持 @PreAuthorize -->
<dependency>
<groupId>com.viewsh</groupId>
<artifactId>viewsh-spring-boot-starter-security</artifactId>
</dependency>
<!-- 多租户(支持 TenantContextHolder -->
<dependency>
<groupId>com.viewsh</groupId>
<artifactId>viewsh-spring-boot-starter-biz-tenant</artifactId>
</dependency>
<!-- Micrometer 指标RuleEngine 节点执行 Timer / 失败计数) -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
</dependency>
<!-- DB 相关 -->
<dependency>
<groupId>com.viewsh</groupId>
<artifactId>viewsh-spring-boot-starter-mybatis</artifactId>
</dependency>
<!-- 缓存相关 -->
<dependency>
<groupId>com.viewsh</groupId>
<artifactId>viewsh-spring-boot-starter-redis</artifactId>
</dependency>
<!-- 测试 -->
<dependency>
<groupId>com.viewsh</groupId>
<artifactId>viewsh-spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>