Search code examples
tarantoolfibers

tarantool how to handle lua errors outside the fiber


I am wondering, how can i set callback on fiber error throw.

example:

local fiber = require("fiber")
local status = 0 --in my case stored in db

local function time_consuming()
    lua_error
    status = 0
end

function external_api_function()
    if status == 1 then return "already running" end

    status = 1
    fiber.create(time_consuming)
    return "started"
end

so i want to set status to 0 if time_consuming function falls. Is where any way to catch it?

I think about checking fiber:status on next api visit. Or create a watchdog for fiber, if i want status to be valid. This will work for me, but seems like not the best solution.


Solution

  • There are multiple ways to achieve your goal.

    Within your example both fibers (main and time_consuming task) share the same scope - status variable. If you change the value of the status variable in the child fiber, parent fiber will see an update. You can check this using simple snippet:

    status = 1
    fiber.create(function() status = 0 end)
    print(status) -- 0
    

    Now, to catch an exception, use pcall function. It accepts a function as a first argument, calls it and returns status as a first value following one or more function results. There is also xpcall function if you want to analyse the error being caught. It takes error handler as a second argument.

    With pcall you may change your time_consuming function like this:

    local function time_consuming()
        local ok = pcall(function() lua_error end)
        if not ok then
            status = 0
        end
    end
    

    and status will successfully updated if lua_error fails.

    But usually I consider this as a bad practice. If more fibers share the same state, it may become difficult to maintain due to uncertainty of the order of fiber execution. So for more reliable solution you may want to use interfiber communication primitives aka channels. You will be able to explicitly ask child fiber to tell you its execution status whether it succeed or not using channel:put() and channel:get() function. See documentation for examples.