Search code examples
luatarantool

Problem with hot reloading Lua app on Tarantool


I'm trying to hot reload a Lua module but the standard way to do it doesn't seem to be working in my case.

I have created 2 simple example modules, 'app.lua' and 'test.lua', where the former one serves as an entry point to the application:

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

while 1 > 0 do
    test2.p()
end

and loads a function from the latter one:

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

return test

This application is running in a docker container build from an official Tarantool image. Let's suppose I have made changes in the code of the 'test' module, say, changed the line with print to 'print("???")'. The standard way to reload a module is to enter the tarantool console on a container and assign nil to the package.loaded['<name_module>']. However, when I type it in, the console says it's already null:

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

What am I doing wrong here?


Solution

  • You may see package.loaded['test'] == nil because you don't connect to Tarantool instance.

    Usually when you connect to Tarantool you look something like

    connected to localhost:3301
    localhost:3301> 
    

    Seems you simply enter to docker container and then run "tarantool". This way you just run new Tarantool instance that knows nothing about your application.

    You can connect to tarantool instance with console command (right in container) or tarantoolctl connect login:password@host:port (for default configuration tarantoolctl connect 3301 works, for details see here) or attach and then check package.loaded['test'] value.

    Here's a simplified approach for reloading code of your modules:

    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
    }
    

    More complex, but proper way is to use the package-reload module.

    Here's an explanation why your code didn't work:

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

    Then you do package.loaded['test'] = nil and drop a key from package.loaded table. Note, you don't drop value because you have a reference (test2 in your case) in your "app.lua" file.