Keep mesh and node config with their history, and move whole-mesh module layers onto each assigned node (hq issue 630)
An assignment is one module on one node, so a new whole-mesh layer is refused and the ones held are laid under each assigned node's layer, every replaced layer kept, so no machine composes differently.
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
-- A config value comes from four sources, the last set winning (novox/hq issue 630): the module's
|
||||
-- default, mesh config, node config, and the module's own value on the node. Mesh config and node config
|
||||
-- hold values only for the predefined keys, a fixed list kept in the catalogue (`predefined.json`). An
|
||||
-- assignment is one module on one node: there is no module layer for the whole mesh any more.
|
||||
|
||||
-- The list of predefined keys, as the catalogue's predefined.json last said it. Replaced whole when a
|
||||
-- build of the catalogue carries the file; `repository` and `commit` say which.
|
||||
create table predefined_key (
|
||||
key text primary key,
|
||||
type text not null check (type in ('number', 'string', 'boolean')),
|
||||
why text not null,
|
||||
repository text,
|
||||
commit text,
|
||||
listed_at timestamptz not null default now()
|
||||
);
|
||||
|
||||
-- Mesh config (node null) and node config: one value per predefined key, and per node. Not a foreign key
|
||||
-- to predefined_key: a key the list drops keeps its value, said as reaching nothing, rather than losing it.
|
||||
create table config (
|
||||
key text not null,
|
||||
node uuid references node(id) on delete cascade,
|
||||
value jsonb not null,
|
||||
set_at timestamptz not null default now(),
|
||||
set_by text,
|
||||
why text not null
|
||||
);
|
||||
create unique index config_for_the_mesh on config (key) where node is null;
|
||||
create unique index config_for_a_node on config (key, node) where node is not null;
|
||||
|
||||
-- Every value that was replaced or cleared, with who set it and why, and who replaced it and why.
|
||||
create table config_history (
|
||||
key text not null,
|
||||
node uuid references node(id) on delete cascade,
|
||||
value jsonb not null,
|
||||
set_at timestamptz,
|
||||
set_by text,
|
||||
why text,
|
||||
replaced_at timestamptz not null default now(),
|
||||
-- set · clear
|
||||
replaced_by text not null,
|
||||
replaced_why text
|
||||
);
|
||||
create index config_history_by_key on config_history (key, node, replaced_at desc);
|
||||
|
||||
-- The module layer for the whole mesh goes: each one is laid under the layer of every node the module is
|
||||
-- assigned to — the mesh's values first, the node's over them, maps merged key by key as composition
|
||||
-- merged them — so every machine composes what it did. Every layer replaced, and the mesh-wide layer
|
||||
-- itself, is kept in settings_history (ADR 0217) with the reason `moved-to-nodes`. A mesh-wide layer of
|
||||
-- a module assigned nowhere is kept in the history only: no machine read it.
|
||||
create function pg_temp.config_630_merge(under jsonb, over jsonb) returns jsonb language plpgsql immutable as $$
|
||||
declare
|
||||
merged jsonb;
|
||||
k text;
|
||||
begin
|
||||
if jsonb_typeof(under) is distinct from 'object' or jsonb_typeof(over) is distinct from 'object' then
|
||||
return over;
|
||||
end if;
|
||||
merged := under;
|
||||
for k in select jsonb_object_keys(over) loop
|
||||
if merged ? k then
|
||||
merged := jsonb_set(merged, array[k], pg_temp.config_630_merge(merged -> k, over -> k));
|
||||
else
|
||||
merged := merged || jsonb_build_object(k, over -> k);
|
||||
end if;
|
||||
end loop;
|
||||
return merged;
|
||||
end
|
||||
$$;
|
||||
|
||||
insert into settings_history (node, module, values, set_at, replaced_by, set_by)
|
||||
select t.node, t.module, t.values, t.set_at, 'moved-to-nodes', t.set_by
|
||||
from settings t
|
||||
join settings s on s.module = t.module and s.node is null
|
||||
where t.node is not null
|
||||
and exists (select 1 from assignment a where a.node = t.node and a.module = t.module);
|
||||
|
||||
insert into settings_history (node, module, values, set_at, replaced_by, set_by)
|
||||
select null, module, values, set_at, 'moved-to-nodes', set_by from settings where node is null;
|
||||
|
||||
insert into settings (node, module, values, set_at, set_by)
|
||||
select a.node, s.module, s.values, now(),
|
||||
coalesce(s.set_by || '; ', '') || 'moved from the whole mesh''s layer to this node''s (novox/hq issue 630)'
|
||||
from settings s
|
||||
join assignment a on a.module = s.module
|
||||
where s.node is null
|
||||
on conflict (node, module) where node is not null
|
||||
do update set values = pg_temp.config_630_merge(excluded.values, settings.values),
|
||||
set_at = now(),
|
||||
set_by = coalesce(settings.set_by || '; ', '') ||
|
||||
'the whole mesh''s layer laid under it (novox/hq issue 630)';
|
||||
|
||||
delete from settings where node is null;
|
||||
Reference in New Issue
Block a user