Skip to content

Commit dcac828

Browse files
sergepetrenkovakhov
authored andcommitted
call: support vshard's request_timeout in read calls
vshard 0.1.28 introduces a new option for read requests: `request_timeout`. `request_timeout` serves as a protection against hung replicas. When it is specified, it must be <= `timeout`, and it introduces new behavior for router calls: they start retrying TimedOut errors, each time trying the request on a new replica, as long as `timeout` (the old one) permits. Support the option only in crud requests with `mode = 'read'`, since it makes no sense with `mode = 'write'`. There is no one to retry the request on if master is unresponsive.
1 parent 830f03b commit dcac828

File tree

13 files changed

+108
-13
lines changed

13 files changed

+108
-13
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
66
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
77

8+
## [Unreleased]
9+
10+
### Added
11+
* Support for `vshard`'s `request_timeout` parameter for calls with `mode = 'read'`
12+
13+
### Changed
14+
15+
### Fixed
16+
817
## [1.6.0] - 09-09-25
918

1019
### Changed

README.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,9 @@ where:
544544
* `bucket_id` (`?number|cdata`) - bucket ID
545545
* `timeout` (`?number`) - `vshard.call` timeout and vshard master
546546
discovery timeout (in seconds), default value is 2
547+
* `request_timeout` (`?number`) - `vshard.call` `request_timeout` parameter.
548+
Can be specified only with `mode` = `read`, and default value is the same as
549+
user-passed `timeout`.
547550
* `mode` (`?string`, `read` or `write`) - if `write` is specified then `get` is
548551
performed on master, default value is `read`
549552
* `prefer_replica` (`?boolean`) - if `true` then the preferred target is one of
@@ -1103,6 +1106,9 @@ where:
11031106
then the map call is performed without any optimizations even
11041107
if full primary key equal condition is specified
11051108
* `timeout` (`?number`) - `vshard.call` timeout (in seconds)
1109+
* `request_timeout` (`?number`) - `vshard.call` `request_timeout` parameter.
1110+
Can be specified only with `mode` = `read`, and default value is the same as
1111+
user-passed `timeout`.
11061112
* `fields` (`?table`) - field names for getting only a subset of fields
11071113
* `fullscan` (`?boolean`) - if `true` then a critical log entry will be skipped
11081114
on potentially long `select`, see [avoiding full scan](doc/select.md#avoiding-full-scan).
@@ -1200,6 +1206,9 @@ where:
12001206
* `index_id` (`?string|number`) - index name or index id. Primary index by default
12011207
* `opts`:
12021208
* `timeout` (`?number`) - `vshard.call` timeout (in seconds)
1209+
* `request_timeout` (`?number`) - `vshard.call` `request_timeout` parameter.
1210+
Can be specified only with `mode` = `read`, and default value is the same as
1211+
user-passed `timeout`.
12031212
* `fields` (`?table`) - field names for getting only a subset of fields
12041213
* `mode` (`?string`, `read` or `write`) - if `write` is specified then `select` is
12051214
performed on master, default value is `read`
@@ -1428,6 +1437,10 @@ where:
14281437
* `space_name` (`string`) - name of the space
14291438
* `conditions` (`?table`) - array of [conditions](#select-conditions)
14301439
* `opts`:
1440+
* `timeout` (`?number`) - `vshard.call` timeout (in seconds)
1441+
* `request_timeout` (`?number`) - `vshard.call` `request_timeout` parameter.
1442+
Can be specified only with `mode` = `read`, and default value is the same as
1443+
user-passed `timeout`.
14311444
* `yield_every` (`?number`) - number of tuples processed to yield after,
14321445
`yield_every` should be > 0, default value is 1000
14331446
* `timeout` (`?number`) - `vshard.call` timeout and vshard master
@@ -1733,7 +1746,7 @@ local result, err = rv:select(space_name, conditions, opts)
17331746
rv:close()
17341747
```
17351748

1736-
Opts are the same as [select opts](#select), except `balance`, `prefer_replica` and `mode` are not supported.
1749+
Opts are the same as [select opts](#select), except `balance`, `request_timeout`, `prefer_replica` and `mode` are not supported.
17371750

17381751
Returns metadata and array of rows, error.
17391752

crud/borders.lua

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ end
6969
local function call_get_border_on_router(vshard_router, border_name, space_name, index_name, opts)
7070
checks('table', 'string', 'string', '?string|number', {
7171
timeout = '?number',
72+
request_timeout = '?number',
7273
fields = '?table',
7374
mode = '?string',
7475
vshard_router = '?string|table',
@@ -105,10 +106,12 @@ local function call_get_border_on_router(vshard_router, border_name, space_name,
105106
if err ~= nil then
106107
return nil, BorderError:new("Failed to get router replicasets: %s", err)
107108
end
109+
local mode = opts.mode or 'read'
108110
local call_opts = {
109-
mode = opts.mode or 'read',
111+
mode = mode,
110112
replicasets = replicasets,
111113
timeout = opts.timeout,
114+
request_timeout = mode == 'read' and opts.request_timeout or nil,
112115
}
113116
local results, err, storages_info = call.map(vshard_router,
114117
CRUD_STAT_FUNC_NAME,
@@ -198,6 +201,10 @@ end
198201
-- @tparam ?number opts.timeout
199202
-- Function call timeout
200203
--
204+
-- @tparam ?number opts.request_timeout
205+
-- vshard call request_timeout
206+
-- default is the same as opts.timeout
207+
--
201208
-- @tparam ?table opts.fields
202209
-- Field names for getting only a subset of fields
203210
--
@@ -226,6 +233,10 @@ end
226233
-- @tparam ?number opts.timeout
227234
-- Function call timeout
228235
--
236+
-- @tparam ?number opts.request_timeout
237+
-- vshard call request_timeout
238+
-- default is the same as opts.timeout
239+
--
229240
-- @tparam ?table opts.fields
230241
-- Field names for getting only a subset of fields
231242
--

crud/common/call.lua

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ function call.map(vshard_router, func_name, func_args, opts)
108108
prefer_replica = '?boolean',
109109
balance = '?boolean',
110110
timeout = '?number',
111+
request_timeout = '?number',
111112
replicasets = '?table',
112113
iter = '?table',
113114
postprocessor = '?table',
@@ -139,7 +140,10 @@ function call.map(vshard_router, func_name, func_args, opts)
139140
end
140141

141142
local futures_by_replicasets = {}
142-
local call_opts = {is_async = true}
143+
local call_opts = {
144+
is_async = true,
145+
request_timeout = opts.mode == 'read' and opts.request_timeout or nil,
146+
}
143147
while iter:has_next() do
144148
local args, replicaset, replicaset_id = iter:get()
145149

@@ -201,6 +205,7 @@ function call.single(vshard_router, bucket_id, func_name, func_args, opts)
201205
prefer_replica = '?boolean',
202206
balance = '?boolean',
203207
timeout = '?number',
208+
request_timeout = '?number',
204209
})
205210

206211
local vshard_call_name, err = call.get_vshard_call_name(opts.mode, opts.prefer_replica, opts.balance)
@@ -214,9 +219,11 @@ function call.single(vshard_router, bucket_id, func_name, func_args, opts)
214219
end
215220

216221
local timeout = opts.timeout or const.DEFAULT_VSHARD_CALL_TIMEOUT
222+
local request_timeout = opts.mode == 'read' and opts.request_timeout or nil
217223

218224
local res, err = retry_call_with_master_discovery(replicaset, vshard_call_name,
219-
func_name, func_args, {timeout = timeout})
225+
func_name, func_args, {timeout = timeout,
226+
request_timeout = request_timeout})
220227
if err ~= nil then
221228
return nil, wrap_vshard_err(vshard_router, err, func_name, nil, bucket_id)
222229
end

crud/count.lua

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ end
110110
local function call_count_on_router(vshard_router, space_name, user_conditions, opts)
111111
checks('table', 'string', '?table', {
112112
timeout = '?number',
113+
request_timeout = '?number',
113114
bucket_id = '?',
114115
force_map_call = '?boolean',
115116
fullscan = '?boolean',
@@ -221,11 +222,14 @@ local function call_count_on_router(vshard_router, space_name, user_conditions,
221222

222223
local yield_every = opts.yield_every or const.DEFAULT_YIELD_EVERY
223224

225+
local mode = opts.mode or 'read'
226+
224227
local call_opts = {
225-
mode = opts.mode or 'read',
228+
mode = mode,
226229
prefer_replica = opts.prefer_replica,
227230
balance = opts.balance,
228231
timeout = opts.timeout,
232+
request_timeout = mode == 'read' and opts.request_timeout or nil,
229233
replicasets = replicasets_to_count,
230234
}
231235

@@ -282,6 +286,10 @@ end
282286
-- Function call timeout in seconds,
283287
-- default value is 2 seconds
284288
--
289+
-- @tparam ?number opts.request_timeout
290+
-- vshard call request_timeout,
291+
-- default is the same as opts.timeout
292+
--
285293
-- @tparam ?number opts.bucket_id
286294
-- Bucket ID
287295
-- default is vshard.router.bucket_id_strcrc32 of primary key
@@ -317,6 +325,7 @@ end
317325
function count.call(space_name, user_conditions, opts)
318326
checks('string', '?table', {
319327
timeout = '?number',
328+
request_timeout = '?number',
320329
bucket_id = '?',
321330
force_map_call = '?boolean',
322331
fullscan = '?boolean',

crud/get.lua

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ get.storage_api = {[GET_FUNC_NAME] = get_on_storage}
5858
local function call_get_on_router(vshard_router, space_name, key, opts)
5959
dev_checks('table', 'string', '?', {
6060
timeout = '?number',
61+
request_timeout = '?number',
6162
bucket_id = '?',
6263
fields = '?table',
6364
prefer_replica = '?boolean',
@@ -116,11 +117,14 @@ local function call_get_on_router(vshard_router, space_name, key, opts)
116117
fetch_latest_metadata = opts.fetch_latest_metadata,
117118
}
118119

120+
local mode = opts.mode or 'read'
121+
119122
local call_opts = {
120-
mode = opts.mode or 'read',
123+
mode = mode,
121124
prefer_replica = opts.prefer_replica,
122125
balance = opts.balance,
123126
timeout = opts.timeout,
127+
request_timeout = mode == 'read' and opts.request_timeout or nil,
124128
}
125129

126130
local storage_result, err = call.single(vshard_router,
@@ -174,6 +178,10 @@ end
174178
-- @tparam ?number opts.timeout
175179
-- Function call timeout
176180
--
181+
-- @tparam ?number opts.request_timeout
182+
-- vshard call request_timeout
183+
-- default is the same as opts.timeout
184+
--
177185
-- @tparam ?number opts.bucket_id
178186
-- Bucket ID
179187
-- (by default, it's vshard.router.bucket_id_strcrc32 of primary key)
@@ -196,6 +204,7 @@ end
196204
function get.call(space_name, key, opts)
197205
checks('string', '?', {
198206
timeout = '?number',
207+
request_timeout = '?number',
199208
bucket_id = '?',
200209
fields = '?table',
201210
prefer_replica = '?boolean',

crud/select/compat/select.lua

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ function select_module.pairs(space_name, user_conditions, opts)
214214
prefer_replica = '?boolean',
215215
balance = '?boolean',
216216
timeout = '?number',
217+
request_timeout = '?number',
217218
readview = '?boolean',
218219
readview_info = '?table',
219220

@@ -247,6 +248,10 @@ function select_module.pairs(space_name, user_conditions, opts)
247248
if opts.vshard_router ~= nil then
248249
return nil, SelectError:new("Readview does not support 'vshard_router' option")
249250
end
251+
252+
if opts.request_timeout ~= nil then
253+
return nil, SelectError:new("Readview does not support 'request_timeout' option")
254+
end
250255
end
251256

252257
if opts.first ~= nil and opts.first < 0 then
@@ -271,6 +276,8 @@ function select_module.pairs(space_name, user_conditions, opts)
271276
prefer_replica = opts.prefer_replica,
272277
balance = opts.balance,
273278
timeout = opts.timeout,
279+
request_timeout = (opts.mode == 'read' or opts.mode == nil) and
280+
opts.request_timeout or nil,
274281
fetch_latest_metadata = opts.fetch_latest_metadata,
275282
},
276283
readview = opts.readview,
@@ -338,6 +345,7 @@ local function select_module_call_xc(vshard_router, space_name, user_conditions,
338345
prefer_replica = '?boolean',
339346
balance = '?boolean',
340347
timeout = '?number',
348+
request_timeout = '?number',
341349
readview = '?boolean',
342350
readview_info = '?table',
343351

@@ -362,6 +370,10 @@ local function select_module_call_xc(vshard_router, space_name, user_conditions,
362370
if opts.vshard_router ~= nil then
363371
return nil, SelectError:new("Readview does not support 'vshard_router' option")
364372
end
373+
374+
if opts.request_timeout ~= nil then
375+
return nil, SelectError:new("Readview does not support 'request_timeout' option")
376+
end
365377
end
366378

367379
if opts.first ~= nil and opts.first < 0 then
@@ -383,6 +395,8 @@ local function select_module_call_xc(vshard_router, space_name, user_conditions,
383395
prefer_replica = opts.prefer_replica,
384396
balance = opts.balance,
385397
timeout = opts.timeout,
398+
request_timeout = (opts.mode == 'read' or opts.mode == nil) and
399+
opts.request_timeout or nil,
386400
fetch_latest_metadata = opts.fetch_latest_metadata,
387401
},
388402
readview = opts.readview,

crud/select/compat/select_old.lua

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,13 @@ local function select_iteration(space_name, plan, opts)
5454
space_name, plan.index_id, plan.conditions, storage_select_opts,
5555
}
5656

57+
local mode = call_opts.mode or 'read'
58+
5759
local results, err, storages_info = call.map(opts.vshard_router, common.SELECT_FUNC_NAME, storage_select_args, {
5860
replicasets = opts.replicasets,
5961
timeout = call_opts.timeout,
60-
mode = call_opts.mode or 'read',
62+
request_timeout = mode == 'read' and call_opts.request_timeout or nil,
63+
mode = mode,
6164
prefer_replica = call_opts.prefer_replica,
6265
balance = call_opts.balance,
6366
})
@@ -355,6 +358,8 @@ local function select_module_call_xc(vshard_router, space_name, user_conditions,
355358
end
356359
end
357360

361+
local mode = opts.mode or 'read'
362+
358363
local iterator_opts = {
359364
after = opts.after,
360365
first = opts.first,
@@ -364,10 +369,11 @@ local function select_module_call_xc(vshard_router, space_name, user_conditions,
364369
field_names = opts.fields,
365370
yield_every = opts.yield_every,
366371
call_opts = {
367-
mode = opts.mode,
372+
mode = mode,
368373
prefer_replica = opts.prefer_replica,
369374
balance = opts.balance,
370375
timeout = opts.timeout,
376+
request_timeout = mode == 'read' and opts.request_timeout or nil,
371377
fetch_latest_metadata = opts.fetch_latest_metadata,
372378
},
373379
}
@@ -439,6 +445,7 @@ function select_module.call(space_name, user_conditions, opts)
439445
prefer_replica = '?boolean',
440446
balance = '?boolean',
441447
timeout = '?number',
448+
request_timeout= '?number',
442449

443450
vshard_router = '?string|table',
444451

test/integration/borders_test.lua

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,12 @@ pgroup.test_opts_not_damaged = function(g)
367367
})
368368

369369
-- min
370-
local min_opts = {timeout = 1, fields = {'name', 'age'}, mode = 'write'}
370+
local min_opts = {
371+
timeout = 1,
372+
request_timeout = 1,
373+
fields = {'name', 'age'},
374+
mode = 'write',
375+
}
371376
local new_min_opts, err = g.router:eval([[
372377
local crud = require('crud')
373378
@@ -382,7 +387,12 @@ pgroup.test_opts_not_damaged = function(g)
382387
t.assert_equals(new_min_opts, min_opts)
383388

384389
-- max
385-
local max_opts = {timeout = 1, fields = {'name', 'age'}, mode = 'write'}
390+
local max_opts = {
391+
timeout = 1,
392+
request_timeout = 1,
393+
fields = {'name', 'age'},
394+
mode = 'write',
395+
}
386396
local new_max_opts, err = g.router:eval([[
387397
local crud = require('crud')
388398

test/integration/count_test.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,7 @@ pgroup.test_opts_not_damaged = function(g)
614614

615615
local count_opts = {
616616
timeout = 1,
617+
request_timeout = 1,
617618
bucket_id = 1161,
618619
yield_every = 105,
619620
mode = 'read',

0 commit comments

Comments
 (0)