Skip to content

Commit 2675925

Browse files
GRISHNOVDifferentialOrange
authored andcommitted
schema: fix stale schema for metadata generation
Corrects using of an stale schema to generate metadata for `crud.update`, `crud.insert`, `crud.insert_*`, `crud.replace`, `crud.replace_*`, `crud.upsert`, `crud.upsert_*`, `crud.delete`, `crud.max`, `crud.min`, `crud.select`, `crud.pairs` and `crud.get`. 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 56348ca commit 2675925

25 files changed

+827
-90
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ 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 returning stale schema for metadata generation.
19+
Now you may use `fetch_latest_metadata` flag to work with latest schema (#236).
20+
1721
## [1.1.1] - 24-03-23
1822

1923
### Changed

README.md

+40
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

+15-5
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

+11-1
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,14 @@ function BasePostprocessor:collect(result_info, err_info)
5253
wrapper_args = '?table',
5354
})
5455

56+
if result_info.value ~= nil and type(result_info.value[1]) == 'table' then
57+
if result_info.value[1].storage_info ~= nil then
58+
self.storage_info[result_info.key] = {
59+
replica_schema_version = result_info.value[1].storage_info.replica_schema_version
60+
}
61+
end
62+
end
63+
5564
local err = err_info.err
5665
if err == nil and result_info.value[1] == nil then
5766
err = result_info.value[2]
@@ -78,8 +87,9 @@ end
7887
--
7988
-- @return[1] table results
8089
-- @return[2] table errs
90+
-- @return[3] table storage_info
8191
function BasePostprocessor:get()
82-
return self.results, self.errs
92+
return self.results, self.errs, self.storage_info
8393
end
8494

8595
return BasePostprocessor

crud/common/map_call_cases/batch_postprocessor.lua

+4
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ 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] = {replica_schema_version = result_info.value[3]}
44+
end
45+
4246
local errs = {err_info.err}
4347
if err_info.err == nil then
4448
errs = result_info.value[2]

crud/common/schema.lua

+17-2
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,19 @@ 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.storage_info = {
234+
replica_uuid = box.info().uuid,
235+
replica_schema_version = replica_schema_version,
236+
}
237+
end
238+
224239
return result
225240
end
226241

crud/common/stash.lua

+4
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,16 @@ local stash = {}
2020
-- @tfield string stats_metrics_registry
2121
-- Stash for metrics rocks statistics registry.
2222
--
23+
-- @tfield string select_module_compat_info
24+
-- Stash for select compatability version registry.
25+
--
2326
stash.name = {
2427
cfg = '__crud_cfg',
2528
stats_internal = '__crud_stats_internal',
2629
stats_local_registry = '__crud_stats_local_registry',
2730
stats_metrics_registry = '__crud_stats_metrics_registry',
2831
ddl_triggers = '__crud_ddl_spaces_triggers',
32+
select_module_compat_info = '__select_module_compat_info',
2933
}
3034

3135
--- Setup Tarantool Cartridge reload.

0 commit comments

Comments
 (0)