Я пытаюсь перезагрузить модуль Lua в горячем режиме, но стандартный способ сделать это, похоже, не работает в моем случае.

Я создал 2 простых примера модуля, 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

Это приложение запускается в сборке docker-контейнера из официального образа Tarantool. Предположим, я внес изменения в код модуля 'test', скажем, изменил строку с print на 'print ("???")'. Стандартный способ перезагрузки модуля - войти в консоль tarantool в контейнере и назначить nil для package.loaded['<name_module>']. Однако, когда я ввожу его, консоль сообщает, что он уже нулевой:

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

Что я здесь делаю не так?

1
user74785 22 Сен 2020 в 06:41

1 ответ

Лучший ответ

Вы можете увидеть package.loaded['test'] == nil, потому что вы не подключаетесь к экземпляру Tarantool.

Обычно при подключении к Tarantool вы выглядите примерно так:

connected to localhost:3301
localhost:3301> 

Кажется, вы просто входите в контейнер докеров и запускаете tarantool. Таким образом, вы просто запускаете новый экземпляр Tarantool, который ничего не знает о вашем приложении.

Вы можете подключиться к экземпляру tarantool с помощью команды console (прямо в контейнере) или tarantoolctl connect login:password@host:port (для конфигурации по умолчанию работает tarantoolctl connect 3301, подробности см. В здесь) или attach, а затем проверьте значение package.loaded['test'].

Вот упрощенный подход к перезагрузке кода ваших модулей:

test2 = require("test")

local function reload()
    package.loaded['test'] = nil -- clean module cache
    test2 = require('test') -- update a reference to test2 with new code
end

while 1 > 0 do
    test2.p()
end

return {
   reload = reload,  -- require('app').reload() in your console for reload
}

Более сложный, но правильный способ - использовать модуль package-reload.

Вот объяснение, почему ваш код не работал:

-- Here you require "test" module
-- Lua check package.loaded['test'] value
-- and if it's nil then physically load file
-- from disk (see dofile function).
--
-- Well, you got a reference to table with
-- your "p" function.
test2 = require("test")

-- Here you've already has a reference
-- to "test" module.
-- It's static, you don't touch it here.
while 1 > 0 do
    test2.p()
end

Затем вы делаете package.loaded['test'] = nil и сбросить ключ из таблицы package.loaded. Обратите внимание: вы не теряете ценность, потому что у вас есть ссылка (test2 в вашем случае) в вашем файле "app.lua".

1
Konstantin Nazarov 22 Сен 2020 в 15:18