Rule 规则服务数据库设计
规则服务回答的是“这台设备现在应该命中哪些业务”,例如哪些任务、广告位、黑名单配置、域名或设备导出配置。它保存规则表达式、设备范围、业务绑定及审批变更状态;任务内容、广告素材、黑名单安装回执和设备档案仍由各自服务维护。规则命中只返回业务编号,不等于业务已经成功执行。
当前测试环境使用独立 MySQL 库 ik_rule:实测 12 张表、110 个字段,与本服务 12 个落库实体全部对应,没有额外未归属表或缺失表。规则运行还依赖 Redis、本地缓存和各业务进程中的 LiteFlow 内存规则链,这些运行状态不在 MySQL 表字典中。
文档导航
| 文档 | 业务问题 |
|---|---|
| 规则定义、审批与运行 | 可视化条件如何形成 EL,修改何时生效,消息表为什么存在 |
| 设备范围、业务绑定与数量 | MAC、资源集、渠道、地区如何组合,businessType/businessId 指向谁 |
| 完整映射与结构差异 | 全部实体字段、索引、非落库投影、旧注释和实际结构的差异 |
| ik_rule 物理字典 | 实测字段类型、长度、默认值和所有索引 |
数据如何流动
数据库 rule_liteflow_chain 是定义存储,rule_business 是业务绑定。MAC/渠道集合先缩小候选规则范围,再检查启用、生效、地区和 EL ,最后返回绑定业务 ID。设备规则导出是特殊调用:跳过逐 MAC 专属规则查询,仍参与其他候选规则集合及 EL 匹配。
数据源与证据边界
manifest.json.service_bindings.rule.master → datasource.rule → ik_rule。本服务 DAL 未发现其他@DS路由或 ES/TDengine 实体。- 提供的 Nacos
liteflow.yaml引用datasource.rule连接配置,加载application_name='ik_v2'的rule_liteflow_chain,轮询启用、间隔与首次启动延迟均为 60 秒配置值。它是配置快照,不代表本次观察到了轮询执行。 - 实库快照采集于 2026-09-18 20:51:12(北京时间)。本目录静态核对源码、继承、Mapper、必要业务和 LiteFlow 读取配置;未运行规则、审批、消息消费、统计、服务、测试或编译,也未读取业务数据。
- 所有关联在本次
ik_rule元数据中均无物理外键。文中关系图表示应用逻辑,业务有效性和跨服务一致性由代码维护。
源码引用约定:B/ 为仓库根下 ik_project/yudao-cloud/yudao-module-rule/yudao-module-rule-biz/src/main/java/cn/iocoder/yudao/module/rule/;A/ 为同模块 yudao-module-rule-api/src/main/java/cn/iocoder/yudao/module/rule/;R/ 为 rule-biz 的 src/main/resources/;F/ 为 ik_project/yudao-cloud/yudao-framework/。数字是当前源码行号。
随着业务从任务筛选扩展到共享 MAC 资源、审批变更、域名分发和设备导出,表中会并存历史命名与新增语 义。本次保留真实列名,按当前调用解释用途,不因为旧注释或某分支当前关闭就判定表废弃。
Rule 完整源码映射与结构差异
本次以 2026-09-18 测试环境 mysql-ik_rule.json 的 12 表、110 字段为物理依据,逐项对照当前实体、继承字段、Mapper 和必要运行读取逻辑。12 个落库实体均有实际表,源码映射字段均找到对应列;另有一个不落库的 MacListUnionDO 联合查询对象。没有使用历史建库 SQL 代替实测现状。
完整字段映射
所有表使用规则服务 master,实际库为 ik_rule。下表源码路径相对于 B/dal/dataobject/(完整前缀见首页),A5 表示继承 BaseDO 的 create_time,update_time,creator,updater,deleted;其中 deleted 带 @TableLogic。其余字段从 Java 驼峰属性映射为所列列名,常量与序列化字段不落库。
| 实体与源码位置 | 实际表 | 全部映射列 |
|---|---|---|
chain/RuleLiteflowChainDO.java:20 | rule_liteflow_chain | id,application_name,name,chain_name,scope,el_data,json_data,business_type,remark,route,namespace,draft,enable,bpm_status,valid,has_mac + A5 |
chain/RuleBusinessDO.java:15 | rule_business | id,liteflow_chain_id,business_type,business_id,valid + A5 |
chain/RuleMacItemDO.java:18 | rule_mac_item | id,liteflow_chain_id,mac,valid,create_time,partition_index |
chain/RuleChannelItemDO.java:13 | rule_channel_item | id,liteflow_chain_id,channel_id,valid |
chain/RuleRegionItemDO.java:14 | rule_region_item | id,liteflow_chain_id,region_id,valid |
chain/RuleChainMacResourceItemDO.java:15 | rule_chain_mac_resource_item | id,liteflow_chain_id,mac_resource_id,valid |
macresource/RuleMacResourceDO.java:15 | rule_mac_resource | id,name,remark + A5 |
macresource/RuleMacResourceItemDO.java:17 | rule_mac_resource_item | id,mac_resource_id,mac,valid,create_time,partition_index |
fielddefinition/RuleFieldDefinitionDO.java:19 | rule_field_definition | id,name,alias_name,type,available_operators + A5 |
businesslimit/RuleBusinessLimitDO.java:13 | rule_business_limit | id,business_type,business_id,limit_count,current_count |
chain/RuleDeviceCountDO.java:16 | rule_device_count | id,type,liteflow_chain_id,business_type,business_id,device_count,create_time,update_time,deleted;实体自行标注逻辑删除 |
bpmnostartmessage/RuleBpmNoStartMessageDO.java:14 | rule_bpm_no_start_message | id,parent_id,liteflow_chain_id,message_key,business_type,business_id,message,status,retry_count,retry_topic,exception_message,exception_stack_trace + A5 |
完整物理类型和默认值见 实测字典。有业务意义的类型边界:draft 为原生 JSON;available_operators/el_data/json_data 均为 varchar(4096);消息实体的 Long id 对应实际 int 主键,Java 类型更宽不代表数据库也支持 bigint 范围。文档保留这些实际约束,不自动扩大字段。
不应误报为缺列的对象
RuleChainMacResourceItemDO的macResourceName/macResourceRemark/ruleChainName/ruleName均为@TableField(exist=false),用于关联展示。MacListUnionDO没有@TableName,由RuleLiteflowChainMapper.xml的 UNION 查询产生。其字段为ruleMacItemId,mac,liteflowChainId,name,chainName,enable,valid,createTime,channelId,sourceType,macResourceItemId,macResourceId,macResourceName,包括关系来源和展示名称;不存在独立物理表。RuleFieldDefinitionDO.availableOperators使用RuleCmpInfoTypeHandler;RuleLiteflowChainDO.draft使用BpmDraftTypeHandler,均启用autoResultMap。它们是单列序列化对象,不应展开成新的子表或推断所有 JSON 键都是物理字段。- 本服务 Redis DAO 保存反向索引集合、规则详情、业务限额以及无范围规则集合;rule-api 还使用本地缓存。这些对象未通过本轮 MySQL/TDengine/ES 采集读取,不能声称已核验 Redis 现存键或 TTL。
实测索引与关系约束
全库无物理外键。除以下索引外,各表都只有普通主键 id;MAC 明细的主键为复合键,见下表。
| 表 | 非主键索引 / 特殊主键 | 业务含义 |
|---|---|---|
rule_business | 普通索引 business_type、liteflow_chain_id | 按业务类型找规则、按规则找业务;三元组去重仍依赖 Service |
rule_business_limit | 普通复合索引 (business_type,business_id) | 查询业务限额;它不是唯一键 |
rule_chain_mac_resource_item | 普通索引 liteflow_chain_id | 查询规则引用的资源 |
rule_channel_item | 普通索引 channel_id | 按设备渠道反查候选规则 |
rule_region_item | 普通索引 region_id | 地区关联查询 |
rule_mac_item | 主键 (id,partition_index);唯一 (liteflow_chain_id,mac,partition_index);普通 liteflow_chain_id/mac/valid | 分区下的规则 MAC 去重和反向检索 |
rule_mac_resource_item | 主键 (id,partition_index);唯一 (mac_resource_id,mac,partition_index);普通 mac/mac_resource_id/valid | 分区下的资源 MAC 去重和反向检索 |
规则链、字段定义、MAC 资源、设备数量和待审批消息表没有其他实测索引。因此“链名唯一”“资源名唯一”“消息唯一标识”“按业 务只保存一条数量结果”等业务描述都不能替代物理唯一约束证据。是否存在重复值本次没有查询。
差异与业务演进记录
| 编号 | 已核验事实 | 如何理解及后续核查边界 |
|---|---|---|
| RULE-01 | rule_liteflow_chain/rule_business/rule_field_definition/rule_mac_resource/rule_bpm_no_start_message 实库额外有 tenant_id,对应实体 BaseDO 不声明 | 保留为物理列;可能由租户拦截器参与,不能删列或断言无租户隔离 |
| RULE-02 | rule_chain_mac_resource_item 实库额外有 create_time,实体未映射 | 实库默认 CURRENT_TIMESTAMP;映射清单不能漏掉这项物理审计信息 |
| RULE-03 | 链名/别名、资源名源码做唯一校验,实库相应表只有主键;业务关联和限额也缺业务组合唯一约束 | 表达“应用维护唯一性”,不宣称数据库已兜底;未检验存量重复 |
| RULE-04 | 消息 id 是 Java Long、实际 int;available_operators/el_data/json_data 为 varchar(4096) | 明确数据库容量边界;不根据 Java 类型或“JSON”命名误写为 bigint/原生 JSON |
| RULE-05 | LiteFlow custom SQL 不检查审批 valid/bpm_status,运行匹配代码另检查 valid!=0 | 内存加载与业务生效分层;需核验实际调用路径,不能只靠 enable 宣称审批完成 |
| RULE-06 | 无范围规则 XML 方法用 valid=1,业务 API 路径用 valid!=0;其他查询也有严格已生 效和包含待变更两类口径 | 保留各入口实际条件,不统一重写成一个“有效状态”;来源 R/mapper/chain/RuleLiteflowChainMapper.xml:71 与 B/service/business/RuleBusinessApiServiceImpl.java:1009 |
| RULE-07 | RuleDeviceCountServiceImpl 不含地区/EL过滤,数据库注释为空 | 应称设备覆盖数量缓存,不能称最终匹配设备数或执行成功数 |
| RULE-08 | 限额维护及匹配分支存在,但业务类型枚举当前全部 hasCountLimit=false;入口另有“暂不实现”旧注释 | 文档以实际分支和开关共同解释,既不判废弃,也不宣称配额已强制启用 |
| RULE-09 | 旧分区方法和常量 150 仍在,当前名单算法采用父ID 10桶×MAC 30桶;单字段 ORM id 对应复合物理主键 | 补采确认两张 MAC 明细表各 300 个 LIST 分区;名单搬迁/查询需保留 partition_index,不可沿用旧 150 常量 |
| RULE-10 | DomainUotaAppServiceImpl 删除解绑使用 DOMAIN_DISPATCH(4),DomainServiceImpl 查询 UOTA App 使用 DOMAIN_DISPATCH_UOTA(5) | 跨服务业务类型使用存在差异,需调用方确认删除后绑定处理;本次不执行删除或修改代码 |
| RULE-11 | SQL 编辑器和带审批管理 Service 是两个保存入口,旧 Kafka 编辑检查回调类已注释,现有 Bus 回调监听器 | 不把历史入口当现行审批流程,运行 Bean/页面访问范围仍待部署核验 |
RULE-10 证据为 task-biz 源码 service/domain/DomainUotaAppServiceImpl.java:94、service/domain/DomainServiceImpl.java:131,132,完整前缀见相邻业务绑定页。规则链主字段 scope 注释保留四种使用范围,但实际绑定还叠加业务类型审批约束,不能仅按该字段的早期描述推断任意多对多绑定都允许。
对照结果与维护建议
本服务 12 张实际表全部归属,没有为了补全“通用规则引擎模型”添加并不存在的表。6 个实库额外字段已分别记录,所有被 exist=false 排除的属性及查询投影均未算作缺列。未发现本服务当前 DAL 直连其他 MySQL 库;跨域对象由 RPC/调用方传入的业务 ID 和设备属性关联。
以后增加筛选字段时同时核对 device DTO、字段定义、比较组件和运行上下文;增加业务类型时同时核对枚举、绑定/解绑、审批通知与业务读取主键;变更审批或缓存状态时同时维护主表与关系表的有效性口径。这样才能让设计文档解释正在运行的业务,而不只是复制一次建表语句。
继承/序列化证据:F/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/dataobject/BaseDO.java:24、同模块 core/type/RuleCmpInfoTypeHandler.java:25 和 core/type/BpmDraftTypeHandler.java:22。本次未运行编译、测试或数据库写操作。