Tarantool 中应用程序热重载问题

我试图对一个 Lua 模块进行热重载,但标准的方法在我的情况下似乎无法正常工作。

我创建了两个简单的示例模块,'app.lua' 和 'test.lua',前者作为应用程序的入口点:

# app.lua
test2 = require("test")

while 1 > 0 do
    test2.p()
end

并从后者加载一个函数:

# test.lua
local test = {}
function test.p()
    print("!!!")
end

return test

这个应用程序在从官方 Tarantool 镜像构建的 docker 容器中运行。假设我已经对 'test' 模块的代码进行了更改,例如将带有 print 的行更改为 'print("???")'。重新加载模块的标准方法是在容器上输入 Tarantool 控制台,并将 nil 分配给 package.loaded['<name_module>']。但是,当我输入时,控制台会显示它已经为空:

tarantool> package.loaded['test']
---
- null
...

我在这里做错了什么?

点赞
用户11592715
用户11592715

你可能会看到package.loaded['test'] == nil,因为你没有连接到 Tarantool 实例。

通常当你连接到 Tarantool 时,会看到以下提示:

connected to localhost:3301
localhost:3301>

看起来你只是输入了 Docker 容器,然后运行了 "tarantool"。这种方式只是运行了一个新的 Tarantool 实例,对你的应用程序一无所知。

你可以使用 console 命令(在容器中直接)或 tarantoolctl connect login:password@host:port(对于默认配置,tarantoolctl connect 3301 可行,有关详细信息请参见此处),或者 attach 连接到 Tarantool 实例,然后检查 package.loaded['test'] 的值。

这里有一种简化的方法来重载你模块的代码:

test2 = require("test")

local function reload()
    package.loaded['test'] = nil -- 清理模块缓存
    test2 = require('test') -- 用新代码更新 test2 的引用
end

while 1 > 0 do
    test2.p()
end

return {
   reload = reload,  -- 在你的控制台中使用 require('app').reload() 进行重载
}

更复杂但更正规的方法是使用 package-reload 模块。

这里解释一下为什么你的代码没有起作用:

-- 这里你要求 "test" 模块
-- Lua 检查 package.loaded['test'] 的值
-- 如果它为 nil,就从硬盘上物理加载文件(参见 dofile 函数)。
--
-- 好吧,你得到了一个你的 "p" 函数的表引用。
test2 = require("test")

-- 这里你已经有了 "test" 模块的引用。
-- 这是静态的,在这里你没有触摸它。
while 1 > 0 do
    test2.p()
end

然后你做了 package.loaded['test'] = nil,然后从 package.loaded 表中删除了一个键。请注意,你没有删除值,因为你在你的 "app.lua" 文件中有一个引用(在你的案例中是 test2)。

2020-09-22 07:01:00