pub struct UpgradeFromEntry {
pub from: String,
pub instructions: Vec<UpgradeInstruction>,
}Expand description
One upgrade entry: the prior version we’re upgrading from, plus the instruction sequence to execute.
Fields§
§from: StringSemver of the prior version. Authored as a literal string;
validated lazily by UpgradeFromEntry::validate.
instructions: Vec<UpgradeInstruction>Ordered list of instructions to execute. Empty list = “no-op upgrade” (rare; usually means only documentation changed).
Implementations§
Source§impl UpgradeFromEntry
impl UpgradeFromEntry
Sourcepub fn prior_versao(&self) -> &str
pub fn prior_versao(&self) -> &str
Prior-versao semver-2 literal this entry declares an upgrade
path from — the string the OTP-shape release_handler:install_release/1
analog matches the running caixa’s :versao against at hot-
upgrade dispatch time to pick this entry’s :instructions
sequence. Returned byte-for-byte from the typed slot’s own
String storage; no cloning, no re-parsing.
The M2 companion of the closed M3 mesh-slot scalar-accessor
family — sibling in shape to crate::Membro::versao_requirement
(a40b0e3), crate::Membro::nome (4a32abf), and the
[crate::WitContract::{source, destination, world_ref}]
(7f0fd43 / 0804823) / [crate::Entrada::{hostname, destination}]
(11f3dfe / 6db982c) &str accessors already routing every
per-mesh-slot-atom scalar-value axis through one typed dispatch
on the substrate primitive — extended here onto the first per-
M2-slot scalar-value axis. Every downstream consumer of the
M2 :upgrade-from :from axis (the UpgradeFromEntry::validate
SemVer-2 parse gate, the validate_upgrade_from cross-entry
duplicate-detection re-parse assertion, the
validate_upgrade_from_against_versao precedence gate,
the validate_upgrade_from_against_behavior state-change-
callback coherence gate, every per-arm error variant carrying
the offending :from verbatim for feira lint rendering)
now reads through this one accessor rather than open-coding
&self.from / &entry.from / self.from.clone() /
entry.from.clone().
A future extension of the axis (an M4 typed :from-range slot
composing multiple prior versions into one entry, an operator-
side pre-parsed semver::Version cache the accessor could
materialize behind the same &str return contract, a per-
cluster :placement-scoped prior-versao overlay the
caixa-operator reconciles ahead of dispatch) migrates as a
single caixa-core edit rather than a coordinated rewrite of
the four validate-side call sites + every downstream error-
variant carrying :from.
Sourcepub fn instructions(&self) -> &[UpgradeInstruction]
pub fn instructions(&self) -> &[UpgradeInstruction]
Substrate-canonical per-:upgrade-from :instructions
OTP-appup migration-instruction-list slice-return accessor
every per-entry instructions-list reader keys off — returns
the author-declared :instructions list verbatim as a
&[UpgradeInstruction] slice-view over the same backing
buffer the raw self.instructions.as_slice() field access
borrows from. Non-optional: an empty slice is the load-bearing
“author declared :instructions ()” sentinel — the
Vec<UpgradeInstruction>::default()-produced empty tail the
UpgradeFromEntry::instructions field’s own docstring already
names as the “no-op upgrade” shape (a metadata-only upgrade
entry — the operator’s :from-match dispatch matches the entry
but runs no instructions, advancing straight to the “traffic
swap” step) and every peer within-entry cross-instruction gate
no-ops against without allocating a new Vec per gate.
The :upgrade-from :instructions slot carries the per-:from
OTP-appup ordered instruction list the wasm-operator’s hot-
upgrade dispatch materializes one per-instruction runtime
primitive from — the Erlang/OTP appup’s per-{from, to, UpgradeInstructions, DowngradeInstructions} entry’s
UpgradeInstructions list (code:load_module/1 /
gen_server:code_change/3 / code:soft_purge/1 /
code:purge/1 / restart_new_emulator — see INSPIRATIONS
§II.4), projected through the tatara-lisp
:upgrade-from ((:from … :instructions …)) author surface
onto a typed Vec<UpgradeInstruction> whose per-element
variant is UpgradeInstruction::LoadModule /
UpgradeInstruction::StateChange /
UpgradeInstruction::SoftPurge / UpgradeInstruction::Purge
/ UpgradeInstruction::Restart. Every downstream consumer
that fans on the per-entry instruction list keys off this
slice (the UpgradeFromEntry::validate per-instruction
shape-check fan-out, the seven paired within-entry cross-
instruction gates Self::validate_restart_exclusive /
Self::validate_state_change_ordering /
Self::validate_purge_ordering /
Self::validate_state_change_before_cleanup /
Self::validate_load_singularity /
Self::validate_state_change_singularity /
Self::validate_cleanup_singularity, the layout-side
crate::layout::StandardLayout’s per-:state-change
script-existence fan-out
(crate::layout::LayoutError::MissingEntry’s
LAYOUT_MISSING_ENTRY_KIND_UPGRADE_SCRIPT arm), the cross-slot
validate_upgrade_from_against_behavior gate’s per-entry
:state-change-instruction detection loop, every future
wasm-operator (M2.5) per-:from-match hot-upgrade dispatch’s
per-instruction runtime-primitive fan-out, every future M4
mesh.pleme.io/v1alpha1/Caixa CR materializer’s per-entry
upgrade-plan admission-webhook fan-out).
Prior to this lift the .instructions Vec<UpgradeInstruction>
was accessed inline at nine production sites across
caixa-core/src/upgrade.rs and caixa-core/src/layout.rs —
the UpgradeFromEntry::validate per-instruction shape-check
fan-out (for instr in &self.instructions), the paired
Self::validate_restart_exclusive restart-count / other-kind
projections + .len() probe (three raw-access sites in one
gate), the Self::validate_state_change_ordering /
Self::validate_purge_ordering /
Self::validate_state_change_before_cleanup /
Self::validate_load_singularity /
Self::validate_state_change_singularity /
Self::validate_cleanup_singularity within-entry cross-
instruction gate traversal heads, the peer
validate_upgrade_from_against_behavior cross-slot
composition gate’s for instr in &entry.instructions
per-entry :state-change detection loop, and the
crate::layout::StandardLayout-side
for instr in &entry.instructions per-:state-change
script-existence fan-out — nine open-coded field-accesses
that expressed no compile-time link back to the typed slot.
A future extension of the :instructions axis to a richer
author surface (a per-cluster overlay the operator pins
through a future :upgrade-from :instructions-overrides slot
so a canary cluster runs a (:state-change …) before the
production fleet does, a per-tenant instruction-list overlay
the M4 CR materializer resolves per-CR to inject cluster-
specific (:soft-purge …) cooldown adjustments, a promotion
of the plain Vec<UpgradeInstruction> to a richer
{static, dynamic} partition once virtual-actor-style
dynamic-instruction composition (an operator-derived
(:load-module …) sequence computed from the running
module set at upgrade time) comes into typed scope, a
per-instruction pre-condition scalar the future adaptive-
upgrade engine reads to bias per-instruction retry
strategy) would have had to be threaded through all nine
open-coded copies in lockstep or one consumer would silently
disagree with the peers on which instruction sequence a
given :upgrade-from entry resolves to — the per-
instruction shape-check reading the raw slot while the
paired within-entry ordering gates read an operator-resolved
slot would silently split the build-time per-entry gate
cohort from the layout-side script-existence gate + the
cross-slot behavior-composition gate + the runtime hot-
upgrade dispatch, a nine-consumer split across the seven
within-entry cross-instruction gates + the layout invariant +
the cross-slot composition gate far from the source
caixa.lisp with no field naming the instruction-sequence-
drift root cause. Lifting the resolution rule to a typed
method on the substrate primitive means every downstream
consumer of the per-entry OTP-appup instruction-list surface
reaches for exactly one typed dispatch — the resolver’s
accept-set migrates as a unit on any future axis addition.
Fifth slice-return (&[T]) accessor on any M2 or M3 typed
slot — sibling to the seed M2
crate::SupervisorSpec::children (bc92bce) &[ChildSpec]
accessor on the peer per-:supervisor static-child-list
Vec-carry axis, the M3 crate::Placement::clusters
(a6e18d7) &[String] accessor on the peer per-:placement
distribution-target-list Vec-carry axis, the M3
crate::AplicacaoSpec::membros (6c77e36) &[Membro]
accessor on the peer per-:membros node-list Vec-carry
axis, and the M3 crate::AplicacaoSpec::contratos
(0dcc926) &[WitContract] accessor on the peer per-
:contratos edge-list Vec-carry axis. This lift closes the
last unlifted Vec-carry axis on any M2 or M3 typed slot in
the substrate — the four peer axes named in the
crate::SupervisorSpec::children seed docstring
(Placement::clusters, AplicacaoSpec::membros,
AplicacaoSpec::contratos, UpgradeFromEntry::instructions)
are now all closed. The per-UpgradeFromEntry type carried
two axes: the scalar Copy-return
UpgradeFromEntry::prior_versao (75d27a8) on the
:from axis, and now the slice-return
UpgradeFromEntry::instructions on the peer
:instructions axis. Named instructions() to match the
storage field’s name verbatim and the tatara-lisp
author-surface term (:instructions) the field’s own
docstring already carries; the accessor’s identity maps
onto the canonical OTP-appup vocabulary the
crate::upgrade module doc already reaches for (“runs
the instructions in order”). Returns &[UpgradeInstruction]
(not &Vec<UpgradeInstruction>) because every downstream
consumer of the instruction list treats it as a read-only
sequence — the slice-view is the narrowest borrow that
supports every present + roadmapped consumer (.iter(),
.len(), .filter(...).count()) without leaking the
backing Vec’s grow/push/reserve surface that no consumer
of the typed view reaches for (the storage-side Vec
remains reachable through the pub instructions field for
the mutation-carrying Serialize/Deserialize derive
round-trip and per-test fixture-mutation paths).
Sourcepub fn validate(&self) -> Result<(), UpgradeError>
pub fn validate(&self) -> Result<(), UpgradeError>
Verify the :from field is a valid semver, every instruction’s
typed shape, the within-entry (:restart)-exclusivity invariant
(an entry containing (:restart) must contain exactly one
(:restart) and nothing else — see
Self::validate_restart_exclusive), the within-entry
state-change-ordering invariant (every (:state-change …) must
be preceded by a (:load-module …) — see
Self::validate_state_change_ordering), the within-entry
purge-ordering invariant (every (:soft-purge …) / (:purge …)
must be preceded by a (:load-module …) — see
Self::validate_purge_ordering), the within-entry
state-change-before-cleanup ordering invariant (no
(:state-change …) may appear after any (:soft-purge …) /
(:purge …) — see
Self::validate_state_change_before_cleanup), the within-
entry load-singularity invariant (no module appears as the
target of (:load-module …) more than once — see
Self::validate_load_singularity), the within-entry
state-change-singularity invariant (no script appears as the
target of (:state-change …) more than once — see
Self::validate_state_change_singularity), and the within-
entry cleanup-singularity invariant (no module appears as the
target of (:soft-purge …) or (:purge …) more than once
total — see Self::validate_cleanup_singularity).
Trait Implementations§
Source§impl Clone for UpgradeFromEntry
impl Clone for UpgradeFromEntry
Source§fn clone(&self) -> UpgradeFromEntry
fn clone(&self) -> UpgradeFromEntry
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for UpgradeFromEntry
impl Debug for UpgradeFromEntry
Source§impl<'de> Deserialize<'de> for UpgradeFromEntry
impl<'de> Deserialize<'de> for UpgradeFromEntry
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for UpgradeFromEntry
Source§impl PartialEq for UpgradeFromEntry
impl PartialEq for UpgradeFromEntry
Source§impl Serialize for UpgradeFromEntry
impl Serialize for UpgradeFromEntry
impl StructuralPartialEq for UpgradeFromEntry
Auto Trait Implementations§
impl Freeze for UpgradeFromEntry
impl RefUnwindSafe for UpgradeFromEntry
impl Send for UpgradeFromEntry
impl Sync for UpgradeFromEntry
impl Unpin for UpgradeFromEntry
impl UnsafeUnpin for UpgradeFromEntry
impl UnwindSafe for UpgradeFromEntry
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.