pub fn upsert_named_entry<E>(
arr: &mut Vec<Value>,
new_entry: Value,
name_key: &'static str,
on_missing_name: impl FnOnce() -> E,
) -> Result<bool, E>Expand description
Upsert new_entry into a typed sequence of programs.yaml-shaped
entries by matching on new_entry’s <name_key> scalar — the
idempotent “replace-in-place if present, else append” contract
every writer-side aggregator overlay lands the same 11-line block
in front of. Returns Ok(true) when the entry was appended new,
Ok(false) when an existing entry with the same <name_key>
value was replaced in place (preserving position); returns
on_missing_name() when new_entry doesn’t carry <name_key>
as a string scalar (the caller’s own typed
crate::RenderError-shaped error surface, threaded through the
closure so this helper stays crate-agnostic).
Two identical-shape call sites collapse onto this helper — the
two [caixa-flux] writer-side upsert paths that both land a
programs.yaml entry into a programs: sequence differing only
on the outer navigation:
caixa_flux::upsert_into_helmrelease_programs— the aggregator-HelmRelease shape, upserting intospec.values.programs[]on aHelmReleasedocument;caixa_flux::upsert_into_programs_yaml— the bare-values.yaml shape, upserting intoprograms[]at the values.yaml root.
Until this lift landed both call sites re-inlined the same
verbatim 11-line block — extract-name-scalar-or-error, iterate
the sequence, replace-in-place-on-match else fall through to
push — with no compile-time link between the two: a rebrand on
either side (a per-entry match key rename beyond the currently-
lifted crate::FLEET_PROGRAMS_KEY_NAME, the idempotency
contract’s semantic reshaping — e.g. matching on
(name, namespace) for the M4 multi-namespace aggregator flow
once the lareira-fleet-programs chart admits per-entry
namespace: overrides, the return-value’s bool-shape shift
once “replace” grows a merge-semantics axis) would silently
desynchronize the two writer-side paths — one path idempotently
upserts under the new contract while the other silently keeps
the old shape, and the failure surfaces at aggregator-apply
time as a duplicated / missing / mis-merged entry far from the
rebrand commit’s source. Peer of the sibling render-side lifts
(single_field_overlay, servico_m2_overlay,
insert_first_seen) on the same “the same shape written
verbatim ≥ 2 times becomes a typed helper” trajectory THEORY.md
§I.3.5 promotes to a build-time concern.
The name_key axis stays parametric (rather than pinned to
crate::FLEET_PROGRAMS_KEY_NAME inside the helper) so a
future per-entry match on a different discriminator scalar (an
M4 id: axis promoted alongside name:, the future
mesh.pleme.io/v1alpha1/Aplicacao CR materializer’s per-entry
spec.selector upsert path) reaches for the same helper with a
different key rather than re-inlining the loop. The closure-
shaped error surface (rather than a bare Result<bool, &'static str> or an added typed error variant in this crate)
keeps every caller’s own error enum authoritative — the
diagnostic remediation for a missing-name-scalar in a programs-
yaml entry rightly names the caller’s aggregator schema
(spec.values.programs[].name for the HelmRelease shape,
programs[].name for the bare values.yaml shape), not this
generic helper.
§Errors
Returns on_missing_name() when new_entry.get(name_key) is
not a serde_yaml::Value::String — the closure surfaces the
caller’s own typed error variant naming the offending schema
axis. On success returns Ok(true) for a newly-appended entry,
Ok(false) for an in-place replacement.