Skip to content

Commit b4ca442

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 3c0597e commit b4ca442

File tree

8 files changed

+171
-20
lines changed

8 files changed

+171
-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
@@ -905,9 +905,12 @@ local function read_impl(cg, space, conditions, opts)
905905
local status, resp = pcall(function()
906906
return crud.pairs(space, conditions, opts):totable()
907907
end)
908-
t.assert(status, resp)
909908

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

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

test/integration/read_scenario.lua

Lines changed: 84 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)
@@ -555,8 +556,90 @@ for space_kind, space_option in pairs(datetime_condition_space_options) do
555556
end
556557

557558

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

test/integration/select_readview_test.lua

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

24962496
local resp, err = rv:select(space, conditions, opts)
2497-
t.assert_equals(err, nil)
2498-
24992497
rv:close()
25002498

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

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

test/integration/select_test.lua

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

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

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

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

0 commit comments

Comments
 (0)