Top.Mail.Ru
Tarantool » latest » Справочники » Справочник по встроенным модулям » Модуль box » Вложенный модуль box.error
 

Вложенный модуль box.error

Вложенный модуль box.error

Общие сведения

Функция box.error предназначена для вызова ошибки. Разница между этой функцией и встроенной Lua-функцией error в том, что когда клиент получает ошибку, код ошибки сохраняется. В отличие от этого, ошибки в Lua всегда передаются на клиент в виде ER_PROC_LUA.

Указатель

Ниже приведен перечень всех функций модуля box.error.

Имя Назначение
box.error() Выдача ошибки
box.error.last() Получение описания последней ошибки
box.error.clear() Очистка записи об ошибках
box.error.new() Создание ошибки без выдачи
box.error.set() Запись ошибки в box.error.last()
error_object.prev Возврат предыдущей ошибки
error_object.set_prev() Установка предыдущей ошибки
Custom error types Создание пользовательского типа ошибок
box.error()

При вызове без аргументов box.error() повторно вызывает последнюю ошибку.

box.error{reason = string[, code = number]}

Выдача ошибки. При вызове с аргументом из Lua-таблицы значения параметров code и reason будут любыми по желанию пользователя. Результатом будут эти значения.

Параметры:
  • reason (string) – (строка) описание ошибки, задается пользователем
  • code (integer) – (целое число) числовой код ошибки, задается пользователем
box.error(code, errtext[, errtext ...])

Выдача ошибки. Моделирование ошибки запроса с текстом на основе одной из ошибок Tarantool’а, заданных в файле errcode.h в исходном дереве. Lua-постоянные, которые соответствуют этим ошибкам в Tarantool’е, определяются как элементы box.error, например box.error.NO_SUCH_USER == 45.

Параметры:
  • code (number) – номер предварительно заданной ошибки
  • errtext(s) (string) – часть сообщения, которое сопровождает ошибку

Пример:

сообщение NO_SUCH_USER = «User '%s' is not found» (пользователь не найден) – оно включает в себя компонент «%s», который будет заменен значением параметра errtext. Таким образом, вызов box.error(box.error.NO_SUCH_USER, 'joe') или box.error(45, 'joe') приведет к ошибке с сообщением «User 'joe' is not found» (пользователь „joe“ не найден).

Исключение:то, что указано в номере errcode.
box.error(code, errtext[, errtext ...])

box.error() может принимать два типа аргументов:

  • код ошибки и ее причину/текст (box.error{code = 555, reason = 'Arbitrary message'}),
  • либо объект ошибки (box.error(err)).

В обоих случаях ошибка будет записана как последняя системная ошибка.

Пример:

tarantool> e1 = box.error.new({code = 111, reason = 'Сause'})
---
...
tarantool> box.error(e1)
---
- error: Сause
...
tarantool> box.error{code = 555, reason = 'Arbitrary message'}
---
- error: Arbitrary message
...
tarantool> box.error()
---
- error: Arbitrary message
...
tarantool> box.error(box.error.FUNCTION_ACCESS_DENIED, 'A', 'B', 'C')
---
- error: A access denied for user 'B' to function 'C'
...
box.error.last()

Получение описания последней ошибки в виде Lua-таблицы с 4 компонентами:

  • «code» (number) номер ошибки
  • «type» (string) C++ класс ошибки
  • «message» (string) сообщение ошибки
  • «trace» – таблица с 2 компонентами:
    • «line» (number) номер строки в исходном файле Tarantool
    • «file» (string) исходный файл Tarantool

Также, если ошибка является системной (например, из-за сбоя в сокете или в файловых операциях ввода/вывода),может добавиться пятый компонент: «errno» (number) номер ошибки в стандарте C.

тип возвращаемого значения:
 table

Для вывода таблицы используйте unpack():

tarantool> box.schema.space.create('')
---
- error: Invalid identifier '' (expected printable symbols only or it is too long)
...
tarantool> box.error.last()
---
- Invalid identifier '' (expected printable symbols only or it is too long)
...
tarantool> box.error.last():unpack()
---
- type: ClientError
  code: 70
  message: Invalid identifier '' (expected printable symbols only or it is too long)
  trace:
  - file: /tmp/tarantool-20200109-43082-1pv0594/tarantool-2.3.1.1/src/box/identifier.c
    line: 68
...
box.error.clear()

Очистка записи об ошибках, то есть функции box.error() или box.error.last() не сработают.

Пример:

tarantool> box.error.last()
---
- Invalid identifier '' (expected printable symbols only or it is too long)
...
tarantool> box.error.clear()
---
...
tarantool> box.error.last()
---
- null
...
box.error.new(code, errtext[, errtext ...])

Создает объект ошибки, но не выдает ее, как это делает box.error(). Это полезно, когда информацию об ошибке нужно сохранить, чтобы вернуться к ней позже. Чтобы явно записать ошибку как последнюю, используйте box.error.set().

Параметры:
  • code (number) – номер предварительно заданной ошибки
  • errtext(s) (string) – часть сообщения, которое сопровождает ошибку

Пример:

tarantool> e=box.error.new{code=5,reason='A',type='B'}
---
...
tarantool> e:unpack()
---
- code: 5
  base_type: CustomError
  type: B
  custom_type: B
  message: A
  trace:
  - file: '[string "e=box.error.new{code=5,reason=''A'',type=''B''}"]'
    line: 1
...
tarantool> box.error.last()
---
- null

Начиная с версии 2.4.1, стал доступен параметр session_settings, который влияет на структуру объектов ошибок. Если error_marshaling_enabled изменяется на true, то объект ошибки будет иметь тип MP_EXT и подтип MP_ERROR. Используя бинарный протокол в теле пакета, который сервер может отправить в ответ на box.error.new(), можно увидеть: код MP_EXT по спецификации MessagePack (обычно 0xc7), за которым следует код MP_ERROR (0x03), за которым следует код MP_ERROR_STACK (0x81), после которого идут все компоненты MP_ERROR_STACK (MP_ARRAY, который содержит MP_MAP, содержащий ключи MP_ERROR_MESSAGE, MP_ERROR_CODE и т.д.). Эти компоненты описаны и проиллюстрированы в разделе Дополительные типы MessagePack – Тип ERROR. Поле «type» ассоциативного массива для объекта ошибки будет иметь key = MP_ERROR_TYPE, поле «code» будет иметь key = MP_ERROR_CODE, поле «message» будет иметь key = MP_ERROR_MESSAGE.

box.error.set(error object)

Явно записывает ошибку как последнюю. Принимает объект ошибки и делает его доступным через box.error.last().

Пример:

tarantool> err = box.error.new({code = 111, reason = 'cause'})
---
...
tarantool> box.error.last()
---
- error: '[string "return tarantool> box.error.last()"]:1: attempt to compare two
    nil values'
...
tarantool> box.error.set(err)
---
...
tarantool> box.error.last()
---
- cause
...
object error_object

Ошибки можно записывать в списки. Для этого у Lua-таблицы, представляющей объект ошибки, есть поле .prev и метод e:set_prev(err).

error_object.prev

Возврат предыдущей ошибки, если она существует.

error_object:set_prev(error object)

Установка ошибки в качестве предыдущей. Принимает объект ошибки или nil.

Пример:

tarantool> e1 = box.error.new({code = 111, reason = 'some cause'})
---
...
tarantool> e2 = box.error.new({code = 111, reason = 'cause of cause'})
---
...
tarantool> e1:set_prev(e2)
---
...
tarantool> e1.prev
---
- cause of cause
...

Циклы для списков ошибок недопустимы:

tarantool> e2:set_prev(e1)
---
- error: 'builtin/error.lua:147: Cycles are not allowed'
...

Установка предыдущей ошибки подтягивает за ней ее собственные предыдущие ошибки:

-- e1 -> e2 -> e3 -> e4
e1:set_prev(e2)
e2:set_prev(e3)
e3:set_prev(e4)
e2:set_prev(e5)
-- Now there are two lists: e1->e2->e5 and e3->e4

Протокол IProto тоже поддерживает диагностику с помощью стека ошибок. Подробнее в разделе Дополнительные типы MessagePack – Тип ERROR.

Пользовательские типы ошибок

Объекты ошибок могут быть созданы двумя способами: с помощью box.error.new() и с помощью box.error().

Оба метода принимают аргументы либо в виде перечисления (code, reason, <reason string args>):

box.error(9, 'my_space', 'reason') -- error: 'Failed to create space my_space: reason'

…либо в виде Lua-таблицы ({code = code, reason = reason, ...}):

box.error({code = 9, reason = 'Failed to create space my_space: reason'})

Также можно определить свой собственный тип ошибок вместо встроенных. Для этого поместите строку со своим типом в поле type, если вы передаете аргументы в виде таблицы, или вместо параметра code при перечислении:

box.error('MyErrorType', 'Message')
box.error({type = 'MyErrorType', code = 1024, reason = 'Message'})

Или вариант без выдачи ошибки:

box.error.new('MyErrorType', 'Message')
box.error.new({type = 'MyErrorType', code = 1024, reason = 'Message'})

При указании пользовательского типа он отображается в атрибуте err.type. Когда он не указан, err.type показывает одну из встроенных ошибок, таких как 'ClientError', 'OurOfMemory' и др.

Ограничение по длине имени для пользовательского типа составляет 63 байта. Все, что длиннее этого ограничения, отсекается.

Исходный тип ошибки можно проверить, используя член err.base_type, хотя, как правило, его не следует использовать. Для пользовательских типов базовым типом является 'CustomError'.

Пример:

tarantool> e = box.error.new({type = 'MyErrorType', code = 1024, reason = 'Message'})
---
...

tarantool> e:unpack()
---
- code: 1024
trace:
- file: '[string "e = box.error.new({type = ''MyErrorType'', code..."]'
    line: 1
type: MyErrorType
custom_type: MyErrorType
message: Message
base_type: CustomError
...

Также можно использовать format string для составления сообщения об ошибке для типа 'CustomError'.

box.error('MyCustomType', 'The error reason: %s', 'some error reason')