Skip to content

Commit 77d39f6

Browse files
committed
schema: fix stale schema for metadata generation
Corrects using of an stale schema to generate metadata during `crud.update`, `crud.insert`, `crud.insert_*`, `crud.replace`, `crud.replace_*`, `crud.upsert`, `crud.upsert_*`, `crud.delete`, `crud.max`, `crud.min`, `crud.select` and `crud.get` working. If the implemented `fetch_latest_metadata` option is used, it is guaranteed that the metadata will be up-to-date. Before receiving the space format, a mismatch check will be performed between the scheme version on all involved storage and the scheme version in the net_box connection of the router. In case of mismatch, the schema reload will be triggered. Closes #236
1 parent 781ef16 commit 77d39f6

25 files changed

+753
-88
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
1414
`upsert`, `upsert_object`, `upsert_many`, `upsert_object_many`,
1515
`update`, `delete`. (#267).
1616

17+
### Fixed
18+
* Crud DML operations was returning stale schema for metadata generation (#236).
19+
1720
## [1.1.1] - 24-03-23
1821

1922
### Changed

README.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,10 @@ where:
236236
the sole responsibility of the developer
237237
* `noreturn` (`?boolean`) - suppress successfully processed tuple
238238
(first return value is `nil`). `false` by default
239+
* `fetch_latest_metadata` (`?boolean`) - guarantees the
240+
up-to-date metadata (space format) in first return value, otherwise
241+
it may not take into account the latest migration of the data format.
242+
Performance overhead is up to 15%. `false` by default
239243

240244
Returns metadata and array contains one inserted row, error.
241245

@@ -303,6 +307,10 @@ where:
303307
the sole responsibility of the developer
304308
* `noreturn` (`?boolean`) - suppress successfully processed tuples
305309
(first return value is `nil`). `false` by default
310+
* `fetch_latest_metadata` (`?boolean`) - guarantees the
311+
up-to-date metadata (space format) in first return value, otherwise
312+
it may not take into account the latest migration of the data format.
313+
Performance overhead is up to 15%. `false` by default
306314

307315
Returns metadata and array with inserted rows, array of errors.
308316
Each error object can contain field `operation_data`.
@@ -441,6 +449,10 @@ where:
441449
* `vshard_router` (`?string|table`) - Cartridge vshard group name or
442450
vshard router instance. Set this parameter if your space is not
443451
a part of the default vshard cluster
452+
* `fetch_latest_metadata` (`?boolean`) - guarantees the
453+
up-to-date metadata (space format) in first return value, otherwise
454+
it may not take into account the latest migration of the data format.
455+
Performance overhead is up to 15%. `false` by default
444456

445457
Returns metadata and array contains one row, error.
446458

@@ -480,6 +492,10 @@ where:
480492
a part of the default vshard cluster
481493
* `noreturn` (`?boolean`) - suppress successfully processed tuple
482494
(first return value is `nil`). `false` by default
495+
* `fetch_latest_metadata` (`?boolean`) - guarantees the
496+
up-to-date metadata (space format) in first return value, otherwise
497+
it may not take into account the latest migration of the data format.
498+
Performance overhead is up to 15%. `false` by default
483499

484500
Returns metadata and array contains one updated row, error.
485501

@@ -518,6 +534,10 @@ where:
518534
a part of the default vshard cluster
519535
* `noreturn` (`?boolean`) - suppress successfully processed tuple
520536
(first return value is `nil`). `false` by default
537+
* `fetch_latest_metadata` (`?boolean`) - guarantees the
538+
up-to-date metadata (space format) in first return value, otherwise
539+
it may not take into account the latest migration of the data format.
540+
Performance overhead is up to 15%. `false` by default
521541

522542
Returns metadata and array contains one deleted row (empty for vinyl), error.
523543

@@ -567,6 +587,10 @@ where:
567587
the sole responsibility of the developer
568588
* `noreturn` (`?boolean`) - suppress successfully processed tuple
569589
(first return value is `nil`). `false` by default
590+
* `fetch_latest_metadata` (`?boolean`) - guarantees the
591+
up-to-date metadata (space format) in first return value, otherwise
592+
it may not take into account the latest migration of the data format.
593+
Performance overhead is up to 15%. `false` by default
570594

571595
Returns inserted or replaced rows and metadata or nil with error.
572596

@@ -634,6 +658,10 @@ where:
634658
the sole responsibility of the developer
635659
* `noreturn` (`?boolean`) - suppress successfully processed tuples
636660
(first return value is `nil`). `false` by default
661+
* `fetch_latest_metadata` (`?boolean`) - guarantees the
662+
up-to-date metadata (space format) in first return value, otherwise
663+
it may not take into account the latest migration of the data format.
664+
Performance overhead is up to 15%. `false` by default
637665

638666
Returns metadata and array with inserted/replaced rows, array of errors.
639667
Each error object can contain field `operation_data`.
@@ -772,6 +800,10 @@ where:
772800
a part of the default vshard cluster
773801
* `noreturn` (`?boolean`) - suppress successfully processed tuple
774802
(first return value is `nil`). `false` by default
803+
* `fetch_latest_metadata` (`?boolean`) - guarantees the
804+
up-to-date metadata (space format) in first return value, otherwise
805+
it may not take into account the latest migration of the data format.
806+
Performance overhead is up to 15%. `false` by default
775807

776808
Returns metadata and empty array of rows or nil, error.
777809

@@ -835,6 +867,10 @@ where:
835867
a part of the default vshard cluster
836868
* `noreturn` (`?boolean`) - suppress successfully processed tuples
837869
(first return value is `nil`). `false` by default
870+
* `fetch_latest_metadata` (`?boolean`) - guarantees the
871+
up-to-date metadata (space format) in first return value, otherwise
872+
it may not take into account the latest migration of the data format.
873+
Performance overhead is up to 15%. `false` by default
838874

839875
Returns metadata and array of errors.
840876
Each error object can contain field `operation_data`.
@@ -977,6 +1013,10 @@ where:
9771013
a part of the default vshard cluster
9781014
* `yield_every` (`?number`) - number of tuples processed on storage to yield after,
9791015
`yield_every` should be > 0, default value is 1000
1016+
* `fetch_latest_metadata` (`?boolean`) - guarantees the
1017+
up-to-date metadata (space format) in first return value, otherwise
1018+
it may not take into account the latest migration of the data format.
1019+
Performance overhead is up to 15%. `false` by default
9801020

9811021

9821022
Returns metadata and array of rows, error.

crud/borders.lua

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ local borders = {}
1616
local STAT_FUNC_NAME = '_crud.get_border_on_storage'
1717

1818

19-
local function get_border_on_storage(border_name, space_name, index_id, field_names)
20-
dev_checks('string', 'string', 'number', '?table')
19+
local function get_border_on_storage(border_name, space_name, index_id, field_names, fetch_latest_metadata)
20+
dev_checks('string', 'string', 'number', '?table', '?boolean')
2121

2222
assert(border_name == 'min' or border_name == 'max')
2323

@@ -38,6 +38,7 @@ local function get_border_on_storage(border_name, space_name, index_id, field_na
3838
return schema.wrap_func_result(space, get_index_border, {index}, {
3939
add_space_schema_hash = true,
4040
field_names = field_names,
41+
fetch_latest_metadata = fetch_latest_metadata,
4142
})
4243
end
4344

@@ -71,9 +72,10 @@ local function call_get_border_on_router(vshard_router, border_name, space_name,
7172
timeout = '?number',
7273
fields = '?table',
7374
vshard_router = '?string|table',
75+
fetch_latest_metadata = '?boolean',
7476
})
7577

76-
local space, err = utils.get_space(space_name, vshard_router, opts.timeout)
78+
local space, err, netbox_schema_version = utils.get_space(space_name, vshard_router, opts.timeout)
7779
if err ~= nil then
7880
return nil, BorderError:new("An error occurred during the operation: %s", err), const.NEED_SCHEMA_RELOAD
7981
end
@@ -108,9 +110,9 @@ local function call_get_border_on_router(vshard_router, border_name, space_name,
108110
replicasets = replicasets,
109111
timeout = opts.timeout,
110112
}
111-
local results, err = call.map(vshard_router,
113+
local results, err, storages_info = call.map(vshard_router,
112114
STAT_FUNC_NAME,
113-
{border_name, space_name, index.id, field_names},
115+
{border_name, space_name, index.id, field_names, opts.fetch_latest_metadata},
114116
call_opts
115117
)
116118

@@ -154,6 +156,14 @@ local function call_get_border_on_router(vshard_router, border_name, space_name,
154156
end
155157
end
156158

159+
if opts.fetch_latest_metadata == true then
160+
-- This option is temporary and is related to [1], [2].
161+
-- [1] https://github.com/tarantool/crud/issues/236
162+
-- [2] https://github.com/tarantool/crud/issues/361
163+
space = utils.fetch_latest_metadata_when_map_storages(space, space_name, vshard_router, opts,
164+
storages_info, netbox_schema_version)
165+
end
166+
157167
local result = utils.format_result({res_tuple}, space, field_names)
158168

159169
if opts.fields ~= nil then

crud/common/map_call_cases/base_postprocessor.lua

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ function BasePostprocessor:new(vshard_router)
1313
early_exit = false,
1414
errs = nil,
1515
vshard_router = vshard_router,
16+
storage_info = {},
1617
}
1718

1819
setmetatable(postprocessor, self)
@@ -52,6 +53,12 @@ function BasePostprocessor:collect(result_info, err_info)
5253
wrapper_args = '?table',
5354
})
5455

56+
if type(result_info.value[1]) == 'table' then
57+
self.storage_info[result_info.key] = {}
58+
local replica_schema_version = result_info.value[1].replica_schema_version
59+
self.storage_info[result_info.key].replica_schema_version = replica_schema_version
60+
end
61+
5562
local err = err_info.err
5663
if err == nil and result_info.value[1] == nil then
5764
err = result_info.value[2]
@@ -78,8 +85,9 @@ end
7885
--
7986
-- @return[1] table results
8087
-- @return[2] table errs
88+
-- @return[3] table storage_info
8189
function BasePostprocessor:get()
82-
return self.results, self.errs
90+
return self.results, self.errs, self.storage_info
8391
end
8492

8593
return BasePostprocessor

crud/common/map_call_cases/batch_postprocessor.lua

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ function BatchPostprocessor:collect(result_info, err_info)
3939
wrapper_args = '?table',
4040
})
4141

42+
if result_info.value ~= nil then
43+
self.storage_info[result_info.key] = {}
44+
self.storage_info[result_info.key].replica_schema_version = result_info.value[3]
45+
end
46+
4247
local errs = {err_info.err}
4348
if err_info.err == nil then
4449
errs = result_info.value[2]

crud/common/schema.lua

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ end
5151
local reload_in_progress = {}
5252
local reload_schema_cond = {}
5353

54-
local function reload_schema(vshard_router)
54+
function schema.reload_schema(vshard_router)
5555
local replicasets = vshard_router:routeall()
5656
local vshard_router_name = vshard_router.name
5757

@@ -96,14 +96,16 @@ function schema.wrap_func_reload(vshard_router, func, ...)
9696
break
9797
end
9898

99-
local ok, reload_schema_err = reload_schema(vshard_router)
99+
local ok, reload_schema_err = schema.reload_schema(vshard_router)
100100
if not ok then
101101
log.warn("Failed to reload schema: %s", reload_schema_err)
102102
break
103103
end
104104

105105
i = i + 1
106106
if i > const.RELOAD_RETRIES_NUM then
107+
local warn_msg = "Number of attempts to reload schema has been ended: %s"
108+
log.warn(warn_msg, const.RELOAD_RETRIES_NUM)
107109
break
108110
end
109111
end
@@ -221,6 +223,17 @@ function schema.wrap_func_result(space, func, args, opts)
221223
end
222224
end
223225

226+
if opts.fetch_latest_metadata == true then
227+
local replica_schema_version
228+
if box.info.schema_version ~= nil then
229+
replica_schema_version = box.info.schema_version
230+
else
231+
replica_schema_version = box.internal.schema_version()
232+
end
233+
result.replica_uuid = box.info().uuid
234+
result.replica_schema_version = replica_schema_version
235+
end
236+
224237
return result
225238
end
226239

@@ -235,7 +248,9 @@ function schema.wrap_box_space_func_result(space, box_space_func_name, box_space
235248
return space[box_space_func_name](space, unpack(box_space_func_args))
236249
end
237250

238-
return schema.wrap_func_result(space, func, {space, box_space_func_name, box_space_func_args}, opts)
251+
local res, err = schema.wrap_func_result(space, func, {space, box_space_func_name, box_space_func_args}, opts)
252+
253+
return res, err
239254
end
240255

241256
-- schema.result_needs_reload checks that schema reload can

crud/common/stash.lua

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,20 @@ local stash = {}
2020
-- @tfield string stats_metrics_registry
2121
-- Stash for metrics rocks statistics registry.
2222
--
23+
-- @tfield string storages_info_on_select
24+
-- Stash for storages info during select working registry.
25+
--
26+
-- @tfield string select_module_compat_info
27+
-- Stash for select compatability version registry.
28+
--
2329
stash.name = {
2430
cfg = '__crud_cfg',
2531
stats_internal = '__crud_stats_internal',
2632
stats_local_registry = '__crud_stats_local_registry',
2733
stats_metrics_registry = '__crud_stats_metrics_registry',
2834
ddl_triggers = '__crud_ddl_spaces_triggers',
35+
storages_info_on_select = '__storages_info_on_select',
36+
select_module_compat_info = '__select_module_compat_info',
2937
}
3038

3139
--- Setup Tarantool Cartridge reload.

0 commit comments

Comments
 (0)