Skip to content

Latest commit

 

History

History
479 lines (425 loc) · 21.7 KB

File metadata and controls

479 lines (425 loc) · 21.7 KB

变更日志

所有重要的项目变更都将记录在此文件中。

[未发布] - 2026-02

新增 (Added)

BasicDataAdapter - 基础数据适配器与字段修改功能

  • 核心功能: 提供动态字段修改能力,支持运行时添加/删除/修改数据字段
    • 新增 BasicDataAdapter 类,继承自 DataAdapter
    • 支持多种数据类型:string, double, int, int64_t, bool, monostate (nil)
    • 提供字段修改 API:
      • set(key, value): 添加或修改字段(支持多种类型重载)
      • set_null(key): 将字段设置为 nil
      • remove(key): 删除指定字段
      • clear_fields(): 清空所有字段
    • 支持字段覆盖:多次调用 set() 会覆盖之前的值
    • 自动去重:使用 unordered_map 存储字段,自动处理重复键
  • 实现细节
    • 使用 std::variant 存储多种类型的字段值
    • push_to_lua(): 创建空 Lua table
    • execute_commands(): 将字段设置到 Lua table(由引擎调用)
    • 空键检查:拒绝空键,防止 Lua 错误
  • 集成:
    • JsonAdapter 继承 BasicDataAdapter,获得字段修改能力
    • 用户自定义适配器可以继承 BasicDataAdapter 获得字段修改功能
  • 测试覆盖: 新增 28 个 BasicDataAdapter 测试用例
    • Set 方法测试(7个)
    • set_null/remove/clear_fields 测试(3个)
    • 字段覆盖测试(2个)
    • 边界情况测试(4个)
    • JsonAdapter 字段修改测试(15个)
  • 总测试数量: 从 196 个增加到 224 个 rule_engine_test 测试用例

Adapter 缓存机制优化

  • 核心功能: 基于 adapter ID 的缓存机制,提升重复匹配性能
    • 使用 std::atomic<uint64_t> 生成唯一 adapter ID
    • 使用 std::weak_ptr 检测 adapter 生命周期
    • 使用 luaL_ref/lua_rawgeti 在 Lua registry 中缓存转换后的 table
    • 支持两种缓存清理策略:Never(永不清理)和 Aggressive(积极清理)
  • 性能优化:
    • 同一 adapter 多次匹配时,直接从缓存获取 table,避免重复转换
    • weak_ptr 自动检测 adapter 是否被释放,释放后自动清理缓存
    • 大幅提升重复匹配场景的性能(2-10x 提升)
  • 实现细节:
    • match_rule() 执行流程:
      1. 检查 adapter ID 是否在缓存中
      2. 检查 weak_ptr 是否还有效
      3. 如果有效,直接从 Lua registry 获取缓存的 table
      4. 如果无效,清理过期缓存,重新转换并缓存
      5. 调用 execute_commands() 应用字段修改
    • execute_commands()BasicDataAdapter 实现,应用 set/remove/clear_fields 操作
  • 测试覆盖: 新增 5 个缓存生命周期测试
    • Adapter 销毁后缓存自动清理
    • 多个 adapter 独立缓存
    • weak_ptr 过期检测
    • Aggressive 清理策略
  • API 变更:
    • match_rule() 现在接受 std::shared_ptr<DataAdapter> 而非引用
    • match_all_rules() 现在接受 std::shared_ptr<DataAdapter> 而非引用
    • 所有使用 adapter 的地方都需要使用 std::make_shared<JsonAdapter>(data)

RuleEngineWrapper - 多线程安全包装器

  • 核心功能: 提供线程安全的规则引擎访问,支持热更新
    • 新增 RuleEngineWrapper 类,封装多线程访问逻辑
    • 使用 Copy-on-Write 模式:shared_ptr + 原子操作
    • Thread-Local Storage:每个线程维护独立的引擎副本
    • Versioning:通过版本号判断是否需要重新克隆
    • Shared Ownership:使用 shared_ptr 确保旧引擎在被使用时不会被销毁
  • API 设计
    • set_template_engine(std::shared_ptr<RuleEngine>): 设置模板引擎(线程安全)
    • get_engine(): 获取线程本地引擎,返回 shared_ptr<const RuleEngine>
    • get_version(): 获取当前全局版本号
  • Const 正确性
    • 返回 shared_ptr<const RuleEngine>,只能调用 const 方法
    • 防止调用配置方法(add_rule, register_function 等)
    • 允许调用查询方法(match_rule, has_rule, get_rule_count 等)
  • 使用场景
    • 多线程服务(如 brpc):每个请求线程安全访问引擎
    • 支持热更新:无需重启服务,运行时更新规则配置
    • 引擎本身非线程安全,通过包装器实现线程安全
  • shared_ptr 安全性
    • 旧引擎的 shared_ptr 在热更新后仍然有效
    • 自动管理生命周期,所有引用释放后自动销毁
    • 不会出现悬空指针或内存泄漏
  • 性能特性
    • 首次调用 get_engine() 需要克隆模板引擎(开销较大)
    • 后续调用直接返回 shared_ptr 拷贝(开销极小,< 1 微秒)
    • 热更新后,各线程下次调用时自动克隆新版本
  • 测试覆盖: 新增 15 个包装器测试用例
    • 基础功能测试(4个)
    • shared_ptr 安全性测试(2个)
    • 热更新测试(2个,包含并发场景)
    • 线程本地存储测试(2个)
    • 并发压力测试(2个)
    • 边界情况测试(2个)
    • 性能测试(1个)
  • 总测试数量: 从 325 个增加到 340 个测试用例(+15个)
  • 文档更新:
    • 在 README.md 中添加 "RuleEngineWrapper" 章节
    • 包含完整的 API 使用示例和多线程场景说明
    • 在 ARCHITECTURE.md 中更新分层架构图
    • 在 TESTING.md 中添加包装器测试分类
    • 在 CHANGELOG.md 中记录此重要新增功能

[未发布] - 2026-01

新增 (Added)

引擎克隆功能

  • 核心功能: 支持规则引擎克隆,可选择性复制规则、Lua 文件、C++ 函数
    • 新增 clone() 方法,支持通过 CloneOption 枚举选择性克隆
    • CloneOption 枚举:NONE, LUA_FILES, CPP_FUNCTIONS, CPP_MEMBER_FUNCTIONS, RULES, ALL
    • 支持按位或组合多个选项(如 RULES | LUA_FILES
    • 便捷方法:clone_rules(), clone_lua_files(), clone_cpp_functions(), clone_safe()
  • 克隆独立性
    • 克隆的引擎拥有独立的 Lua 状态
    • 修改克隆引擎不影响原引擎
    • C++ 成员函数使用相同的实例指针
  • 使用场景
    • 多线程环境:每个线程使用独立的克隆引擎
    • 批量处理隔离:为每个批次创建独立引擎
    • 测试和调试:克隆引擎用于测试,不影响生产环境
  • 测试覆盖: 新增 43 个克隆功能测试用例
    • 基本克隆测试(6个:NONE, RULES, LUA_FILES, CPP_FUNCTIONS, CPP_MEMBER_FUNCTIONS, ALL)
    • 便捷方法测试(4个)
    • 组合选项测试(3个)
    • 错误处理测试(2个)
    • 独立性测试(3个)
    • 多次克隆测试(2个)
    • 边界情况测试(5个)
    • 复杂场景测试(7个)
    • 功能验证测试(11个)
  • 总测试数量: 从 282 个增加到 325 个测试用例(+43个)
    • rule_engine_test: 从 143 个增加到 186 个测试用例
  • 文档更新:
    • 在 README.md 中添加 "引擎克隆" 章节
    • 包含完整的 API 使用示例
    • 提供多种使用场景说明
    • 在 ARCHITECTURE.md 和 TESTING.md 中更新相关内容

C++ 异常处理测试和文档

  • 异常处理测试: 新增 7 个 C++ 异常处理相关测试用例
    • C++ 函数抛出异常的演示测试(使用 pcall 捕获)
    • C++ 函数抛出异常测试(不使用 pcall,验证 match_rule 失败)
    • C++ 函数安全捕获异常测试(3个场景:正常输入、负数、缺少参数)
    • 类成员函数异常处理测试
    • 异常处理最佳实践测试
    • 直接调用(不使用 pcall)测试
    • 多函数异常处理测试
  • 重要发现: LuaJIT 可以捕获 C++ 异常,程序不会崩溃!
    • 通过实际测试验证:注册的 C++ 函数抛出异常不会导致程序崩溃
    • LuaJIT 将 C++ 异常转换为简短的错误信息 "C++ exception"
    • 使用 pcall 和不使用 pcall 的行为差异已文档化
  • 文档更新: 在 README.md 和 ARCHITECTURE.md 中添加详细的异常处理说明
    • 说明 LuaJIT 可以安全捕获 C++ 异常
    • 提供两种场景(使用/不使用 pcall)的详细对比
    • 强调虽然安全,但错误信息会丢失
    • 提供正确的异常捕获和转换示例
    • 添加异常处理流程对比表
    • 包含完整的最佳实践指南
  • 总测试数量: 从 266 个增加到 273 个测试用例(+7个)
    • rule_engine_test: 从 127 个增加到 134 个测试用例

Lua 公共函数加载功能

  • 核心功能: 支持加载 Lua 公共函数文件,方便业务逻辑快速迭代
    • 新增 RuleEngine::add_lua_file() 方法
    • 用户可以在 Lua 文件中自由定义全局变量和函数
    • 支持自定义命名空间(utils, validators, helpers 等)
    • 支持加载多个文件,后加载的文件会覆盖同名变量
    • 支持与 C++ 注册函数混合使用
  • 测试覆盖: 新增 9 个 Lua 公共函数加载测试用例
    • utils 命名空间测试(3个场景)
    • 多命名空间测试(validators + helpers)
    • 全局函数测试
    • 与 C++ 函数混合使用测试
    • 错误处理测试(文件不存在、语法错误、运行时错误)
    • 覆盖已存在函数测试
  • 总测试数量: 从 273 个增加到 282 个测试用例(+9个)
    • rule_engine_test: 从 134 个增加到 143 个测试用例
  • 文档更新:
    • 在 README.md 中添加 "Lua 公共函数加载" 章节
    • 包含完整的 API 使用示例
    • 提供多个命名空间的使用示例
    • 说明注意事项和最佳实践
    • 在 ARCHITECTURE.md 和 TESTING.md 中更新相关内容

改进 (Changed)

call_match_function 错误处理增强

  • 问题修复: 修复了 call_match_function 中所有错误返回路径未设置 result 字段的问题
    • 规则函数表不存在:现在设置 result.matched = falseresult.message
    • 规则函数不存在:现在设置 result.matched = falseresult.message
    • 数据适配器失败:现在设置 result.matched = falseresult.message
    • Lua pcall 失败(包括 C++ 异常):现在设置 result.matched = falseresult.message
    • 返回值类型错误:现在设置 result.matched = falseresult.message
  • 错误信息同步: 所有错误路径同时设置 result.messageerror_msg 参数,保持一致
  • 格式统一: lua_pcall 失败的错误信息使用 "Failed to call match: " 前缀,与批量匹配版本保持一致
  • 改进效果:
    • 调用者可以通过 result.message 获取详细错误信息,即使 match_rule() 返回 false
    • 提升了调试体验和错误追踪能力
    • 确保 result.matched 始终正确反映匹配状态

C++ 函数注册功能

  • 函数注册机制: 支持将 C++ 函数注册到 Lua 的全局 ljre 命名空间
    • 注册普通 C++ 函数到 Lua
    • 注册类成员函数到 Lua(通过静态分发器模式)
    • 使用 lua_pushcclosurelua_pushlightuserdata 实现
    • 所有注册函数存储在全局 ljre 表中,避免命名空间污染
  • 函数管理功能:
    • register_function(): 注册函数(支持普通函数和类成员函数)
    • unregister_function(): 注销指定函数
    • clear_registered_functions(): 清空所有已注册函数
    • has_function(): 检查函数是否已注册
    • get_registered_functions(): 获取所有已注册函数名列表
  • 函数在规则中使用:
    • Lua 规则可通过 ljre.function_name() 调用注册的 C++ 函数
    • 支持无返回值、单返回值、多返回值的 C++ 函数
    • 支持在规则中调用多个注册函数
    • 函数在规则热更新后保持有效(持久化)
    • 支持错误处理和栈平衡管理

函数注册测试覆盖

  • 测试数量: 新增 30 个函数注册相关测试用例
    • 普通 C++ 函数注册测试(2个)
    • 类成员函数注册测试(3个)
    • 函数管理测试(4个)
    • 函数在规则中使用测试(6个)
    • 多函数协同测试(3个)
    • 错误处理和边界情况测试(6个)
    • 无效状态下的函数操作测试(6个)
  • 总测试数量: 从 236 个增加到 266 个测试用例(+30个)
    • rule_engine_test: 从 103 个增加到 127 个测试用例

边界情况测试增强

  • match_all_rules 边界情况测试: 新增 7 个测试用例
    • push_to_lua 失败场景测试
    • 函数表不存在场景测试
    • 函数不存在场景测试
    • 第一个返回值不是布尔值场景测试
    • 第二个返回值不是字符串场景测试(使用空消息)
    • 混合错误场景测试
    • 只有错误场景测试
  • 总测试数量: 从 228 个增加到 236 个测试用例

改进 (Changed)

返回值类型检查优化

  • 精确类型检查: 使用 lua_type() 代替 lua_isstring()
    • 修复 lua_isstring() 对数字返回 true 的问题(因为 Lua 会自动转换数字为字符串)
    • 现在只有精确的 LUA_TSTRING 类型才会被当作字符串处理
    • 数字、nil 等类型不再被误判为字符串
  • 统一行为: match_all_rulesmatch_rule 的返回值处理逻辑完全一致
    • 当第二个返回值不是字符串时,message 字段为空字符串
    • 不再使用默认消息 "Matched" 或 "Not matched"

测试更新

  • 更新 MatchAllRules_SecondReturnNotString 测试用例
    • 测试名称改为 MatchAllRules_SecondReturnNotString_UsesEmptyMessage
    • 验证 message 为空字符串而非包含 "Matched"
  • 所有 236 个测试用例全部通过

文档更新 (Documentation)

  • 更新 README.md:
    • 更新 match 函数返回值说明
    • 明确第二个返回值必须是精确的 string 类型
    • 更新注意事项,说明非字符串类型的处理方式
  • 更新 ARCHITECTURE.md:
    • 更新返回值说明
    • 添加类型检查细节
  • 更新 CHANGELOG.md:
    • 记录类型检查优化
    • 记录测试用例增加

[未发布] - 2025-01

新增 (Added)

LuaState 功能增强

  • JIT 动态控制: 新增 JIT 编译器的运行时控制功能
    • enable_jit(): 启用 JIT 编译引擎
    • disable_jit(): 禁用 JIT 编译引擎,切换到解释模式
    • flush_jit(): 刷新 JIT 编译器缓存,清除已编译的代码
  • 支持 LuaJIT jit 库的自动加载
  • JIT 控制方法支持无效 Lua 状态检测(返回 false)

JsonAdapter 深度嵌套限制功能

  • 最大嵌套深度控制: 防止深度嵌套 JSON 导致栈溢出和性能问题
    • 默认最大深度: 8192 层
    • 可通过构造函数参数和 set_max_nesting_depth() 方法配置
    • 深度限制范围: [1, 8192]
    • 超过深度限制时自动截断子元素为 nil
  • 深度限制验证:
    • set_max_nesting_depth() 自动限制在有效范围内
    • 超过最大值时限制为 8192
    • 小于最小值时限制为 1

测试覆盖率大幅提升

  • LuaState 测试: 52 个测试用例
    • JIT 控制相关测试(enable/disable/flush)
    • 错误处理测试(覆盖栈顶非字符串场景)
  • JsonAdapter 测试: 从 35 个增加到 55 个测试用例(+20个)
    • 深度嵌套限制测试(9个测试用例)
      • 默认深度值测试(MAX_NESTING_DEPTH = 8192)
      • 深度设置和边界测试(最小值 1,最大值 8192)
      • 深度超限截断测试(对象和数组)
      • 浅层嵌套完整转换测试
      • 深层数组嵌套截断测试
    • 异常处理测试(自定义 ExceptionThrowingDataAdapter)
    • 边界条件测试(深度嵌套、大量数据、混合类型)
    • 完整覆盖异常捕获和错误传播路径
  • RuleEngine 测试: 从 43 个增加到 89 个测试用例(+46个)
    • JIT 控制测试(11个测试用例)
      • enable_jit/disable_jit/flush_jit 功能测试
      • JIT 状态切换测试(多次切换)
      • JIT 性能影响测试(验证结果一致性)
      • 多规则 JIT 控制测试
      • 无效 Lua 状态下的 JIT 控制测试(3个)
    • Lua 状态无效场景测试
    • 完整覆盖 call_match_function 所有错误路径
    • 规则配置文件边界条件测试
  • Integration 测试: 从 11 个增加到 15 个测试用例(+4个)
    • 深度嵌套限制集成测试(4个)
      • 深层对象嵌套截断测试
      • 深层数组嵌套截断测试
      • 安全访问模式测试(and 短路、pcall、逐层检查)
      • 深度限制下的规则执行测试
  • 总测试数量: 从 138 个增加到 228 个测试用例(+65%)

改进 (Changed)

代码质量优化

  • 移除 RuleRuleInfo 结构体中不必要的 loaded 成员
    • 规则在 map 中存在即表示已加载,简化状态管理
    • 减少了不必要的复杂度

错误处理增强

  • 完善了 LuaState::get_error_string() 对各种栈顶类型的处理
    • 正确处理 table、boolean、nil、function、userdata、thread 等非字符串类型
    • 栈顶非字符串时返回 "Unknown error" 且不弹出栈元素
  • JIT 控制方法在无效 Lua 状态下返回 false,而不是崩溃

性能优化

  • 深度嵌套 JSON 处理性能大幅提升
    • 10000 层嵌套:从 10+ 秒优化到微秒级(超限时截断)
    • 50000 层嵌套:从崩溃优化到正常处理(超限时截断)
    • 默认支持 8192 层完整转换
  • 最新性能测试结果(2026-01-12):
    • 简单规则:LuaJIT 1.04 μs vs Native 0.36 μs(2.85x 慢)
    • 中等规则:LuaJIT 4.54 μs vs Native 7.82 μs(快 1.72x)
    • 复杂规则:LuaJIT 20.57 μs vs Native 18.48 μs(1.11x 慢)
    • 超复杂规则:LuaJIT 92.63 μs vs Native 26.38 μs(3.51x 慢)
    • JIT 启用后性能提升 4.5%(1.20 μs → 1.18 μs)
    • 关键发现:中等复杂度规则性能优于 Native 实现,这是 LuaJIT 的最佳应用场景

测试辅助工具

  • 新增 ExceptionThrowingDataAdapter 用于测试异常处理路径
  • 新增 RuleEngineInternalTest 测试子类,支持访问内部 Lua 状态
  • 新增 RuleEngineInvalidStateTest 测试子类,支持模拟无效 Lua 状态
  • 新增 RuleEngineWithInvalidState 测试辅助类,用于测试无效状态下的 JIT 控制

文档更新 (Documentation)

  • 更新 README.md:
    • 反映最新的测试用例数量(228 个)
    • 更新特性列表,添加深度嵌套限制和 JIT 控制功能
    • 详细列出各测试文件的测试类别,包括新增的深度限制和 JIT 控制测试
    • 更新性能测试结果(2026-01-12)
      • 中等规则:从"1.01x 慢"更新为"快 1.72x"
      • 复杂规则:从"2.88x 慢"更新为"1.11x 慢"
      • 超复杂规则:从"11.61x 慢"更新为"3.51x 慢"
      • 简单规则:从"4.86x 慢"更新为"2.85x 慢"
  • 更新 TESTING.md:
    • 更新测试统计表格(228 个测试用例)
    • 详细说明各测试模块的覆盖范围
    • 添加深度嵌套限制测试分类
    • 添加 JIT 控制测试分类
  • 更新 ARCHITECTURE.md:
    • 更新测试数量(228 个)
    • 更新测试覆盖表格
  • 更新 CHANGELOG.md:
    • 记录所有重要变更
    • 添加最新性能测试结果

测试覆盖率详情

LuaState (52 个测试)

  • ✅ 构造和析构:移动语义、自我赋值
  • ✅ 文件加载:成功/失败/语法错误/运行时错误
  • ✅ Buffer 加载:各种代码格式和大小
  • ✅ 错误处理:栈顶各种类型(string、number、table、boolean、nil、function、userdata、thread)
  • ✅ 栈操作:栈平衡检查
  • ✅ 安全性:禁用 io 库、状态独立性
  • ✅ 边界条件:零大小、超大代码、Unicode 路径
  • ✅ JIT 控制:enable/disable/flush 及各种组合场景

LuaStackGuard (17 个测试)

  • ✅ 基本功能:栈恢复、多次 push/pop
  • ✅ 嵌套场景:多层守卫嵌套
  • ✅ Release 机制:手动释放、多次调用
  • ✅ 空栈处理:栈为空时的行为
  • ✅ 函数调用场景:实际使用模式
  • ✅ 表迭代场景:遍历表时的栈管理
  • ✅ 错误处理:异常情况下的栈恢复

JsonAdapter (46 个测试)

  • ✅ 基本类型:null、boolean、integer、float、string
  • ✅ 数组转换:空数组、嵌套数组、大数组、混合类型
  • ✅ 对象转换:空对象、嵌套对象、大量键、特殊键
  • ✅ 特殊字符:含空字符字符串、Unicode 字符、特殊字符键
  • ✅ 异常处理:标准异常捕获、错误消息生成、无 error_msg 场景
  • ✅ 边界条件:深度嵌套(500+ 层)、1000 个键的大对象
  • ✅ 栈平衡:成功和失败时的栈平衡保证

RuleEngine (78 个测试)

  • ✅ 规则管理:添加、移除、重载、清空规则
  • ✅ 配置加载:从配置文件加载规则列表
  • ✅ 规则匹配:单个规则匹配、所有规则匹配
  • ✅ 错误场景:无效状态、规则不存在、规则函数表不存在、match 函数不存在
  • ✅ 返回值验证:非布尔返回值、单返回值
  • ✅ 数据适配器:push_to_lua 失败场景
  • ✅ 边界条件:空配置、重复规则、无效字段

Integration Test (11 个测试)

  • ✅ 端到端工作流:完整的规则引擎使用流程
  • ✅ 用户注册验证:实际业务场景模拟
  • ✅ 规则动态管理:运行时添加/删除规则
  • ✅ 多引擎独立:多个引擎实例互不干扰
  • ✅ 复杂数据结构:嵌套对象和数组
  • ✅ 大数据集处理:大量规则和数据

技术债务 (Technical Debt)

废弃 (Deprecated)

移除 (Removed)

安全性 (Security)

无安全相关问题修复

已知问题 (Known Issues)

升级指南 (Migration Guide)

从旧版本升级

如果你是从之前的版本升级,请注意以下变更:

  1. 规则结构变更:

    • RuleInfo 结构体不再包含 loaded 字段
    • 规则引擎内部也不再跟踪 loaded 状态
    • 这不影响公共 API,仅影响内部实现
  2. JIT 功能:

    • LuaState 现在会自动加载 jit 库
    • 可以通过 enable_jit()/disable_jit() 动态控制 JIT
    • 默认情况下 JIT 是启用的
  3. 测试要求:

    • 所有新增测试必须通过
    • 代码覆盖率要求 ≥85%

版本命名规范

本项目遵循语义化版本 (Semantic Versioning) 规范:

  • 主版本号: 不兼容的 API 修改
  • 次版本号: 向下兼容的功能性新增
  • 修订号: 向下兼容的问题修正