Skip to content

[TNTP-8909] fix: stop following the transfer destination on bucket ref error retries - #511

Merged
Satbek merged 3 commits into
masterfrom
tntp-8909-double-buckets
Aug 29, 2026
Merged

[TNTP-8909] fix: stop following the transfer destination on bucket ref error retries#511
Satbek merged 3 commits into
masterfrom
tntp-8909-double-buckets

Conversation

@Satbek

@Satbek Satbek commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

During rebalancing the source storage rejects a request with a bucket
ref error (e.g. TRANSFER_IS_IN_PROGRESS) and reports the transfer
destination. The router followed this redirect and retried the request
directly on the destination.

The destination, however, may not have received the bucket yet: it has
neither the _bucket record nor the data, and it is still in fast mode,
so no bucket ownership check is performed. The request was applied
against an empty space and acknowledged to the client. Once
bucket_recv() delivered the data, the cluster state diverged from the
acknowledged result: a deleted tuple reappeared, and the final result
of replace/update/upsert could differ from what was acknowledged.

The router no longer follows the destination reported by the error:
the bucket route cache is reset and the retry target is re-discovered
via vshard discovery, so a request is applied only on the replicaset
that actually holds the bucket.

A failed request is retried at most once and only after a recovery
action: the master is located on MISSING_MASTER, the cached master is
updated on NON_MASTER, the bucket route is reset on bucket ref errors
and the retry is re-routed by the bucket id. Other errors are returned
to the caller without a retry: the old code retried them blindly,
which silently doubled the effective request timeout. The retry is
given only the time left before the request deadline. Map requests are
not recovered at all: they are async, so storage errors arrive later,
in the future payload (see #513).

The rebalance safe mode also missed the start of a transfer on vshard
0.1.41+, where the bucket status is UPDATEd to READONLY instead of
being REPLACEd with SENDING, so safe mode was not enabled during
rebalancing and writes were not protected with bucket refs. Now the
READONLY update enables the safe mode as well.

Closes #509

@Satbek
Satbek force-pushed the tntp-8909-double-buckets branch from 077fa83 to e8ec406 Compare August 19, 2026 08:07
@Satbek
Satbek requested review from Serpentian, a1div0 and vakhov August 19, 2026 10:15
@Satbek
Satbek force-pushed the tntp-8909-double-buckets branch from e8ec406 to 0b500ca Compare August 19, 2026 10:50

@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.

Great work!

Comment thread crud/common/call.lua
Comment thread test/integration/double_buckets_test.lua Outdated
Comment thread crud/common/call.lua Outdated
Comment thread crud/common/call.lua Outdated
Comment thread crud/common/call.lua Outdated
Comment thread test/integration/double_buckets_test.lua Outdated
Comment thread test/integration/double_buckets_test.lua Outdated
Comment thread test/integration/double_buckets_test.lua Outdated
Comment thread test/integration/double_buckets_test.lua Outdated
Comment thread test/integration/double_buckets_test.lua Outdated
@Satbek
Satbek force-pushed the tntp-8909-double-buckets branch 5 times, most recently from 3d130e0 to 4818995 Compare August 24, 2026 13:42
@Satbek
Satbek requested a review from Serpentian August 24, 2026 14:07
@Satbek
Satbek force-pushed the tntp-8909-double-buckets branch from 4818995 to 7d134de Compare August 24, 2026 14:13
Comment thread crud/common/call.lua Outdated
Comment thread crud/common/map_call_cases/batch_postprocessor.lua
Comment thread crud/common/call.lua

@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.

Almost there! We're moving fast

Please, let's properly split the changes between the commits. Otherwise, I cannot judge, whether the code is properly splitted and I am forced to look at all the changes in their entirety, this way it's way easier to skip the bug.

And if you don't mind, can you in the future please write your responses to each comment before re-requesting their review? This helps a lot to see if you have addressed the comments. Even a simple "Fixed" is better than nothing. Thanks in advance!

Comment thread test/integration/double_buckets_test.lua
@Satbek Satbek changed the title [TNTP-8909] get rid of retry on bucket ref error [TNTP-8909] fix: stop following the transfer destination on bucket ref error retries Aug 27, 2026
@Satbek
Satbek force-pushed the tntp-8909-double-buckets branch from 1c9c2f2 to ff41e1a Compare August 27, 2026 11:40
Comment thread crud/common/sharding/init.lua
@Satbek
Satbek force-pushed the tntp-8909-double-buckets branch 2 times, most recently from e6320e0 to 91d8a35 Compare August 27, 2026 12:44
@Satbek
Satbek requested a review from Serpentian August 27, 2026 13:45

@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.

Looks like the last iteration to me. Thank you for putting up with my whining :)

Comment thread crud/common/call.lua Outdated
Comment thread test/entrypoint/srv_say_hi/all.lua Outdated
Comment thread CHANGELOG.md Outdated
Comment thread CHANGELOG.md Outdated
Comment thread CHANGELOG.md
Comment thread test/integration/double_buckets_test.lua Outdated
Comment thread crud/common/call.lua Outdated
Comment thread crud/common/call.lua Outdated
@Satbek
Satbek force-pushed the tntp-8909-double-buckets branch 5 times, most recently from 44dce5c to 1ebb427 Compare August 27, 2026 16:36
@Satbek
Satbek force-pushed the tntp-8909-double-buckets branch 5 times, most recently from e9abc48 to ced2b4c Compare August 27, 2026 18:08
wrap_vshard_err() took a bucket_id and, when the replicaset id was not
known, resolved it by routing the bucket and then matching the
replicaset object against vshard_router:routeall() -- a workaround for
tarantool/vshard#460 for the versions where a replicaset had no id
field. The rockspec now requires vshard >= 0.1.41, where replicaset.id
is always available, so the workaround is obsolete.

Now the replicaset id is always passed by the caller and
vshard_utils.get_replicaset_id() is dropped;
@Satbek
Satbek force-pushed the tntp-8909-double-buckets branch 3 times, most recently from 0714738 to 2ef416c Compare August 28, 2026 09:44
@Satbek

Satbek commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

I also returned back recovery for call.map because we actually can handle MISSING_MASTER error in it.

@Satbek
Satbek requested a review from Serpentian August 28, 2026 10:44
Comment thread crud/common/rebalance.lua
Comment thread test/helper.lua
Comment thread crud/common/call.lua Outdated
Comment thread crud/common/call.lua
@Satbek
Satbek force-pushed the tntp-8909-double-buckets branch from 2ef416c to 2a967f4 Compare August 28, 2026 14:19
The _bucket trigger that turns the rebalance safe mode on recognized
the start of a bucket migration by two markers: an INSERT of a bucket
in the RECEIVING status and a REPLACE of a bucket into the SENDING
status. Since vshard 0.1.41 a transfer on the source storage starts
with an UPDATE to the READONLY status instead, so neither marker
fired and the safe mode stayed disabled for the whole rebalancing.

Handle the UPDATE to READONLY as one more start marker. The REPLACE
to SENDING branch is kept for compatibility with older vshard
versions.

Part of #509.
@Satbek
Satbek force-pushed the tntp-8909-double-buckets branch 2 times, most recently from 4a05ba9 to 156f935 Compare August 28, 2026 14:59
call_with_retry_and_recovery() retried every failed call once, whatever
the error was, and for a single call it followed the destination
reported in a bucket ref error. The destination may not have received
the bucket yet, so in fast mode the request was applied there against
an empty space and the same key could end up on two storages. An
unrelated failure -- a storage error, a timeout -- was retried just as
blindly, silently doubling the requested timeout.

Recovery becomes an explicit step: recover_from_err() performs an
action for the errors it knows and only then reports whether a retry
makes sense. The master is located on MISSING_MASTER and the cached one
is updated on NON_MASTER; on WRONG_BUCKET, BUCKET_IS_LOCKED and
TRANSFER_IS_IN_PROGRESS the route cache is reset and the target is
re-discovered via vshard:route() instead of being taken from the error.
If the action did not help, or the error is anything else, it is
returned to the caller as is. A deadline is taken before the first
attempt, so the retry never runs past the requested timeout.

Map calls recover from MISSING_MASTER only: vshard does not search for
a master on an async call and reports it right away, while storage
errors arrive later, in the future payload -- see #513.

On the test side, the safe mode setup is extracted from
helpers.start_cluster() into helpers.set_safe_mode(), so that a test
can toggle the mode on a running cluster.

Closes #509.
@Satbek
Satbek force-pushed the tntp-8909-double-buckets branch from 156f935 to 4ffc828 Compare August 28, 2026 15:03
@Satbek
Satbek requested a review from Serpentian August 28, 2026 15:25

@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 fixes, the current version seems correct. Speaking of existing code, it requires substantial refactoring, it's very hard to make changes to it now: there're too many rough edges and small bugs in it. But I really appreciate, that you've fixed the things we've found.

I really hope, that someday we'll drop all that code from crud and allow vshard to do its work in order to avoid such nasty bugs. But for that to happen we must find a way to bump the perf of all requests

@Satbek
Satbek merged commit a305aa1 into master Aug 29, 2026
66 of 67 checks passed
@Satbek
Satbek deleted the tntp-8909-double-buckets branch August 29, 2026 04:59
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.

Violation of request consistency during rebalancing

4 participants