diff --git a/internal/lua/api_timer.go b/internal/lua/api_timer.go index 8173440..b48092e 100644 --- a/internal/lua/api_timer.go +++ b/internal/lua/api_timer.go @@ -83,9 +83,6 @@ type TimerManager struct { // queueClosed 队列是否已关闭 queueClosed bool - - // closed 是否已完全关闭(防止重复关闭) - closed bool } // TimerEntry 定时器条目。 @@ -366,9 +363,9 @@ func (m *TimerManager) WaitAll(timeout time.Duration) bool { // Close 关闭定时器管理器。 // // 执行顺序: -// 1. 设置停止标志,拒绝新定时器 -// 2. 优雅关闭:等待回调队列排空(5 秒超时) -// 3. 关闭调度器 LState +// 1. 设置停止标志,拒绝新定时器 +// 2. 优雅关闭:等待回调队列排空(5 秒超时) +// 3. 关闭调度器 LState // // 注意:该方法是幂等的,可安全调用多次。 func (m *TimerManager) Close() { diff --git a/internal/lua/cache.go b/internal/lua/cache.go index 15175a3..eefdaef 100644 --- a/internal/lua/cache.go +++ b/internal/lua/cache.go @@ -138,9 +138,9 @@ func (c *CodeCache) generateFileKey(path string) string { // GetOrCompileInline 获取或编译内联脚本。 // // 查找流程: -// 1. 基于脚本内容生成缓存键 -// 2. 检查缓存是否命中且未过期 -// 3. 未命中则解析并编译脚本,存入缓存 +// 1. 基于脚本内容生成缓存键 +// 2. 检查缓存是否命中且未过期 +// 3. 未命中则解析并编译脚本,存入缓存 // // 参数: // - src: Lua 源代码字符串 @@ -191,9 +191,9 @@ func (c *CodeCache) GetOrCompileInline(src string) (*glua.FunctionProto, error) // GetOrCompileFile 获取或编译文件脚本。 // // 查找流程: -// 1. 基于文件路径生成缓存键 -// 2. 检查缓存是否命中、未过期且文件未变更 -// 3. 未命中则读取文件、解析并编译,存入缓存 +// 1. 基于文件路径生成缓存键 +// 2. 检查缓存是否命中、未过期且文件未变更 +// 3. 未命中则读取文件、解析并编译,存入缓存 // // 参数: // - path: Lua 脚本文件路径 diff --git a/internal/lua/context.go b/internal/lua/context.go index d41aeeb..336313d 100644 --- a/internal/lua/context.go +++ b/internal/lua/context.go @@ -208,11 +208,11 @@ func (c *LuaContext) Exit(code int) { // // 该方法必须在请求处理结束时调用。 // 重置操作包括: -// 1. 关闭并清空协程引用 -// 2. 清空 Variables map -// 3. 截断 OutputBuffer -// 4. 重置 Phase、Exited 标记 -// 5. 清空 Engine 和 RequestCtx 引用 +// 1. 关闭并清空协程引用 +// 2. 清空 Variables map +// 3. 截断 OutputBuffer +// 4. 重置 Phase、Exited 标记 +// 5. 清空 Engine 和 RequestCtx 引用 func (c *LuaContext) Release() { if c.Coroutine != nil { c.Coroutine.Close() diff --git a/internal/lua/coroutine.go b/internal/lua/coroutine.go index 9e9fbaf..58865be 100644 --- a/internal/lua/coroutine.go +++ b/internal/lua/coroutine.go @@ -366,11 +366,11 @@ func (c *LuaCoroutine) ExecuteFile(path string) error { // executeProto 执行编译后的字节码,处理 yield/resume 循环。 // // 该函数是协程执行的核心循环: -// 1. 从 FunctionProto 创建 Lua 函数 -// 2. Resume 执行协程 -// 3. 如果 yield,调用 handleYield 处理并继续 Resume -// 4. 如果 error,记录统计并返回错误 -// 5. 如果正常结束,更新执行计数 +// 1. 从 FunctionProto 创建 Lua 函数 +// 2. Resume 执行协程 +// 3. 如果 yield,调用 handleYield 处理并继续 Resume +// 4. 如果 error,记录统计并返回错误 +// 5. 如果正常结束,更新执行计数 func (c *LuaCoroutine) executeProto(proto *glua.FunctionProto) error { fn := c.Engine.L.NewFunctionFromProto(proto) st, execErr, values := c.Engine.L.Resume(c.Co, fn) diff --git a/internal/lua/engine.go b/internal/lua/engine.go index 93ef2f9..9839ab9 100644 --- a/internal/lua/engine.go +++ b/internal/lua/engine.go @@ -7,13 +7,15 @@ // - 调度器:专用的 LState 用于定时器回调执行,实现线程隔离 // // 架构设计: -// 采用 Server 级单 LState + 请求级临时协程架构。 -// 所有请求共享一个主 LState 的全局环境,但各自拥有独立的协程状态, -// 确保请求间的数据隔离性和并发安全性。 +// +// 采用 Server 级单 LState + 请求级临时协程架构。 +// 所有请求共享一个主 LState 的全局环境,但各自拥有独立的协程状态, +// 确保请求间的数据隔离性和并发安全性。 // // 主要用途: -// 用于在 fasthttp 服务中嵌入 Lua 脚本,实现动态请求处理、 -// 负载均衡、响应过滤等可编程功能,兼容 OpenResty/ngx_lua API 语义。 +// +// 用于在 fasthttp 服务中嵌入 Lua 脚本,实现动态请求处理、 +// 负载均衡、响应过滤等可编程功能,兼容 OpenResty/ngx_lua API 语义。 // // 注意事项: // - LuaEngine 非并发安全,NewEngine/Close 应在初始化/关闭阶段调用 @@ -108,11 +110,11 @@ type EngineStats struct { // NewEngine 创建并初始化 Lua 引擎。 // // 该函数执行以下初始化步骤: -// 1. 创建主 LState,配置栈大小和内存优化选项 -// 2. 加载安全的标准库(base、table、string、math、coroutine) -// 3. 按需加载危险库(os、io),默认禁止 package 库 -// 4. 初始化字节码缓存、共享字典、定时器、location 管理器 -// 5. 执行协程池预热 +// 1. 创建主 LState,配置栈大小和内存优化选项 +// 2. 加载安全的标准库(base、table、string、math、coroutine) +// 3. 按需加载危险库(os、io),默认禁止 package 库 +// 4. 初始化字节码缓存、共享字典、定时器、location 管理器 +// 5. 执行协程池预热 // // 参数: // - config: 引擎配置,为 nil 时使用 DefaultConfig() @@ -122,11 +124,12 @@ type EngineStats struct { // - error: 初始化失败时返回错误 // // 使用示例: -// engine, err := lua.NewEngine(nil) // 使用默认配置 -// if err != nil { -// // 处理初始化错误 -// } -// defer engine.Close() +// +// engine, err := lua.NewEngine(nil) // 使用默认配置 +// if err != nil { +// // 处理初始化错误 +// } +// defer engine.Close() // // 注意事项: // - 该方法应在服务启动阶段调用,不应在请求处理路径中调用 @@ -198,10 +201,10 @@ func NewEngine(config *Config) (*LuaEngine, error) { // Close 关闭 Lua 引擎,释放所有资源。 // // 关闭顺序: -// 1. 取消引擎上下文,通知所有子 goroutine 退出 -// 2. 关闭定时器管理器(等待定时器回调排空) -// 3. 关闭共享字典管理器 -// 4. 关闭主 LState +// 1. 取消引擎上下文,通知所有子 goroutine 退出 +// 2. 关闭定时器管理器(等待定时器回调排空) +// 3. 关闭共享字典管理器 +// 4. 关闭主 LState // // 注意:该方法是幂等的,可安全调用多次。 func (e *LuaEngine) Close() { @@ -226,10 +229,10 @@ func (e *LuaEngine) Close() { // NewCoroutine 创建请求级临时协程。 // // 该方法执行以下操作: -// 1. 检查并发限制,超过最大协程数时返回错误 -// 2. 通过主 LState.NewThread() 创建底层 Lua 协程 -// 3. 从对象池中获取 LuaCoroutine 结构体(复用内存) -// 4. 设置执行上下文(含超时控制)和请求上下文 +// 1. 检查并发限制,超过最大协程数时返回错误 +// 2. 通过主 LState.NewThread() 创建底层 Lua 协程 +// 3. 从对象池中获取 LuaCoroutine 结构体(复用内存) +// 4. 设置执行上下文(含超时控制)和请求上下文 // // 参数: // - req: fasthttp 请求上下文,用于 API 访问(ngx.req、ngx.resp 等) @@ -282,10 +285,10 @@ func (e *LuaEngine) NewCoroutine(req *fasthttp.RequestCtx) (*LuaCoroutine, error // releaseCoroutine 释放协程资源并放回对象池。 // // 该方法执行以下清理操作: -// 1. 取消执行上下文和协程 -// 2. 清空所有引用字段,防止内存泄漏 -// 3. 更新活跃协程计数和关闭计数 -// 4. 将 LuaCoroutine 结构体放回对象池(仅复用内存) +// 1. 取消执行上下文和协程 +// 2. 清空所有引用字段,防止内存泄漏 +// 3. 更新活跃协程计数和关闭计数 +// 4. 将 LuaCoroutine 结构体放回对象池(仅复用内存) // // 注意:这是内部方法,外部应通过 LuaCoroutine.Close() 间接调用。 func (e *LuaEngine) releaseCoroutine(coro *LuaCoroutine) { @@ -391,11 +394,11 @@ func (e *LuaEngine) LocationManager() *LocationManager { // 该调度器 LState 仅加载安全子集库,禁止危险操作。 // // 初始化步骤: -// 1. 创建 LState(跳过默认库) -// 2. 加载安全库(base、table、string、math) -// 3. 注册安全的 API(ngx.shared、ngx.log、ngx.timer) -// 4. 创建回调队列(容量 1024) -// 5. 启动调度器 goroutine +// 1. 创建 LState(跳过默认库) +// 2. 加载安全库(base、table、string、math) +// 3. 注册安全的 API(ngx.shared、ngx.log、ngx.timer) +// 4. 创建回调队列(容量 1024) +// 5. 启动调度器 goroutine // // 返回值: // - error: 初始化失败时返回错误 @@ -522,8 +525,8 @@ func (e *LuaEngine) EnqueueCallback(entry *CallbackEntry) bool { // CloseScheduler 关闭调度器。 // // 执行以下操作: -// 1. 关闭回调队列(阻止新回调入队) -// 2. 关闭调度器 LState +// 1. 关闭回调队列(阻止新回调入队) +// 2. 关闭调度器 LState // // 注意:该方法是幂等的,可安全调用多次。 func (e *LuaEngine) CloseScheduler() { diff --git a/internal/lua/engine_test.go b/internal/lua/engine_test.go index 4dd34bf..678bfad 100644 --- a/internal/lua/engine_test.go +++ b/internal/lua/engine_test.go @@ -402,9 +402,10 @@ func TestEngineCoroutineExecutionContext(t *testing.T) { coro, err := engine.NewCoroutine(nil) require.NoError(t, err) - // 验证执行上下文已设置 + // 验证执行上下文已设置(Engine 创建的执行上下文总是存在) assert.NotNil(t, coro.ExecutionContext) - assert.NotNil(t, coro.Cancel) + // Cancel 可能为 nil(gopher-lua 的 NewThread 只有在主 LState 有 ctx 时才返回 cancel) + // ExecutionContext 由 Engine 创建,用于超时控制,这是主要需要验证的 coro.Close() } diff --git a/internal/lua/filter_writer.go b/internal/lua/filter_writer.go index 95f0db6..ed5c9da 100644 --- a/internal/lua/filter_writer.go +++ b/internal/lua/filter_writer.go @@ -8,10 +8,10 @@ // - 对象池:ResponseInterceptorPool、bufferPool 减少 GC 压力 // // 执行流程: -// 1. 启用拦截模式后,header 和 body 写入被延迟 -// 2. HeaderFilter 阶段可执行 Lua 脚本修改响应头 -// 3. BodyFilter 阶段可执行 Lua 脚本修改响应体 -// 4. Flush 时应用所有修改并发送响应 +// 1. 启用拦截模式后,header 和 body 写入被延迟 +// 2. HeaderFilter 阶段可执行 Lua 脚本修改响应头 +// 3. BodyFilter 阶段可执行 Lua 脚本修改响应体 +// 4. Flush 时应用所有修改并发送响应 // // 注意事项: // - 流式 body(SetBodyStream)无法缓冲,header filter 在设置前应用 @@ -201,10 +201,10 @@ func (ri *ResponseInterceptor) SetBodyString(body string) { // Flush 执行 header/body filter 并发送响应。 // // 执行顺序: -// 1. 执行 header filter 回调 -// 2. 应用 header 修改和删除 -// 3. 执行 body filter 回调 -// 4. 发送最终响应 +// 1. 执行 header filter 回调 +// 2. 应用 header 修改和删除 +// 3. 执行 body filter 回调 +// 4. 发送最终响应 // // 返回值: // - error: filter 执行失败时返回错误 diff --git a/internal/lua/middleware.go b/internal/lua/middleware.go index ca953c2..977242e 100644 --- a/internal/lua/middleware.go +++ b/internal/lua/middleware.go @@ -5,7 +5,8 @@ // - MultiPhaseLuaMiddleware:多阶段 Lua 中间件,支持在请求生命周期不同阶段执行不同脚本 // // 中间件执行顺序(从外到内): -// rewrite -> access -> content -> header_filter -> body_filter -> log +// +// rewrite -> access -> content -> header_filter -> body_filter -> log // // 注意事项: // - 中间件在协程创建失败时记录错误并继续执行下一处理器 @@ -142,15 +143,15 @@ func (m *LuaMiddleware) Name() string { // Process 包装请求处理器,注入 Lua 脚本执行逻辑。 // // 执行流程: -// 1. 检查中间件是否启用,未启用则直接调用 next -// 2. 创建 Lua 上下文并设置阶段 -// 3. 初始化协程(失败时记录错误并继续) -// 4. 执行 Lua 脚本文件 -// 5. 处理 ngx.exit/ngx.redirect 导致的终止(视为正常行为) -// 6. 非 ngx.exit 错误时设置 500 响应 -// 7. 刷新输出缓冲 -// 8. 如果脚本调用了 ngx.exit,不继续执行 next -// 9. 否则继续执行后续处理器 +// 1. 检查中间件是否启用,未启用则直接调用 next +// 2. 创建 Lua 上下文并设置阶段 +// 3. 初始化协程(失败时记录错误并继续) +// 4. 执行 Lua 脚本文件 +// 5. 处理 ngx.exit/ngx.redirect 导致的终止(视为正常行为) +// 6. 非 ngx.exit 错误时设置 500 响应 +// 7. 刷新输出缓冲 +// 8. 如果脚本调用了 ngx.exit,不继续执行 next +// 9. 否则继续执行后续处理器 // // 返回值: // - fasthttp.RequestHandler: 包装后的处理器 @@ -253,7 +254,8 @@ func (m *LuaMiddleware) IsEnabled() bool { // // 支持在不同请求处理阶段执行不同的 Lua 脚本。 // 阶段按逆序包装,确保执行顺序为: -// rewrite -> access -> content -> header_filter -> body_filter -> log +// +// rewrite -> access -> content -> header_filter -> body_filter -> log type MultiPhaseLuaMiddleware struct { // engine Lua 引擎实例 engine *LuaEngine @@ -317,7 +319,8 @@ func (m *MultiPhaseLuaMiddleware) AddPhase(phase Phase, scriptPath string, timeo // Process 包装请求处理器,按逆序添加各阶段中间件。 // // 执行顺序(从先到后): -// rewrite -> access -> content -> header_filter -> body_filter -> log +// +// rewrite -> access -> content -> header_filter -> body_filter -> log // // 通过在包装链中逆序注册(从 log 开始),确保实际执行时先执行 rewrite。 func (m *MultiPhaseLuaMiddleware) Process(next fasthttp.RequestHandler) fasthttp.RequestHandler {