Skip to content

Commit 2495a6f

Browse files
crud: support vshard with no UUIDs in config
PR #404 has introduced vshard 0.1.25 + Tarantool 3.0 "name as key" identification mode based on UUIDs extraction. If works fine if vshard configuration (or Tarantool 3.0 configuration which builds vshard one) provides UUIDs, but fails if it isn't. Since UUIDs are optional and won't be provided in most cases, it makes crud fails to work on most Tarantool 3.0 vshard clusters. This patch fixes the issue. Now the code uses name as key, if corresponding mode is enabled, and uuid otherwise. Patch doesn't cover `select_old` since it runs only on pre-3.0 Tarantool. Unfortunately, code relies on vshard internals since now there is no other way [1]. This patch covers new mode support for readview code as well. It likely was broken before this patch even if UUIDs were provided. 1. tarantool/vshard#460 Follows #404 Closes #407
1 parent 45a362a commit 2495a6f

21 files changed

+429
-202
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ 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+
### Fixed
11+
* Compatibility with vshard configuration if UUIDs are omitted (#407).
12+
813
## [1.4.2] - 25-12-23
914

1015
### Added

crud.lua

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,12 +173,13 @@ function crud.init_storage()
173173

174174
local user = nil
175175
if not box.info.ro then
176-
local replicaset_uuid, replicaset = utils.get_self_vshard_replicaset()
176+
local replicaset_key, replicaset = utils.get_self_vshard_replicaset()
177177

178178
if replicaset == nil or replicaset.master == nil then
179-
error(string.format('Failed to find a vshard configuration for ' ..
180-
' replicaset with replicaset_uuid %s.',
181-
replicaset_uuid))
179+
error(string.format(
180+
'Failed to find a vshard configuration ' ..
181+
'for storage replicaset with key %q.',
182+
replicaset_key))
182183
end
183184
user = luri.parse(replicaset.master.uri).login or 'guest'
184185
end

crud/common/call.lua

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,28 +40,34 @@ function call.get_vshard_call_name(mode, prefer_replica, balance)
4040
return 'callbre'
4141
end
4242

43-
local function wrap_vshard_err(vshard_router, err, func_name, replicaset_uuid, bucket_id)
43+
local function wrap_vshard_err(vshard_router, err, func_name, replicaset_id, bucket_id)
4444
-- Do not rewrite ShardingHashMismatchError class.
4545
if err.class_name == sharding_utils.ShardingHashMismatchError.name then
4646
return errors.wrap(err)
4747
end
4848

49-
if replicaset_uuid == nil then
49+
if replicaset_id == nil then
5050
local replicaset, _ = vshard_router:route(bucket_id)
5151
if replicaset == nil then
5252
return CallError:new(
5353
"Function returned an error, but we couldn't figure out the replicaset: %s", err
5454
)
5555
end
5656

57-
replicaset_uuid = replicaset.uuid
57+
replicaset_id = utils.get_replicaset_id(vshard_router, replicaset)
58+
59+
if replicaset_id == nil then
60+
return CallError:new(
61+
"Function returned an error, but we couldn't figure out the replicaset id: %s", err
62+
)
63+
end
5864
end
5965

60-
err = utils.update_storage_call_error_description(err, func_name, replicaset_uuid)
66+
err = utils.update_storage_call_error_description(err, func_name, replicaset_id)
6167
err = errors.wrap(err)
6268

6369
return CallError:new(utils.format_replicaset_error(
64-
replicaset_uuid, "Function returned an error: %s", err
70+
replicaset_id, "Function returned an error: %s", err
6571
))
6672
end
6773

@@ -104,13 +110,13 @@ function call.map(vshard_router, func_name, func_args, opts)
104110
local futures_by_replicasets = {}
105111
local call_opts = {is_async = true}
106112
while iter:has_next() do
107-
local args, replicaset = iter:get()
113+
local args, replicaset, replicaset_id = iter:get()
108114
local future = replicaset[vshard_call_name](replicaset, func_name, args, call_opts)
109-
futures_by_replicasets[replicaset.uuid] = future
115+
futures_by_replicasets[replicaset_id] = future
110116
end
111117

112118
local deadline = fiber_clock() + timeout
113-
for replicaset_uuid, future in pairs(futures_by_replicasets) do
119+
for replicaset_id, future in pairs(futures_by_replicasets) do
114120
local wait_timeout = deadline - fiber_clock()
115121
if wait_timeout < 0 then
116122
wait_timeout = 0
@@ -119,14 +125,14 @@ function call.map(vshard_router, func_name, func_args, opts)
119125
local result, err = future:wait_result(wait_timeout)
120126

121127
local result_info = {
122-
key = replicaset_uuid,
128+
key = replicaset_id,
123129
value = result,
124130
}
125131

126132
local err_info = {
127133
err_wrapper = wrap_vshard_err,
128134
err = err,
129-
wrapper_args = {func_name, replicaset_uuid},
135+
wrapper_args = {func_name, replicaset_id},
130136
}
131137

132138
local early_exit = postprocessor:collect(result_info, err_info)
@@ -179,13 +185,13 @@ function call.any(vshard_router, func_name, func_args, opts)
179185
if replicasets == nil then
180186
return nil, CallError:new("Failed to get router replicasets: %s", err.err)
181187
end
182-
local replicaset = select(2, next(replicasets))
188+
local replicaset_id, replicaset = next(replicasets)
183189

184190
local res, err = replicaset:call(func_name, func_args, {
185191
timeout = timeout,
186192
})
187193
if err ~= nil then
188-
return nil, wrap_vshard_err(vshard_router, err, func_name, replicaset.uuid)
194+
return nil, wrap_vshard_err(vshard_router, err, func_name, replicaset_id)
189195
end
190196

191197
if res == box.NULL then

crud/common/map_call_cases/base_iter.lua

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,13 @@ end
6666
--
6767
-- @return[1] table func_args
6868
-- @return[2] table replicaset
69+
-- @return[3] string replicaset_id
6970
function BaseIterator:get()
71+
local replicaset_id = self.next_index
7072
local replicaset = self.next_replicaset
7173
self.next_index, self.next_replicaset = next(self.replicasets, self.next_index)
7274

73-
return self.func_args, replicaset
75+
return self.func_args, replicaset, replicaset_id
7476
end
7577

7678
return BaseIterator

crud/common/map_call_cases/batch_insert_iter.lua

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ function BatchInsertIterator:new(opts)
4040
return nil, SplitTuplesError:new("Failed to split tuples by replicaset: %s", err.err)
4141
end
4242

43-
local next_replicaset, next_batch = next(sharding_data.batches)
43+
local next_index, next_batch = next(sharding_data.batches)
4444

4545
local execute_on_storage_opts = opts.execute_on_storage_opts
4646
execute_on_storage_opts.sharding_func_hash = sharding_data.sharding_func_hash
@@ -51,7 +51,7 @@ function BatchInsertIterator:new(opts)
5151
space_name = opts.space.name,
5252
opts = execute_on_storage_opts,
5353
batches_by_replicasets = sharding_data.batches,
54-
next_index = next_replicaset,
54+
next_index = next_index,
5555
next_batch = next_batch,
5656
}
5757

@@ -67,8 +67,10 @@ end
6767
--
6868
-- @return[1] table func_args
6969
-- @return[2] table replicaset
70+
-- @return[3] string replicaset_id
7071
function BatchInsertIterator:get()
71-
local replicaset = self.next_index
72+
local replicaset_id = self.next_index
73+
local replicaset = self.next_batch.replicaset
7274
local func_args = {
7375
self.space_name,
7476
self.next_batch.tuples,
@@ -77,7 +79,7 @@ function BatchInsertIterator:get()
7779

7880
self.next_index, self.next_batch = next(self.batches_by_replicasets, self.next_index)
7981

80-
return func_args, replicaset
82+
return func_args, replicaset, replicaset_id
8183
end
8284

8385
return BatchInsertIterator

crud/common/map_call_cases/batch_upsert_iter.lua

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ function BatchUpsertIterator:new(opts)
4848
return nil, SplitTuplesError:new("Failed to split tuples by replicaset: %s", err.err)
4949
end
5050

51-
local next_replicaset, next_batch = next(sharding_data.batches)
51+
local next_index, next_batch = next(sharding_data.batches)
5252

5353
local execute_on_storage_opts = opts.execute_on_storage_opts
5454
execute_on_storage_opts.sharding_func_hash = sharding_data.sharding_func_hash
@@ -59,7 +59,7 @@ function BatchUpsertIterator:new(opts)
5959
space_name = opts.space.name,
6060
opts = execute_on_storage_opts,
6161
batches_by_replicasets = sharding_data.batches,
62-
next_index = next_replicaset,
62+
next_index = next_index,
6363
next_batch = next_batch,
6464
}
6565

@@ -75,8 +75,10 @@ end
7575
--
7676
-- @return[1] table func_args
7777
-- @return[2] table replicaset
78+
-- @return[3] string replicaset_id
7879
function BatchUpsertIterator:get()
79-
local replicaset = self.next_index
80+
local replicaset_id = self.next_index
81+
local replicaset = self.next_batch.replicaset
8082
local func_args = {
8183
self.space_name,
8284
self.next_batch.tuples,
@@ -86,7 +88,7 @@ function BatchUpsertIterator:get()
8688

8789
self.next_index, self.next_batch = next(self.batches_by_replicasets, self.next_index)
8890

89-
return func_args, replicaset
91+
return func_args, replicaset, replicaset_id
9092
end
9193

9294
return BatchUpsertIterator

crud/common/schema.lua

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ local ReloadSchemaError = errors.new_class('ReloadSchemaError', {capture_stack =
88

99
local const = require('crud.common.const')
1010
local dev_checks = require('crud.common.dev_checks')
11+
local utils = require('crud.common.vshard_utils')
1112

1213
local schema = {}
1314

@@ -234,7 +235,8 @@ function schema.wrap_func_result(space, func, args, opts)
234235
replica_schema_version = box.internal.schema_version()
235236
end
236237
result.storage_info = {
237-
replica_uuid = box.info().uuid,
238+
replica_uuid = box.info().uuid, -- Backward compatibility.
239+
replica_id = utils.get_self_vshard_replica_id(), -- Replacement for replica_uuid.
238240
replica_schema_version = replica_schema_version,
239241
}
240242
end

crud/common/sharding/init.lua

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,13 @@ function sharding.get_replicasets_by_bucket_id(vshard_router, bucket_id)
1818
return nil, GetReplicasetsError:new("Failed to get replicaset for bucket_id %s: %s", bucket_id, err.err)
1919
end
2020

21+
local replicaset_id = utils.get_replicaset_id(vshard_router, replicaset)
22+
if replicaset_id == nil then
23+
return nil, GetReplicasetsError:new("Failed to get replicaset id for bucket_id %s replicaset", bucket_id)
24+
end
25+
2126
return {
22-
[replicaset.uuid] = replicaset,
27+
[replicaset_id] = replicaset,
2328
}
2429
end
2530

@@ -206,8 +211,8 @@ end
206211
-- Specified space
207212
--
208213
-- @return[1] batches
209-
-- Map where key is a replicaset and value
210-
-- is table of tuples related to this replicaset
214+
-- Map where key is a replicaset id and value
215+
-- is replicaset and table of tuples related to this replicaset
211216
function sharding.split_tuples_by_replicaset(vshard_router, tuples, space, opts)
212217
dev_checks('table', 'table', 'table', {
213218
operations = '?table',
@@ -247,15 +252,25 @@ function sharding.split_tuples_by_replicaset(vshard_router, tuples, space, opts)
247252
sharding_data.bucket_id, err.err)
248253
end
249254

250-
local record_by_replicaset = batches[replicaset] or {tuples = {}}
255+
local replicaset_id = utils.get_replicaset_id(vshard_router, replicaset)
256+
if replicaset_id == nil then
257+
return nil, GetReplicasetsError:new(
258+
"Failed to get replicaset id for bucket_id %s replicaset",
259+
sharding_data.bucket_id)
260+
end
261+
262+
local record_by_replicaset = batches[replicaset_id] or {
263+
replicaset = replicaset,
264+
tuples = {},
265+
}
251266
table.insert(record_by_replicaset.tuples, tuple)
252267

253268
if opts.operations ~= nil then
254269
record_by_replicaset.operations = record_by_replicaset.operations or {}
255270
table.insert(record_by_replicaset.operations, opts.operations[i])
256271
end
257272

258-
batches[replicaset] = record_by_replicaset
273+
batches[replicaset_id] = record_by_replicaset
259274
end
260275

261276
return {

0 commit comments

Comments
 (0)