Проблема с горячей перезагрузкой приложения Lua на Tarantool

#lua #tarantool

#lua #tarantool

Вопрос:

Я пытаюсь выполнить горячую перезагрузку модуля 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:

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

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

 connected to localhost:3301
localhost:3301> 
  

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

Вы можете подключиться к экземпляру tarantool с console помощью команды (прямо в контейнере) или tarantoolctl connect login:password@host:port (для tarantoolctl connect 3301 работы с конфигурацией по умолчанию, подробности см. Здесь) или прикрепить, а затем проверить 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
}
  

Более сложный, но правильный способ — использовать модуль перезагрузки пакета.

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

 -- 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».