Кажется, что параметр error_marshaling_enabled всегда включен - PullRequest
0 голосов
/ 27 мая 2020

Когда я запускаю этот код:

$client->evaluate('
    box.session.settings.error_marshaling_enabled = false
    box.error{code = 42, reason = "Foobar", type = "MyError"}
');

независимо от значения error_marshaling_enabled, я всегда получаю ответ с новым (расширенным) форматом ошибки:

  [
    49 => 'Foobar',
    82 => [
      0 => [
        0 => [
          0 => 'CustomError',
          2 => 3,
          1 => 'eval',
          3 => 'Foobar',
          4 => 0,
          5 => 42,
          6 => [
            'custom_type' => 'MyError',
          ],
        ],
      ],
    ],
  ],

Почему?

1 Ответ

1 голос
/ 29 мая 2020

Короткий ответ.

error_marshaling_enabled опция влияет только на то, как объекты ошибок кодируются в теле ответа (48, IPROTO_DATA). Это не влияет на то, как они возвращаются как исключения в заголовке ответа (82, IPROTO_ERROR).

Длинный ответ.

В Tarantool объект ошибки можно вернуть двумя способами: как исключение и как объект. Например, вот как вызвать ошибку как исключение:

function throw_error()
    box.error({code = 1000, reason = "Error message"})
    -- Or
    error('Some error string')
end

Вот как вернуть его как объект:

function return_error()
    return box.error.new({code = 1000, reason = "Error message"})
end

Если функция была вызвана удаленно, с использованием IPROTO протокол через соединитель, такой как netbox, или соединитель PHP, или любой другой, способ возврата ошибки влияет на то, как она кодируется в ответном пакете MessagePack. Когда функция выдает ошибку, и ошибка достигает верхнего кадра стека, не будучи обнаруженной, она кодируется как IPROTO_ERROR (82) и IPROTO_ERROR_24 (49).

Когда объект ошибки возвращается как обычное значение, а не как исключение, оно также кодируется как обычное значение внутри IPROTO_DATA (48). Так же, как строка, число, кортеж и т. Д. c.

С кодировкой IPROTO_ERROR / IPROTO_ERROR_24 не так много места для конфигурации. Формат этих значений изменить нельзя. IPROTO_ERROR всегда возвращается как карта MessagePack со стеком ошибок. IPROTO_ERROR_24 всегда является сообщением об ошибке. Поле IPROTO_ERROR_24 сохранено для совместимости с коннекторами к версиям Tarantool <2.4.1. </p>

С кодировкой в ​​составе IPROTO_DATA вы можете выбрать способ сериализации с помощью опции error_marshaling_enabled. Если это правда, ошибки кодируются как тип расширения MessagePack MP_EXT и содержат весь стек ошибок, закодированный точно так же, как значение IPROTO_ERROR. Если для параметра установлено значение false (поведение по умолчанию в 2.4.1), ошибка кодируется в виде строки MP_STR, которая является сообщением об ошибке. Если имеется стек ошибок, кодируется только самая новая ошибка.

error_marshaling_enabled существует для обратной совместимости, на случай, если ваше приложение в Tarantool хочет быть совместимым со старыми коннекторами, которые не поддерживают MP_EXT закодированные ошибки.

В Tarantool <2.4.1 ошибки кодировались в результате MessagePack в виде строки с сообщением об ошибке, а стеки ошибок вообще не существовали. Поэтому, когда были представлены новый формат и функция стеков ошибок, установка нового формата по умолчанию было бы слишком радикальным изменением, нарушающим старые соединители. </p>

Рассмотрим эти примеры того, как маршалинг ошибок влияет на результаты. Здесь я использую консоль Tarantool 2.4.1 и встроенный коннектор netbox. Приведенный ниже код можно скопировать и вставить в консоль.

Первый экземпляр:

box.cfg{listen = 3313}
box.schema.user.grant('guest', 'super')

function throw_error()
    box.error({code = 1000, reason = "Error message"})
end

function return_error()
    return box.error.new({code = 1000, reason = "Error message"})
end

Второй экземпляр:

netbox = require('net.box')
c = netbox.connect(3313)

Теперь я пытаюсь вызвать функцию на второй экземпляр:

tarantool> c:call('throw_error')
---
- error: Error message
...

c:call('throw_error') вызвал исключение. Если я поймаю его с помощью функции pcall() Lua, я увижу объект ошибки.

tarantool> ok, err = pcall(c.call, c, 'throw_error')
tarantool> err:unpack()
---
- code: 1000
  base_type: ClientError
  type: ClientError
  message: Error message
  trace:
  - file: '[string "function throw_error()..."]'
    line: 2
...

Как видите, я не устанавливал error_marshaling_enabled, но получил полную ошибку. Теперь я вызову другую функцию без исключений. Но объект ошибки не будет заполнен.

tarantool> err = c:call('return_error')
tarantool> err
---
- Error message
...
tarantool> err:unpack()
---
- error: '[string "return err:unpack()"]:1: attempt to call method ''unpack'' (a nil
    value)'
...

Ошибка была возвращена в виде простой строки, сообщения об ошибке. Не как объект ошибки. Теперь я включу маршалинг:

tarantool> c:eval('box.session.settings.error_marshaling_enabled = true')
---
...
tarantool> err = c:call('return_error')
---
...
tarantool> err:unpack()
---
- code: 1000
  base_type: ClientError
  type: ClientError
  message: Error message
  trace:
  - file: '[C]'
    line: 4294967295
...

Теперь та же функция вернула ошибку в новом формате, более функциональном.

В итоге: error_marshaling_enabled влияет только на возвращаемые ошибки. Не выкидываемые ошибки.

...