Skip to content

Commit

Permalink
Make select error more informative
Browse files Browse the repository at this point in the history
Report "crud is not initialized" error if storage functions
are not defined.
Before this patch, select error description does not give
any clues about possible causes of undefined storage functions.

Part of #229
  • Loading branch information
psergee authored and DifferentialOrange committed Jun 15, 2022
1 parent 142d513 commit 182d46b
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 12 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
an user can explicitly request a full scan through by passing `fullscan=true`
to `select` or `count` options table argument in which a case a log entry will
not be created (#276).
* Make select error description more informative when merger
built-in module or tuple-merger external module is used
in case of disabled/uninit storage (#229).

### Fixed
* `crud.select()` if a condition is '<=' and it's value < `after`.
Expand Down
12 changes: 1 addition & 11 deletions crud/common/call.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ local sharding_utils = require('crud.common.sharding.utils')
local fiber_clock = require('fiber').clock

local CallError = errors.new_class('CallError')
local NotInitializedError = errors.new_class('NotInitialized')

local call = {}

Expand Down Expand Up @@ -46,16 +45,6 @@ local function wrap_vshard_err(err, func_name, replicaset_uuid, bucket_id)
return errors.wrap(err)
end

if err.type == 'ClientError' and type(err.message) == 'string' then
if err.message == string.format("Procedure '%s' is not defined", func_name) then
if func_name:startswith('_crud.') then
err = NotInitializedError:new("crud isn't initialized on replicaset: %q", replicaset_uuid)
else
err = NotInitializedError:new("Function %s is not registered", func_name)
end
end
end

if replicaset_uuid == nil then
local replicaset, _ = vshard.router.route(bucket_id)
if replicaset == nil then
Expand All @@ -67,6 +56,7 @@ local function wrap_vshard_err(err, func_name, replicaset_uuid, bucket_id)
replicaset_uuid = replicaset.uuid
end

err = utils.update_storage_call_error_description(err, func_name, replicaset_uuid)
err = errors.wrap(err)

return CallError:new(utils.format_replicaset_error(
Expand Down
19 changes: 19 additions & 0 deletions crud/common/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ local ParseOperationsError = errors.new_class('ParseOperationsError', {capture_s
local ShardingError = errors.new_class('ShardingError', {capture_stack = false})
local GetSpaceFormatError = errors.new_class('GetSpaceFormatError', {capture_stack = false})
local FilterFieldsError = errors.new_class('FilterFieldsError', {capture_stack = false})
local NotInitializedError = errors.new_class('NotInitialized')

local utils = {}

Expand Down Expand Up @@ -692,4 +693,22 @@ function utils.check_name_isident(name)
return true
end

function utils.update_storage_call_error_description(err, func_name, replicaset_uuid)
if err == nil then
return nil
end

if err.type == 'ClientError' and type(err.message) == 'string' then
if err.message == string.format("Procedure '%s' is not defined", func_name) then
if func_name:startswith('_crud.') then
err = NotInitializedError:new("crud isn't initialized on replicaset: %q",
replicaset_uuid or "Unknown")
else
err = NotInitializedError:new("Function %s is not registered", func_name)
end
end
end
return err
end

return utils
4 changes: 3 additions & 1 deletion crud/select/merger.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ local merger_lib = compat.require('tuple.merger', 'merger')

local Keydef = require('crud.compare.keydef')
local stats = require('crud.stats')
local utils = require("crud.common.utils")

local function bswap_u16(num)
return bit.rshift(bit.bswap(tonumber(num)), 16)
Expand Down Expand Up @@ -113,7 +114,8 @@ local function fetch_chunk(context, state)
-- Wait for requested data.
local res, err = future:wait_result(timeout)
if res == nil then
error(err)
local wrapped_err = errors.wrap(utils.update_storage_call_error_description(err, func_name, replicaset.uuid))
error(wrapped_err)
end

-- Decode metainfo, leave data to be processed by the merger.
Expand Down
58 changes: 58 additions & 0 deletions test/integration/select_test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1959,3 +1959,61 @@ pgroup.test_storage_nil_err_is_processed = function(g)
t.assert_str_contains(err.str, 'StorageError', 'Storage error class is preserved')
t.assert_str_contains(err.str, 'My storage error', 'Storage error msg is preserved')
end

pgroup.before_test('test_storage_uninit_select_error_text', function(g)
helpers.call_on_storages(g.cluster, function(server)
server.net_box:eval([[
local _crud = rawget(_G, '_crud')
rawset(_G, '_real_crud_select', _crud.select_on_storage)
_crud.select_on_storage = nil
]])
end)
end)

pgroup.after_test('test_storage_uninit_select_error_text', function(g)
helpers.call_on_storages(g.cluster, function(server)
server.net_box:eval([[
local _crud = rawget(_G, '_crud')
_crud.select_on_storage = rawget(_G, '_real_crud_select')
rawset(_G, '_real_crud_select', nil)
]])
end)
end)

pgroup.test_storage_uninit_select_error_text = function(g)
local obj, err = g.cluster.main_server.net_box:call('crud.select', {
'customers', {{'==', 'age', 101}}
})
t.assert_equals(obj, nil)
t.assert_str_contains(err.str, 'SelectError')
t.assert_str_contains(err.str, 'NotInitialized')
t.assert_str_contains(err.str, "crud isn't initialized on replicaset")
end

pgroup.before_test('test_storage_uninit_get_error_text', function(g)
helpers.call_on_storages(g.cluster, function(server)
server.net_box:eval([[
local _crud = rawget(_G, '_crud')
rawset(_G, '_real_crud_get', _crud.get_on_storage)
_crud.get_on_storage = nil
]])
end)
end)

pgroup.after_test('test_storage_uninit_get_error_text', function(g)
helpers.call_on_storages(g.cluster, function(server)
server.net_box:eval([[
local _crud = rawget(_G, '_crud')
_crud.get_on_storage = rawget(_G, '_real_crud_get')
rawset(_G, '_real_crud_get', nil)
]])
end)
end)

pgroup.test_storage_uninit_get_error_text = function(g)
local obj, err = g.cluster.main_server.net_box:call('crud.get', {'customers', 1})
t.assert_equals(obj, nil)
t.assert_str_contains(err.str, 'GetError')
t.assert_str_contains(err.str, 'NotInitialized')
t.assert_str_contains(err.str, "crud isn't initialized on replicaset")
end

0 comments on commit 182d46b

Please sign in to comment.