• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tarantool / crud / 19959665764

05 Dec 2025 10:11AM UTC coverage: 88.424%. First build
19959665764

Pull #463

github

Satbek
Fix tests after fast/safe mode changes

* add access to _bucket space in privillage tests
* fix select_readview_test
* enable double buckets test
* add safe_mode_disable for cartirdge reload test: test_storage
* add safe_mode_disable for test_any_vshard_call_timeout
Pull Request #463: TNTP-2109: call bucket_ref/bucket_unref on crud operations

205 of 269 new or added lines in 16 files covered. (76.21%)

5217 of 5900 relevant lines covered (88.42%)

12766.29 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.23
/crud/get.lua
1
local checks = require('checks')
593✔
2
local errors = require('errors')
593✔
3

4
local call = require('crud.common.call')
593✔
5
local const = require('crud.common.const')
593✔
6
local utils = require('crud.common.utils')
593✔
7
local sharding = require('crud.common.sharding')
593✔
8
local sharding_key_module = require('crud.common.sharding.sharding_key')
593✔
9
local sharding_metadata_module = require('crud.common.sharding.sharding_metadata')
593✔
10
local dev_checks = require('crud.common.dev_checks')
593✔
11
local schema = require('crud.common.schema')
593✔
12
local bucket_ref_unref = require('crud.common.sharding.bucket_ref_unref')
593✔
13

14
local GetError = errors.new_class('GetError', {capture_stack = false})
593✔
15

16
local get = {}
593✔
17

18
local GET_FUNC_NAME = 'get_on_storage'
593✔
19
local CRUD_GET_FUNC_NAME = utils.get_storage_call(GET_FUNC_NAME)
593✔
20

21
local function get_on_storage(space_name, key, field_names, opts)
22
    dev_checks('string', '?', '?table', {
260✔
23
        bucket_id = 'number|cdata',
24
        sharding_key_hash = '?number',
25
        sharding_func_hash = '?number',
26
        skip_sharding_hash_check = '?boolean',
27
        fetch_latest_metadata = '?boolean',
28
    })
29

30
    opts = opts or {}
260✔
31

32
    local space = box.space[space_name]
260✔
33
    if space == nil then
260✔
34
        return nil, GetError:new("Space %q doesn't exist", space_name)
×
35
    end
36

37
    local _, err = sharding.check_sharding_hash(space_name,
520✔
38
                                                opts.sharding_func_hash,
260✔
39
                                                opts.sharding_key_hash,
260✔
40
                                                opts.skip_sharding_hash_check)
260✔
41

42
    if err ~= nil then
260✔
43
        return nil, err
4✔
44
    end
45

46
    local ref_ok, bucket_ref_err = bucket_ref_unref.bucket_refro(opts.bucket_id)
256✔
47
    if not ref_ok then
256✔
NEW
48
        return nil, bucket_ref_err
×
49
    end
50
    -- add_space_schema_hash is false because
51
    -- reloading space format on router can't avoid get error on storage
52
    local result = schema.wrap_box_space_func_result(space, 'get', {key}, {
512✔
53
        add_space_schema_hash = false,
54
        field_names = field_names,
256✔
55
        fetch_latest_metadata = opts.fetch_latest_metadata,
256✔
56
    })
57
    local unref_ok, err_unref = bucket_ref_unref.bucket_unrefro(opts.bucket_id)
256✔
58
    if not unref_ok then
256✔
NEW
59
        return nil, err_unref
×
60
    end
61

62
    return result
256✔
63
end
64

65
get.storage_api = {[GET_FUNC_NAME] = get_on_storage}
593✔
66

67
-- returns result, err, need_reload
68
-- need_reload indicates if reloading schema could help
69
-- see crud.common.schema.wrap_func_reload()
70
local function call_get_on_router(vshard_router, space_name, key, opts)
71
    dev_checks('table', 'string', '?', {
298✔
72
        timeout = '?number',
73
        request_timeout = '?number',
74
        bucket_id = '?',
75
        fields = '?table',
76
        prefer_replica = '?boolean',
77
        balance = '?boolean',
78
        mode = '?string',
79
        vshard_router = '?string|table',
80
        fetch_latest_metadata = '?boolean',
81
    })
82

83
    local space, err, netbox_schema_version = utils.get_space(space_name, vshard_router, opts.timeout)
298✔
84
    if err ~= nil then
298✔
85
        return nil, GetError:new("An error occurred during the operation: %s", err), const.NEED_SCHEMA_RELOAD
×
86
    end
87
    if space == nil then
298✔
88
        return nil, GetError:new("Space %q doesn't exist", space_name), const.NEED_SCHEMA_RELOAD
52✔
89
    end
90

91
    if box.tuple.is(key) then
544✔
92
        key = key:totable()
×
93
    end
94

95
    local sharding_key = key
272✔
96
    local sharding_key_hash = nil
272✔
97
    local skip_sharding_hash_check = nil
98

99
    if opts.bucket_id == nil then
272✔
100
        local primary_index_parts = space.index[0].parts
216✔
101

102
        local sharding_key_data, err = sharding_metadata_module.fetch_sharding_key_on_router(vshard_router, space_name)
216✔
103
        if err ~= nil then
216✔
104
            return nil, err
×
105
        end
106

107
        sharding_key, err = sharding_key_module.extract_from_pk(vshard_router,
432✔
108
                                                                space_name,
216✔
109
                                                                sharding_key_data.value,
216✔
110
                                                                primary_index_parts, key)
432✔
111
        if err ~= nil then
216✔
112
            return nil, err
4✔
113
        end
114

115
        sharding_key_hash = sharding_key_data.hash
212✔
116
    else
117
        skip_sharding_hash_check = true
56✔
118
    end
119

120
    local bucket_id_data, err = sharding.key_get_bucket_id(vshard_router, space_name, sharding_key, opts.bucket_id)
268✔
121
    if err ~= nil then
268✔
122
        return nil, err
8✔
123
    end
124

125
    -- When the sharding index (bucket_id) is the primary index, bucket_id can be passed as box.NULL.
126
    sharding.fill_bucket_id_pk(space, key, bucket_id_data.bucket_id)
260✔
127

128
    local get_on_storage_opts = {
260✔
129
        bucket_id = bucket_id_data.bucket_id,
260✔
130
        sharding_func_hash = bucket_id_data.sharding_func_hash,
260✔
131
        sharding_key_hash = sharding_key_hash,
260✔
132
        skip_sharding_hash_check = skip_sharding_hash_check,
260✔
133
        fetch_latest_metadata = opts.fetch_latest_metadata,
260✔
134
    }
135

136
    local mode = opts.mode or 'read'
260✔
137

138
    local call_opts = {
260✔
139
        mode = mode,
260✔
140
        prefer_replica = opts.prefer_replica,
260✔
141
        balance = opts.balance,
260✔
142
        timeout = opts.timeout,
260✔
143
        request_timeout = mode == 'read' and opts.request_timeout or nil,
260✔
144
    }
145

146
    local storage_result, err = call.single(vshard_router,
520✔
147
        bucket_id_data.bucket_id, CRUD_GET_FUNC_NAME,
260✔
148
        {space_name, key, opts.fields, get_on_storage_opts},
260✔
149
        call_opts
150
    )
260✔
151

152
    if err ~= nil then
260✔
153
        local err_wrapped = GetError:new("Failed to call get on storage-side: %s", err)
4✔
154

155
        if sharding.result_needs_sharding_reload(err) then
8✔
156
            return nil, err_wrapped, const.NEED_SHARDING_RELOAD
2✔
157
        end
158

159
        return nil, err_wrapped
2✔
160
    end
161

162
    if storage_result.err ~= nil then
256✔
163
        return nil, GetError:new("Failed to get: %s", storage_result.err)
60✔
164
    end
165

166
    local tuple = storage_result.res
226✔
167

168
    -- protect against box.NULL
169
    if tuple == nil then
226✔
170
        tuple = nil
102✔
171
    end
172

173
    if opts.fetch_latest_metadata == true then
226✔
174
        -- This option is temporary and is related to [1], [2].
175
        -- [1] https://github.com/tarantool/crud/issues/236
176
        -- [2] https://github.com/tarantool/crud/issues/361
177
        space = utils.fetch_latest_metadata_when_single_storage(space, space_name, netbox_schema_version,
4✔
178
                                                                vshard_router, opts, storage_result.storage_info)
4✔
179
    end
180

181
    return utils.format_result({tuple}, space, opts.fields)
226✔
182
end
183

184
--- Get tuple from the specified space by key
185
--
186
-- @function call
187
--
188
-- @param string space_name
189
--  A space name
190
--
191
-- @param key
192
--  Primary key value
193
--
194
-- @tparam ?number opts.timeout
195
--  Function call timeout
196
--
197
-- @tparam ?number opts.request_timeout
198
--  vshard call request_timeout
199
--  default is the same as opts.timeout
200
--
201
-- @tparam ?number opts.bucket_id
202
--  Bucket ID
203
--  (by default, it's vshard.router.bucket_id_strcrc32 of primary key)
204
--
205
-- @tparam ?boolean opts.prefer_replica
206
--  Call on replica if it's possible
207
--
208
-- @tparam ?boolean opts.balance
209
--  Use replica according to round-robin load balancing
210
--
211
-- @tparam ?string|table opts.vshard_router
212
--  Cartridge vshard group name or vshard router instance.
213
--  Set this parameter if your space is not a part of the
214
--  default vshard cluster.
215
--
216
-- @return[1] object
217
-- @treturn[2] nil
218
-- @treturn[2] table Error description
219
--
220
function get.call(space_name, key, opts)
593✔
221
    checks('string', '?', {
286✔
222
        timeout = '?number',
223
        request_timeout = '?number',
224
        bucket_id = '?',
225
        fields = '?table',
226
        prefer_replica = '?boolean',
227
        balance = '?boolean',
228
        mode = '?string',
229
        vshard_router = '?string|table',
230
        fetch_latest_metadata = '?boolean',
231
    })
232

233
    opts = opts or {}
286✔
234

235
    local vshard_router, err = utils.get_vshard_router_instance(opts.vshard_router)
286✔
236
    if err ~= nil then
286✔
237
        return nil, GetError:new(err)
8✔
238
    end
239

240
    return schema.wrap_func_reload(vshard_router, sharding.wrap_method, call_get_on_router,
282✔
241
                                   space_name, key, opts)
282✔
242
end
243

244
return get
593✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc