tarantool как обрабатывать ошибки lua вне волокна

Мне интересно, как я могу установить обратный вызов при выбросе ошибки волокна.

пример:

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

поэтому я хочу установить статус на 0, если функция time_consuming падает. Есть где как его поймать?

Я думаю о проверке fiber: status при следующем посещении API. Или создайте сторожевой таймер для волокна, если я хочу, чтобы статус был действительным. Это сработает для меня, но кажется не лучшим решением.


person Vasil    schedule 17.06.2020    source источник


Ответы (1)


Есть несколько способов достичь поставленной цели.

В вашем примере оба волокна (задача main и time_consuming) имеют одну и ту же область видимости - переменную status. Если вы измените значение переменной status в дочернем волокне, родительский файбер увидит обновление. Вы можете проверить это с помощью простого фрагмента:

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

Теперь, чтобы поймать исключение, используйте функцию pcall. Он принимает функцию в качестве первого аргумента, вызывает ее и возвращает статус в качестве первого значения после одного или нескольких результатов функции. Также существует функция xpcall, если вы хотите проанализировать обнаруженную ошибку. Второй аргумент - обработчик ошибок.

С pcall вы можете изменить свою time_consuming функцию следующим образом:

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

и status будет успешно обновлен, если lua_error не удастся.

Но обычно я считаю это плохой практикой. Если несколько волокон находятся в одном и том же состоянии, это может стать трудным в обслуживании из-за неопределенности порядка выполнения волокон. Поэтому для более надежного решения вы можете использовать примитивы межволоконной связи, известные как каналы. Вы сможете явно попросить дочерний файбер сообщить вам статус своего выполнения, успешно он или нет, используя channel:put() и channel:get() функции. См. Документацию для примеров.

person RunFor    schedule 17.06.2020
comment
Также имейте в виду, что если вы хотите создать сторожевое волокно, вам необходимо реализовать цикл, который будет постоянно повторять какое-то действие. В противном случае ваш оператор будет оценен, и волокно будет мертвым сразу после возврата внутренней функции. Обычно это простой while true do ... end цикл, но могут быть вариации. Дополнительную информацию см. В fiber документации. - person RunFor; 17.06.2020