tarantool как обрабатывать lua ошибок вне волокна - PullRequest
1 голос
/ 17 июня 2020

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

пример:

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. Или создайте сторожевой таймер для волокна, если я хочу, чтобы статус был действительным. Это сработает для меня, но кажется не лучшим решением.

1 Ответ

3 голосов
/ 17 июня 2020

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

В вашем примере оба волокна (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(). Примеры см. В документации.

...