Skip to content

Commit 1f3b28f

Browse files
crud: fix passing errors from storages for merger
Before this patch, returning any errors from storages for merger operations (`crud.select`, `crud.pairs`, `readview:select`, `readview:pairs`) had resulted in non-informative "Invalid merge source 0x556bb6885a00" errors. This patch fixes the issue by replacing error return with error throw. Part of #373
1 parent 4f148d2 commit 1f3b28f

8 files changed

+172
-20
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
1212
non-iterating indexes (#373).
1313
* Precision loss for decimal conditions in case of non-indexed fields or
1414
non-iterating indexes (#373).
15+
* Passing errors from storages for merger operations (`crud.select`,
16+
`crud.pairs`, `readview:select`, `readview:pairs`) (#423).
1517

1618
## [1.4.3] - 05-02-24
1719

crud/readview.lua

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,22 +133,22 @@ local function select_readview_on_storage(space_name, index_id, conditions, opts
133133
end
134134

135135
if space_readview == nil then
136-
return cursor, ReadviewError:new("Space %q doesn't exist", space_name)
136+
return ReadviewError:assert(false, "Space %q doesn't exist", space_name)
137137
end
138138

139139
local space = box.space[space_name]
140140
if space == nil then
141-
return cursor, ReadviewError:new("Space %q doesn't exist", space_name)
141+
return ReadviewError:assert(false, "Space %q doesn't exist", space_name)
142142
end
143143
space_readview.format = space:format()
144144

145145
local index_readview = space_readview.index[index_id]
146146
if index_readview == nil then
147-
return cursor, ReadviewError:new("Index with ID %s doesn't exist", index_id)
147+
return ReadviewError:assert(false, "Index with ID %s doesn't exist", index_id)
148148
end
149149
local index = space.index[index_id]
150150
if index == nil then
151-
return cursor, ReadviewError:new("Index with ID %s doesn't exist", index_id)
151+
return ReadviewError:assert(false, "Index with ID %s doesn't exist", index_id)
152152
end
153153

154154
local _, err = sharding.check_sharding_hash(space_name,
@@ -179,7 +179,7 @@ local function select_readview_on_storage(space_name, index_id, conditions, opts
179179
readview_index = index_readview,
180180
})
181181
if err ~= nil then
182-
return cursor, ReadviewError:new("Failed to execute select: %s", err)
182+
return ReadviewError:assert(false, "Failed to execute select: %s", err)
183183
end
184184

185185
if resp.tuples_fetched < opts.limit or opts.limit == 0 then

crud/select.lua

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,12 @@ local function select_on_storage(space_name, index_id, conditions, opts)
6161

6262
local space = box.space[space_name]
6363
if space == nil then
64-
return cursor, SelectError:new("Space %q doesn't exist", space_name)
64+
SelectError:assert(false, "Space %q doesn't exist", space_name)
6565
end
6666

6767
local index = space.index[index_id]
6868
if index == nil then
69-
return cursor, SelectError:new("Index with ID %s doesn't exist", index_id)
69+
SelectError:assert(false, "Index with ID %s doesn't exist", index_id)
7070
end
7171

7272
local _, err = sharding.check_sharding_hash(space_name,
@@ -83,7 +83,7 @@ local function select_on_storage(space_name, index_id, conditions, opts)
8383
scan_condition_num = opts.scan_condition_num,
8484
})
8585
if err ~= nil then
86-
return cursor, SelectError:new("Failed to generate tuples filter: %s", err)
86+
return SelectError:assert(false, "Failed to generate tuples filter: %s", err)
8787
end
8888

8989
-- execute select
@@ -95,7 +95,7 @@ local function select_on_storage(space_name, index_id, conditions, opts)
9595
yield_every = opts.yield_every,
9696
})
9797
if err ~= nil then
98-
return cursor, SelectError:new("Failed to execute select: %s", err)
98+
return SelectError:assert(false, "Failed to execute select: %s", err)
9999
end
100100

101101
if resp.tuples_fetched < opts.limit or opts.limit == 0 then

test/integration/pairs_readview_test.lua

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -895,11 +895,13 @@ local function read_impl(cg, space, conditions, opts)
895895
local status, resp = pcall(function()
896896
return rv:pairs(space, conditions, opts):totable()
897897
end)
898-
t.assert(status, resp)
899-
900898
rv:close()
901899

902-
return resp, nil
900+
if status then
901+
return resp, nil
902+
else
903+
return nil, resp
904+
end
903905
end, {space, conditions, opts})
904906
end
905907

@@ -919,3 +921,17 @@ for case_name_template, case in pairs(gh_373_types_cases) do
919921
case(g, read_impl)
920922
end
921923
end
924+
925+
pgroup.before_test(
926+
'test_pairs_merger_process_storage_error',
927+
read_scenario.before_merger_process_storage_error
928+
)
929+
930+
pgroup.test_pairs_merger_process_storage_error = function(g)
931+
read_scenario.merger_process_storage_error(g, read_impl)
932+
end
933+
934+
pgroup.after_test(
935+
'test_pairs_merger_process_storage_error',
936+
read_scenario.after_merger_process_storage_error
937+
)

test/integration/pairs_test.lua

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -904,9 +904,12 @@ local function read_impl(cg, space, conditions, opts)
904904
local status, resp = pcall(function()
905905
return crud.pairs(space, conditions, opts):totable()
906906
end)
907-
t.assert(status, resp)
908907

909-
return resp, nil
908+
if status then
909+
return resp, nil
910+
else
911+
return nil, resp
912+
end
910913
end, {space, conditions, opts})
911914
end
912915

@@ -926,3 +929,17 @@ for case_name_template, case in pairs(gh_373_types_cases) do
926929
case(g, read_impl)
927930
end
928931
end
932+
933+
pgroup.before_test(
934+
'test_pairs_merger_process_storage_error',
935+
read_scenario.before_merger_process_storage_error
936+
)
937+
938+
pgroup.test_pairs_merger_process_storage_error = function(g)
939+
read_scenario.merger_process_storage_error(g, read_impl)
940+
end
941+
942+
pgroup.after_test(
943+
'test_pairs_merger_process_storage_error',
944+
read_scenario.after_merger_process_storage_error
945+
)

test/integration/read_scenario.lua

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,12 @@ local function gh_418_read_with_secondary_noneq_index_condition(cg, read)
5050
-- iterator had erroneously expected tuples to be sorted by `last_login`
5151
-- index while iterating on `city` index. Before the issue had beed fixed,
5252
-- user had received only one record instead of two.
53-
local result = read(cg,
53+
local result, err = read(cg,
5454
'logins',
5555
{{'=', 'city', 'Tatsumi Port Island'}, {'<=', 'last_login', 42}},
5656
{bucket_id = PINNED_BUCKET_NO}
5757
)
58+
t.assert_equals(err, nil)
5859

5960
if type(result) == 'number' then -- crud.count
6061
t.assert_equals(result, 2)
@@ -546,8 +547,91 @@ for space_kind, space_option in pairs(datetime_condition_space_options) do
546547
end
547548
end
548549

550+
551+
local function before_merger_process_storage_error(cg)
552+
helpers.call_on_storages(cg.cluster, function(server)
553+
server:exec(function()
554+
local space
555+
if box.info.ro == false then
556+
space = box.schema.space.create('speedy_gonzales', {if_not_exists = true})
557+
558+
space:format({
559+
{name = 'id', type = 'unsigned'},
560+
{name = 'bucket_id', type = 'unsigned'},
561+
})
562+
563+
space:create_index('pk', {
564+
parts = {'id'},
565+
if_not_exists = true,
566+
})
567+
568+
space:create_index('bucket_id', {
569+
parts = {'bucket_id'},
570+
unique = false,
571+
if_not_exists = true,
572+
})
573+
end
574+
575+
local real_select_impl = rawget(_G, '_crud').select_on_storage
576+
rawset(_G, '_real_select_impl', real_select_impl)
577+
578+
local real_select_readview_impl = rawget(_G, '_crud').select_readview_on_storage
579+
rawset(_G, '_real_select_readview_impl', real_select_readview_impl)
580+
581+
-- Drop right before select to cause storage-side error.
582+
-- Work guaranteed only with mode = 'write'.
583+
local function erroneous_select_impl(...)
584+
if box.info.ro == false then
585+
space:drop()
586+
end
587+
588+
return real_select_impl(...)
589+
end
590+
rawget(_G, '_crud').select_on_storage = erroneous_select_impl
591+
592+
-- Close right before select to cause storage-side error.
593+
-- Work guaranteed only with mode = 'write'.
594+
local function erroneous_select_readview_impl(space_name, index_id, conditions, opts)
595+
local list = box.read_view.list()
596+
597+
for k,v in pairs(list) do
598+
if v.id == opts.readview_id then
599+
list[k]:close()
600+
end
601+
end
602+
603+
return real_select_readview_impl(space_name, index_id, conditions, opts)
604+
end
605+
rawget(_G, '_crud').select_readview_on_storage = erroneous_select_readview_impl
606+
end)
607+
end)
608+
end
609+
610+
local function merger_process_storage_error(cg, read)
611+
local _, err = read(cg, 'speedy_gonzales', {{'==', 'id', 1}})
612+
t.assert_not_equals(err, nil)
613+
614+
local err_msg = err.err or tostring(err)
615+
t.assert_str_contains(err_msg, "Space \"speedy_gonzales\" doesn't exist")
616+
end
617+
618+
local function after_merger_process_storage_error(cg)
619+
helpers.call_on_storages(cg.cluster, function(server)
620+
server:exec(function()
621+
local real_select_impl = rawget(_G, '_real_select_impl')
622+
rawget(_G, '_crud').select_on_storage = real_select_impl
623+
624+
local real_select_readview_impl = rawget(_G, '_real_select_readview_impl')
625+
rawget(_G, '_crud').select_readview_on_storage = real_select_readview_impl
626+
end)
627+
end)
628+
end
629+
549630
return {
550631
gh_418_read_with_secondary_noneq_index_condition = gh_418_read_with_secondary_noneq_index_condition,
551632
gh_373_read_with_decimal_condition_cases = gh_373_read_with_decimal_condition_cases,
552633
gh_373_read_with_datetime_condition_cases = gh_373_read_with_datetime_condition_cases,
634+
before_merger_process_storage_error = before_merger_process_storage_error,
635+
merger_process_storage_error = merger_process_storage_error,
636+
after_merger_process_storage_error = after_merger_process_storage_error,
553637
}

test/integration/select_readview_test.lua

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2493,11 +2493,13 @@ local function read_impl(cg, space, conditions, opts)
24932493
t.assert_equals(err, nil)
24942494

24952495
local resp, err = rv:select(space, conditions, opts)
2496-
t.assert_equals(err, nil)
2497-
24982496
rv:close()
24992497

2500-
return crud.unflatten_rows(resp.rows, resp.metadata)
2498+
if err ~= nil then
2499+
return nil, err
2500+
end
2501+
2502+
return crud.unflatten_rows(resp.rows, resp.metadata), nil
25012503
end, {space, conditions, opts})
25022504
end
25032505

@@ -2517,3 +2519,17 @@ for case_name_template, case in pairs(gh_373_types_cases) do
25172519
case(g, read_impl)
25182520
end
25192521
end
2522+
2523+
pgroup.before_test(
2524+
'test_select_merger_process_storage_error',
2525+
read_scenario.before_merger_process_storage_error
2526+
)
2527+
2528+
pgroup.test_select_merger_process_storage_error = function(g)
2529+
read_scenario.merger_process_storage_error(g, read_impl)
2530+
end
2531+
2532+
pgroup.after_test(
2533+
'test_select_merger_process_storage_error',
2534+
read_scenario.after_merger_process_storage_error
2535+
)

test/integration/select_test.lua

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2273,9 +2273,12 @@ local function read_impl(cg, space, conditions, opts)
22732273
opts.mode = 'write'
22742274

22752275
local resp, err = cg.cluster.main_server:call('crud.select', {space, conditions, opts})
2276-
t.assert_equals(err, nil)
22772276

2278-
return crud.unflatten_rows(resp.rows, resp.metadata)
2277+
if err ~= nil then
2278+
return nil, err
2279+
end
2280+
2281+
return crud.unflatten_rows(resp.rows, resp.metadata), nil
22792282
end
22802283

22812284
pgroup.test_gh_418_select_with_secondary_noneq_index_condition = function(g)
@@ -2294,3 +2297,17 @@ for case_name_template, case in pairs(gh_373_types_cases) do
22942297
case(g, read_impl)
22952298
end
22962299
end
2300+
2301+
pgroup.before_test(
2302+
'test_select_merger_process_storage_error',
2303+
read_scenario.before_merger_process_storage_error
2304+
)
2305+
2306+
pgroup.test_select_merger_process_storage_error = function(g)
2307+
read_scenario.merger_process_storage_error(g, read_impl)
2308+
end
2309+
2310+
pgroup.after_test(
2311+
'test_select_merger_process_storage_error',
2312+
read_scenario.after_merger_process_storage_error
2313+
)

0 commit comments

Comments
 (0)