Skip to content

fix: FakeFish pitfalls — mysql callbacks, JIT const, json arrays, pool lease, net send - #20

Open
esrrhs wants to merge 1 commit into
masterfrom
fix/pitfalls-callbacks-const-json-pool
Open

esrrhs wants to merge 1 commit into
masterfrom
fix/pitfalls-callbacks-const-json-pool

Conversation

@esrrhs

@esrrhs esrrhs commented Sep 30, 2026

Copy link
Copy Markdown
Owner

背景

FakeFish(fakelua 的真实项目方)在实战中发现 8 个问题,文档见 fakefish 仓库 docs/fakelua-pitfalls.md。本 PR 逐一修复,共 21 个文件(+776/-86)。

修复清单

P0-1 conn:query 回调传内联闭包被静默丢弃(最严重)

  • 所有 mysql 回调参数(connect/query/stmt_prepare/stmt_execute)现在支持内联闭包(VarClosure*),闭包可捕获上下文;全局函数名字符串继续支持。
  • 传其他类型直接抛 bad argument,不再静默丢弃。
  • 实现:ResultCallback { name, closure },派发时闭包走 DispatchCallClosure(arena 分配无 GC,裸指针安全)。

P0-2 查询失败时部分错误路径完全没有回调

  • Query/StmtPrepare/StmtExecute 的所有提前 return 路径统一设置错误并派发回调。
  • 契约:query 一旦被调用,回调恰好被调用一次。

P1-3 模块级标量多赋值点被 JIT 标 const 导致编译失败

  • 类型推断器收集"声明后有再赋值点"的文件级变量(ir.global_reassigned_vars,经 file_level_init_exps_ 判定绑定归属,对遮蔽免疫),CGen 对其发射非 const 的 static int64_t。
  • 从未再赋值的文件级常量保持 static const 优化(infer.test_global_const_int 验证不回退)。
  • 既有测试 exception.const_reassign 原本断言的就是这个 bug(期待编译失败),已按新语义更新为期待编译成功。

P1-4 连接池无租约语义导致永久泄漏

  • 新增 pool:with(fn) 租约 API:取连接传给 fn(conn),正常返回或抛错都自动归还。
  • 同连接飞行中再 query 改为排队(每 tick 至多启动一条,避免覆盖未派发结果),不再报 "connection not ready"。
  • 连接进入错误终态时,排队的 query 逐个收到错误回调。

P1-5 json.encode 空 table 产出 {} 而非 []

  • 纯数组启发式:空 table 编码为 [];非空仍要求 1..N 连续整数键。
  • 新增 json.encode_array() 严格通道:非数组形 table 直接报错。

P1-6 回调上下文多重静默限制

  • 派发上下文(IoContext::InDispatch())中的 send 改为入队、由本轮 tick 派发完后统一泵出(事件驱动改轮询驱动),消除平台相关的静默丢弃;发送失败记 WARN 日志。
  • README 补充"回调上下文允许/禁止操作矩阵"。

P2-7 MySQL 结果值全为字符串、格式未文档化

  • 行值按列类型转换:整数列(TINY/SHORT/LONG/LONGLONG/INT24/YEAR)→ 整数,浮点/小数列 → 浮点,其余保持 string,NULL 为 nil;解析失败回退字符串。
  • SELECT / DML 结果表布局、行值类型规则写入 README(zh/en)。

P2-8 tick 泵序与嵌套回调延迟无文档

  • README 补充:泵序固定 timer → net → http → mysql → redis;回调里发起的 IO 最早下一轮 tick 可见;mysql 同连接 query 排队规则。

测试

  • 全量 1557 个测试:1545 通过;13 个失败中 12 个为需要真实 MySQL/Redis 服务器的 integration_*(本机无服务器,环境性),exception.const_reassign 已按新语义修复。
  • 新增回归测试:mysql 闭包回调恰好一次 / 非法回调类型报错 / pool:with、JIT const 多赋值点、json 空 table 与 encode_array、net 回调内 send。
  • net 新测试用 TCC 单后端驱动:C++→Lua 回调固定派发 TCC 编译的函数,文件级可变状态在各后端有独立副本(详见测试注释)。

兼容性说明

  • json.encode({}) 行为从 "{}" 变为 "[]"(本 PR 的目的);需要空对象的场景请使用带字符串键的表或自行处理。
  • mysql 行值从 string 变为对应 number 类型;tonumber(v) 对 number 原样返回,既有代码兼容。
  • 文档中 FakeFish 侧的 CI/config 两个问题按原文档说明不在 fakelua 修复范围。

…ease, net send

Fixes the 8 issues found by the FakeFish project (fakelua-pitfalls):

- P0-1: mysql callbacks now accept inline closures (VarClosure*) in
  addition to global function names; invalid callback types throw a
  loud "bad argument" instead of being silently dropped by
  CVarToString("").
- P0-2: all early-return paths in Query/StmtPrepare/StmtExecute now
  fire the callback with an error. Contract: every conn:query() call
  results in exactly one callback.
- P1-3: file-level numeric locals with reassignment points are no
  longer emitted as C const (which broke JIT compilation with
  "cannot assign to variable with const-qualified type"). Never-
  reassigned file constants keep the const optimization.
- P1-4: in-flight query on the same connection is queued instead of
  erroring; new pool:with(fn) lease API auto-returns the connection
  even when fn throws.
- P1-5: json.encode({}) now produces [] (pure-array heuristic);
  new json.encode_array() for strict array-shaped encoding.
- P1-6: sends issued inside dispatch callbacks are queued and pumped
  by the tick after dispatch completes; send failures log WARN.
- P2-7: result rows convert values by column type (int/float columns
  return numbers instead of strings); result table layout documented.
- P2-8: tick pump order and callback-context rules documented in
  native READMEs (zh/en), incl. the allowed/forbidden operation matrix.

exception.const_reassign test updated: it asserted the P1-3 bug
(compile failure); now expects successful compilation per the new
semantics. New regression tests for all the above.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant