[Tarantool-patches] [PATCH vshard 4/5] error: introduce from_string

Vladislav Shpilevoy v.shpilevoy at tarantool.org
Fri Dec 17 03:25:30 MSK 2021


vshard.storage.call() and most of the other vshard.storage.*
functions now raise an exception STORAGE_IS_DISABLED when the
storage is disabled.

The router wants to catch it to handle in a special way. But
unfortunately,

- error(obj) in a Lua function is wrapped into LuajitError. 'obj'
  is saved into 'message' using its __tostring meta-method.

- It is not possible to create your own error type in a sane way.

These 2 facts mean that the router needs to be able to extract
the original error from LuajitError's message. In vshard errors
are serialized into json, so a valid vshard error, such as
STORAGE_IS_DISABLED, can be extracted from LuajitError's message
if it wasn't truncated due to being too long. For this particular
error it won't happen.

The patch introduces new method vshard.error.from_string() to
perform this extraction for its further usage in router.

Part of #298
---
 test/unit/error.result   | 18 ++++++++++++++++++
 test/unit/error.test.lua |  6 ++++++
 vshard/error.lua         | 19 +++++++++++++++++++
 3 files changed, 43 insertions(+)

diff --git a/test/unit/error.result b/test/unit/error.result
index bb4e0cc..258b14f 100644
--- a/test/unit/error.result
+++ b/test/unit/error.result
@@ -48,6 +48,24 @@ test_run:grep_log('default', '"reason":"reason","code":11,"type":"ShardingError"
 ---
 - '"reason":"reason","code":11,"type":"ShardingError"'
 ...
+e = lerror.vshard(lerror.code.STORAGE_IS_DISABLED, 'any reason')
+---
+...
+e = lerror.from_string(tostring(e))
+---
+...
+assert(e.code == lerror.code.STORAGE_IS_DISABLED)
+---
+- true
+...
+assert(e.type == 'ShardingError')
+---
+- true
+...
+assert(e.message == 'Storage is disabled: any reason')
+---
+- true
+...
 --
 -- Part of gh-100: check `error.vshard`.
 --
diff --git a/test/unit/error.test.lua b/test/unit/error.test.lua
index 0a51d33..5e669b6 100644
--- a/test/unit/error.test.lua
+++ b/test/unit/error.test.lua
@@ -19,6 +19,12 @@ log = require('log')
 log.info('Log error: %s', vshard_error)
 test_run:grep_log('default', '"reason":"reason","code":11,"type":"ShardingError"')
 
+e = lerror.vshard(lerror.code.STORAGE_IS_DISABLED, 'any reason')
+e = lerror.from_string(tostring(e))
+assert(e.code == lerror.code.STORAGE_IS_DISABLED)
+assert(e.type == 'ShardingError')
+assert(e.message == 'Storage is disabled: any reason')
+
 --
 -- Part of gh-100: check `error.vshard`.
 --
diff --git a/vshard/error.lua b/vshard/error.lua
index 2b97eae..96c4bdd 100644
--- a/vshard/error.lua
+++ b/vshard/error.lua
@@ -244,6 +244,24 @@ local function make_error(e)
     end
 end
 
+--
+-- Restore an error object from its string serialization.
+--
+local function from_string(str)
+    -- Error objects in VShard are stringified into json. Hence can restore also
+    -- as json. The only problem is that the json might be truncated if it was
+    -- stored in an error message of a real error object. It is not very
+    -- reliable.
+    local ok, res = pcall(json.decode, str)
+    if not ok then
+        return nil
+    end
+    if type(res) ~= 'table' or type(res.type) ~= 'string' or
+       type(res.code) ~= 'number' or type(res.message) ~= 'string' then
+        return nil
+    end
+    return make_error(res)
+end
 
 local function make_alert(code, ...)
     local format = error_message_template[code]
@@ -266,6 +284,7 @@ return {
     box = box_error,
     vshard = vshard_error,
     make = make_error,
+    from_string = from_string,
     alert = make_alert,
     timeout = make_timeout,
 }
-- 
2.24.3 (Apple Git-128)



More information about the Tarantool-patches mailing list