Skip to content

Commit f199991

Browse files
committed
WIP: config/schema: collect annotations in :pairs()
Sometimes we need to know somethings about parent nodes during processing of a current node. The ideal solution would be pre-process schema in `schema.new()` and saturate schema nodes with extra information. For example, we can add a `parent` field. Or merge annotations from the root node down to the current one and store in the current node. However, we have shared schema nodes between instance_config and cluster_config. I'm in a doubt whether the copying in appropriate places would be error-prone. The next commit needs the annotations from the parent nodes in `<schema>:pairs()`, so this functionality is added to this particular method. TBD: Consider the alternative approach with precomputing on `schema.new()` and a copying function for a schema. TBD: Add a test. TBD: Part of #xxxx NO_DOC=the schema module is internal, at least now NO_CHANGELOG=see NO_DOC
1 parent 59f7371 commit f199991

File tree

1 file changed

+39
-1
lines changed

1 file changed

+39
-1
lines changed

src/box/lua/config/utils/schema.lua

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,31 @@ local function walkthrough_assert_table(ctx, schema, data)
102102
schema.type, type(data))
103103
end
104104

105+
-- XXX
106+
local function walkthrough_add_annotations(ctx, schema)
107+
assert(ctx.annotations ~= nil)
108+
local non_annotation_keys = {
109+
type = true,
110+
fields = true,
111+
key = true,
112+
value = true,
113+
items = true,
114+
}
115+
local frame = table.copy(ctx.annotations[#ctx.annotations] or {})
116+
for k, v in pairs(schema) do
117+
if not non_annotation_keys[k] then
118+
frame[k] = v
119+
end
120+
end
121+
table.insert(ctx.annotations, frame)
122+
end
123+
124+
-- XXX
125+
local function walkthrough_remove_annotations(ctx)
126+
assert(ctx.annotations ~= nil)
127+
table.remove(ctx.annotations)
128+
end
129+
105130
-- }}} Walkthrough helpers
106131

107132
-- {{{ Scalar definitions
@@ -1345,13 +1370,18 @@ end
13451370
-- {{{ <schema object>:pairs()
13461371

13471372
local function schema_pairs_append_node(schema, ctx)
1373+
walkthrough_add_annotations(ctx, schema)
13481374
table.insert(ctx.acc, {
13491375
path = table.copy(ctx.path),
13501376
schema = schema,
1377+
annotations = ctx.annotations[#ctx.annotations]
13511378
})
1379+
walkthrough_remove_annotations(ctx)
13521380
end
13531381

13541382
local function schema_pairs_impl(schema, ctx)
1383+
walkthrough_add_annotations(ctx, schema)
1384+
13551385
if is_scalar(schema) then
13561386
schema_pairs_append_node(schema, ctx)
13571387
elseif schema.type == 'record' then
@@ -1367,6 +1397,8 @@ local function schema_pairs_impl(schema, ctx)
13671397
else
13681398
assert(false)
13691399
end
1400+
1401+
walkthrough_remove_annotations(ctx)
13701402
end
13711403

13721404
-- Walk over the schema and return scalar, array and map schema
@@ -1377,12 +1409,18 @@ end
13771409
-- for _, w in schema:pairs() do
13781410
-- local path = w.path
13791411
-- local schema = w.schema
1412+
-- local annotations = w.annotations
13801413
-- <...>
13811414
-- end
13821415
--
1416+
-- w.annotations contains all the annotations merged from the root
1417+
-- schema node down to the given one. If the same annotation is
1418+
-- present in an ancestor node and in an descendant node, the
1419+
-- latter is preferred.
1420+
--
13831421
-- TODO: Rewrite it without collecting a list beforehand.
13841422
function methods.pairs(self)
1385-
local ctx = walkthrough_start(self, {acc = {}})
1423+
local ctx = walkthrough_start(self, {acc = {}, annotations = {}})
13861424
schema_pairs_impl(rawget(self, 'schema'), ctx)
13871425
return fun.iter(ctx.acc)
13881426
end

0 commit comments

Comments
 (0)