pub struct ModuleRuntime { /* private fields */ }Expand description
The per-run module state a deploy command carries: the target’s stored subscription plus the repo’s committed re-anchors. Built once per command (under the advisory lock, after the tracking tables are ensured), mutated only through its own methods so the in-memory view and the stored tables never diverge within a run.
Implementations§
Source§impl ModuleRuntime
impl ModuleRuntime
Sourcepub fn established(&self) -> &BTreeSet<String>
pub fn established(&self) -> &BTreeSet<String>
The modules established on this target (base excluded). THE establishment source for every consumer.
Sourcepub async fn load(
pool: &PgPool,
tracking_table: &TrackingTable,
baselines_dir: &Path,
) -> Result<Self>
pub async fn load( pool: &PgPool, tracking_table: &TrackingTable, baselines_dir: &Path, ) -> Result<Self>
Load the stored subscription and the committed re-anchors. The
consumed-through cursor is not loaded here — it is derived from the
baseline main rows whenever the crossing loop needs it, so a
pre-subscription target (rows but no _modules table yet) needs no
special reconstruction: its provision baseline row seeds the cursor
natively.
Sourcepub fn adoption_baseline(&self) -> Option<(u64, &[MigrationSection])>
pub fn adoption_baseline(&self) -> Option<(u64, &[MigrationSection])>
The baseline adoption reads content from: simply the highest-version committed baseline, re-anchor or not.
Provenance-cut sections make any committed baseline safe to
adopt from, unconsumed re-anchors included: a re-anchor’s remap sections
carry objects already present under the source’s old name, so per-section
adoption records those as satisfied and runs only the plain
sections plus remap sections whose source the target lacks — no
collision, no routing around the re-anchor.
Sourcepub fn needing_baseline_content<'a, I: IntoIterator<Item = &'a String>>(
&self,
modules: I,
) -> Vec<String>
pub fn needing_baseline_content<'a, I: IntoIterator<Item = &'a String>>( &self, modules: I, ) -> Vec<String>
Of modules, those not established here whose pre-baseline state
lives in the adoption baseline (Self::adoption_baseline) —
adopting them requires provision --modules (baseline content), not
replay. Modules absent from it are younger: their whole (break-free)
history is in the migrations and plain apply adopts them.
Sourcepub async fn forecast_crossings(
&self,
migrations: &[ParsedMigration],
) -> Result<BTreeSet<String>>
pub async fn forecast_crossings( &self, migrations: &[ParsedMigration], ) -> Result<BTreeSet<String>>
The never-established modules this apply’s crossing sweep would
SUBSCRIBE — a read-only forecast the apply adoption guard consults so
it can ride a crossing instead of refusing toward provision. Thread a
simulated subscription through every committed re-anchor above the
derived cursor, in version order, using the exact wholeness evaluation
the real loop uses ([evaluate_crossing] fed by [run_eligible]-
filtered acquisition pairs). There is no second ordering or derivation
path: this is a pure read-only replay of the same predicates the sweep
applies, so its prediction cannot drift from what the sweep then does.
A module in the result (a brand-new module whose sources this target holds whole, at a split / modularization / merge crossing) needs NOTHING from the baseline — the crossing relabels objects already present. Modules NOT in the result the guard treats as before: baseline-content refusal if they need it, ordinary replay adoption otherwise. A wholeness membrane stops the walk (its own crossing and everything after are not forecast as subscribing); the real apply loop then surfaces that membrane — a needed-modules block always coincides with the blocked module having baseline content, so a named blocked module still gets the clean baseline-content refusal here, while an unnamed one (bare-source apply) reaches the membrane unpreempted.
No circularity: the evaluation reads only the stored subscription, the
committed re-anchors, and the migration files’ acquisition sections —
never the requested --modules selection.
Sourcepub async fn cross_re_anchors_through(
&mut self,
ceiling: Option<u64>,
) -> Result<()>
pub async fn cross_re_anchors_through( &mut self, ceiling: Option<u64>, ) -> Result<()>
The crossing loop. Consume, in version order, every
committed re-anchor above the derived cursor and at or below ceiling
(None = all of them — the end-of-apply sweep that makes a pure
re-tag land on a fully-up-to-date target).
Single-shot gate+commit per re-anchor: only correct when nothing of
those versions remains to run in this apply — i.e. for re-anchors
strictly below the migration being processed, and for the final sweep.
A re-anchor AT a pending migration’s version goes through the split
Self::gate_re_anchor_at / Self::commit_crossing pair instead
(two-phase): its acquisition delta lives in migration V itself,
so wholeness only finalizes once V’s sections have run.
Sourcepub async fn gate_re_anchor_at(
&self,
version: u64,
acquirable: &BTreeSet<(Option<String>, Option<String>)>,
) -> Result<Option<PendingCrossing>>
pub async fn gate_re_anchor_at( &self, version: u64, acquirable: &BTreeSet<(Option<String>, Option<String>)>, ) -> Result<Option<PendingCrossing>>
Gate phase of the two-phase crossing: evaluate the re-anchor
at exactly version (if one exists above the derived cursor) against the
subscription, WITHOUT writing anything. The caller runs version V’s
sections next and then calls Self::commit_crossing with the
returned pending crossing. On wholeness failure this bails — the
strong membrane: nothing at or after V may run.
Sourcepub async fn commit_crossing(&mut self, pending: PendingCrossing) -> Result<()>
pub async fn commit_crossing(&mut self, pending: PendingCrossing) -> Result<()>
Commit phase of the two-phase crossing: rewrite the subscription through the gated re-anchor’s remaps and record the consumption in the ledger — one transaction (the caller holds the advisory lock). Runs after the version’s own sections completed (acquisition deltas live in migration V), so wholeness has finalized.
The consumption is a what-happened fact recorded like any other: the
re-anchor’s own baseline main row (with its checksum), which
seeds the derived cursor so the re-anchor is never re-evaluated, plus
zero-trace satisfied section rows for exactly the remap sections the
crossing relabeled — those whose source the target holds. Irrelevant
sections (source not held) record nothing. Crossing ≠ mutation: an
untouched subscription still records its consumption row (the main row
names no modules, so it is always safe to write).
Sourcepub async fn record_provisioned(
&mut self,
modules: &BTreeSet<String>,
) -> Result<()>
pub async fn record_provisioned( &mut self, modules: &BTreeSet<String>, ) -> Result<()>
Record a fresh provision’s outcome: subscribe the provisioned modules. One transaction, under the caller’s advisory lock.
Provision never crosses. It seeds no cursor of its own: the baseline row provision already laid down (or none, on a baseline-free replay) IS the cursor seed — the derived cursor is the highest baseline version, so every re-anchor ≤ it is moot without any special step.
Auto Trait Implementations§
impl !RefUnwindSafe for ModuleRuntime
impl !UnwindSafe for ModuleRuntime
impl Freeze for ModuleRuntime
impl Send for ModuleRuntime
impl Sync for ModuleRuntime
impl Unpin for ModuleRuntime
impl UnsafeUnpin for ModuleRuntime
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> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more