Skip to content

fix: pass timeout to vshard in map calls - #521

Open
Col-Waltz wants to merge 1 commit into
tarantool:masterfrom
Col-Waltz:add-timeout-option-for-vshard-call
Open

Col-Waltz wants to merge 1 commit into
tarantool:masterfrom
Col-Waltz:add-timeout-option-for-vshard-call

Conversation

@Col-Waltz

@Col-Waltz Col-Waltz commented Oct 27, 2026 •

Copy link
Copy Markdown

call.map() passed request_timeout to vshard, but didn't pass timeout.
Vshard then fell back to CALL_TIMEOUT_MAX (64s) and could crash on
assert(request_timeout <= timeout) when request_timeout > 64 inside
vshard call.

Pass timeout to vshard call options in call.map() to make map calls
consistent with call.single() and to keep CRUD and vshard time budgets
aligned (CRUD default is 2s, vshard default is 64s).

Also validate request_timeout <= timeout early and return a clear error
instead of failed assertion.

Comment thread crud/common/call.lua Resolved
Comment thread crud/common/call.lua Resolved
@Col-Waltz
Col-Waltz force-pushed the add-timeout-option-for-vshard-call branch from 828b776 to 6c169a9 Compare October 28, 2026 22:15
@sergepetrenko sergepetrenko removed their assignment Oct 29, 2026

@Serpentian Serpentian left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the patch!

Comment thread crud/common/call.lua
"request_timeout (%s) must be <= timeout (%s): pass request_timeout <= %s",
tostring(opts.request_timeout), tostring(timeout), tostring(timeout)
)
end

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's call.single, which still passes request_timeout > timeout to vshard unchanged. So, the assertion failure can be still reproduced with crud.get() and crud.locate()

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, added check also for call.single

Comment thread crud/common/call.lua
local futures_by_replicasets = {}
local call_opts = {
is_async = true,
timeout = timeout,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

crud/crud/select/merger.lua

Lines 204 to 208 in e7b4b8b

local net_box_opts = {is_async = true, buffer = buf,
skip_header = utils.tarantool_supports_netbox_skip_header_option() or nil}
local func_args_ext = utils.append_array({ box.session.effective_user(), func_name }, func_args)
local future = replicaset[vshard_call_name](replicaset, "_crud.call_on_storage",
func_args_ext, net_box_opts)

The merger-backed select and pairs path calls replicaset methods directly. Its net_box_opts contains neither timeout nor request_timeout, although their public options are accepted and carried into call_opts. Consequently, this path bypasses the new map validation and leaves vshard using its own timeout defaults.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And btw in merge the default timeout is also nil:

local timeout = context.timeout or call.DEFAULT_VSHARD_CALL_TIMEOUT

There's a typo, should be const instead of call

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, fixed typo and also added timeout to new merger and new_readview because they did not pass timeout to the vshard. Also added checks for select functions which are susceptible to the same issue with vshard assertion return. Checks are performed once a function call before any heavy logic is performed and souldn't affect perf much.

Comment thread crud/common/call.lua Outdated

local timeout = opts.timeout or const.DEFAULT_VSHARD_CALL_TIMEOUT

if opts.mode == 'read' and opts.request_timeout ~= nil and opts.request_timeout > timeout then

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, it's still the hot-path. The same way it's in vshard. And now we add if, which always be executed.

See, how crud uses the dev_checks for checking the options, And these checks are disabled on real production. However, there's still public entrypoints (e.g. crud.update.call), and they use the ordinary checks module, they're always launched.

So, the perfect solution imho should be some extension of the checks in crud, which will allow specifying the function, which will receive the whole opts table and compare request_timeout and timeout. And these checks under dev_checks will also be enabled only if TARANTOOL_CRUD_ENABLE_INTERNAL_CHECKS=ON.

But I'd rather ask smb from crud team, whether we should care that much. Maybe @vakhov

P.S. These checks are not in vshard since #521 (comment)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd keep the current check without extending checks. Before making the final decision, though, we should build the patched version and benchmark it against the reference to measure any performance regression. This is a separate task, and I've already contacted Ilya about it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd keep the current check without extending checks.

Which means that this will be LuaJIT assertion failure, when request_timeout > timeout. Are we ok with such behavior?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By "the current check" I meant the explicit validation added in this PR. We should add the same validation to call.single() so that invalid timeout combinations produce a clear error there too. My suggestion was to do this with a plain if, without extending checks.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that this checks can affect performance. I refactored checks having the least severe impact on performance. I performed some perf tests and there is no rate reduction more than 1% even on cold run. But after we make a proper perf testing we can remove this checks or add a flag to crud/common/dev_checks and hide this checks under this flag to not use them on production.

@Serpentian Serpentian assigned Col-Waltz and vakhov and unassigned Serpentian Oct 29, 2026
@Serpentian
Serpentian requested a review from vakhov October 29, 2026 10:11
@Col-Waltz
Col-Waltz force-pushed the add-timeout-option-for-vshard-call branch 2 times, most recently from d1d78dc to df9d41e Compare November 3, 2026 12:57
@Col-Waltz
Col-Waltz requested a review from Serpentian November 3, 2026 13:06
@Col-Waltz
Col-Waltz force-pushed the add-timeout-option-for-vshard-call branch 3 times, most recently from f34b8e8 to e27e7b3 Compare November 3, 2026 17:09
call.map() passed request_timeout to vshard, but didn't pass timeout.
Vshard then fell back to CALL_TIMEOUT_MAX (64s) and could crash on
assert(request_timeout <= timeout) when request_timeout > 64 inside
vshard call.

Pass timeout to vshard call options in call.map() to make map calls
consistent with call.single() and to keep CRUD and vshard time budgets
aligned (CRUD default is 2s, vshard default is 64s).

Also validate request_timeout <= timeout early and return a clear error
instead of failed assertion.
@Col-Waltz
Col-Waltz force-pushed the add-timeout-option-for-vshard-call branch from e27e7b3 to 6957534 Compare November 3, 2026 17:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants