Skip to main content

LimitsSpec

Struct LimitsSpec 

Source
pub struct LimitsSpec {
    pub memory: Option<u64>,
    pub fuel: Option<u64>,
    pub wall_clock: Option<Duration>,
    pub cpu: Option<u32>,
}
Expand description

Per-process limits. All fields optional — None = unbounded for that axis.

Fields§

§memory: Option<u64>

Max linear memory in bytes. Authored as a byte-size string ("64MiB", "1GiB", "512KB"). Round-trips back to the same canonical string on serialize.

§fuel: Option<u64>

Max wasm instructions per outermost call (wasmtime fuel). Plain integer; None = unbounded.

§wall_clock: Option<Duration>

Wall-clock cap per outermost call. Authored as a duration string ("30s", "500ms", "2m").

§cpu: Option<u32>

Soft CPU share. Authored as a Kubernetes-style millicore string ("500m" for half a core, "2" or "2000m" for two cores). Stored as millicores (u32).

Implementations§

Source§

impl LimitsSpec

Source

pub const fn is_empty(&self) -> bool

True when no axis is bounded.

Source

pub const fn memory(&self) -> Option<u64>

Substrate-canonical per-:limits :memory Lunatic-per-process wasm32-linear-memory byte-cap scalar accessor every consumer of the Servico’s wasmtime::StoreLimits::memory_size propagation keys off — returns the author-declared :limits :memory typed byte-cap verbatim as an Option<u64>, copied out of the typed slot’s own Option<u64> storage (Option<u64> is Copy, so the accessor returns by value; no borrow of &self past the call). None when the slot is absent (the “no memory cap declared — engine-default applies, today the pre-M2 unbounded- linear-memory shape” arm the module-level docstring names on LimitsSpec::memory itself — LimitsSpec::is_empty’s memory().is_none() arm reads this predicate too, so an authored-but-unset :limits (:memory ()) round-trips to a servico_m2_overlay emission structurally identical to one that omits the slot entirely).

The :limits :memory slot carries the “per-process wasm32 linear-memory byte-cap” Lunatic-shaped sandboxing contract (theory/INSPIRATIONS.md §III.1) — the typed slot’s Option<u64> accept-set (zero-floor rejected through LimitsError::MemoryZero, wasm32-page-floor rejected through LimitsError::MemoryBelowWasm32Page, upper-bounded by LIMITS_MEMORY_WASM32_MAX_BYTES, authored as a byte-size string that round-trips back to the canonical form through [ser_byte_size] / [de_byte_size]) maps onto the wasmtime Store::limiter-side memory_size projection the wasm-engine M2 wires and, via crate::render::servico_m2_overlay, onto the pleme-computeunit Helm-library-chart values sub-block’s limits.memory key that lands as the ComputeUnit CR’s spec.limits.memory field.

Prior to this lift the .memory field was accessed inline at four sites inside impl LimitsSpecLimitsSpec::is_empty’s self.memory.is_none() arm and three LimitsSpec::validate arms (the numeric zero-floor arm at line 397, the wasm32-page structural floor arm at line 427, and the wasm32 upper-cap arm at line 449) — four open-coded field-accesses that expressed no compile-time link back to the typed slot. A future extension of the :limits :memory axis to a richer author surface — a per-instance memory-declaration override the operator pins through a future ComputeUnit CR-side spec.limits.memory overlay, a split of the single u64 byte-cap into a {min, max} pair once wasm32’s (memory M N) two-arg form promotes past its current single-max typed bound, a wasm64 promotion once the wasm-engine grows past the wasm32 4 GiB structural ceiling — would have had to be threaded through every open-coded copy in lockstep or the emptiness predicate and the validate call would silently disagree on which cap a given LimitsSpec resolves to. Lifting the resolution to a typed method on the substrate primitive means every downstream consumer of the Servico’s per-:limits byte-cap surface reaches for exactly one typed dispatch — the resolver’s accept-set migrates as a unit on any future axis addition.

First Option<Copy-T>-return accessor on the M2 slot family (peer of the sibling per-:politicas crate::MeshPolicy::mtls_required c0110f1 Option<bool> accessor, per-:politicas crate::MeshPolicy::retries bdfb399 Option<u32> accessor, and per-:politicas crate::MeshPolicy::timeout 7073d0f Option<Duration> accessor on the M3 mesh-slot family — same “one typed dispatch on the substrate primitive, thin projections at each consumer” discipline extended onto the peer per-:limits typed-u64 optional-scalar axis; opens the “optional per-slot Copy-T scalar” projection pattern the sibling per-:limits :fuel (Option) / :wall-clock (Option) / :cpu (Option) future lifts fold on). Named memory() to match the storage field’s name; the accessor’s identity maps onto the canonical Lunatic-shaped theory/INSPIRATIONS.md §III.1 vocabulary the slot’s docstring already carries.

Source

pub const fn fuel(&self) -> Option<u64>

Substrate-canonical per-:limits :fuel wasmtime-per-call wasm-instruction budget scalar accessor every consumer of the Servico’s wasmtime::Store::set_fuel propagation keys off — returns the author-declared :limits :fuel typed wasm-instruction budget verbatim as an Option<u64>, copied out of the typed slot’s own Option<u64> storage (Option<u64> is Copy, so the accessor returns by value; no borrow of &self past the call). None when the slot is absent (the “no fuel budget declared — engine-default applies, today the pre-M2 unbounded-fuel-counter shape” arm the module-level docstring names on LimitsSpec::fuel itself — LimitsSpec::is_empty’s fuel().is_none() arm reads this predicate too, so an authored-but-unset :limits (:fuel ()) round-trips to a servico_m2_overlay emission structurally identical to one that omits the slot entirely).

The :limits :fuel slot carries the “per-call wasm-instruction budget” wasmtime-shaped sandboxing contract (theory/INSPIRATIONS.md §III.1 — Lunatic’s supervised wasm-Store-per-process fuel accounting, translated onto pleme-io’s typed :limits slot) — the typed slot’s Option<u64> accept-set (zero-floor rejected through LimitsError::FuelZero because wasmtime traps the first instruction at fuel=0, upper-bounded by LIMITS_FUEL_MAX (10¹² wasm instructions — the operationally-reachable per-call budget within the sibling LIMITS_WALL_CLOCK_MAX 1h ceiling)) maps onto the wasmtime Store::set_fuel call the M2.5 wasm-engine wires per outermost call and, via crate::render::servico_m2_overlay, onto the pleme-computeunit Helm-library-chart values sub-block’s limits.fuel key that lands as the ComputeUnit CR’s spec.limits.fuel field.

Prior to this lift the .fuel field was accessed inline at two sites inside impl LimitsSpecLimitsSpec::is_empty’s self.fuel.is_none() arm and LimitsSpec::validate’s if let Some(f) = self.fuel { … } zero-floor + upper-cap bracket arm — two open-coded field-accesses that expressed no compile-time link back to the typed slot. A future extension of the :limits :fuel axis to a richer author surface — a per-instance ComputeUnit CR-side spec.limits.fuel overlay the operator pins per-cluster, a wasm-instruction-count → wasmtime-fuel-unit rescale once the fuel-tracking backend switches from Cranelift’s implicit 1:1 count to a per-opcode-weighted budget, a split of the single per-outermost-call u64 budget into a {per_call, per_second} pair once the wasm-engine grows a sustained-throughput cap — would have had to be threaded through every open-coded copy in lockstep or the emptiness predicate and the validate call would silently disagree on which fuel budget a given LimitsSpec resolves to. Lifting the resolution to a typed method on the substrate primitive means every downstream consumer of the Servico’s per-:limits fuel-budget surface reaches for exactly one typed dispatch — the resolver’s accept-set migrates as a unit on any future axis addition.

Second Option<Copy-T>-return accessor on the M2 slot family (peer of the sibling per-:limits LimitsSpec::memory (620c067) Option<u64> accessor — same typed-u64 optional-scalar shape, extended to the peer per-:limits wasm-instruction-budget axis; sibling to crate::MeshPolicy::mtls_required (c0110f1) / crate::MeshPolicy::retries (bdfb399) / crate::MeshPolicy::timeout (7073d0f) on the closed M3 mesh-slot Option<Copy-T> accessor family). The pair (memory(), fuel()) jointly projects the two Option<u64> axes every M2 :limits consumer that fans on wasm-linear-memory-cap + wasm-fuel-budget keys off. Two of the four :limits axes now route through a typed dispatch on the substrate primitive; the two remaining (wall_clock: Option<Duration>, cpu: Option<u32>) fold on the same one-line accessor + is_empty-arm-route + validate-arm-route + three-test pattern. Named fuel() to match the storage field’s name; the accessor’s identity maps onto the canonical wasmtime-Store::set_fuel-shaped vocabulary the slot’s docstring already carries.

Source

pub const fn wall_clock(&self) -> Option<Duration>

Substrate-canonical per-:limits :wall-clock wasmtime-per-call wall-clock deadline scalar accessor every consumer of the Servico’s wasmtime::Store::epoch_deadline_* / wasi:clocks propagation keys off — returns the author-declared :limits :wall-clock typed Duration verbatim as an Option<Duration>, copied out of the typed slot’s own Option<Duration> storage (Duration is Copy, so Option<Duration> is Copy and the accessor returns by value; no borrow of &self past the call). None when the slot is absent (the “no wall-clock deadline declared — engine-default applies, today the pre-M2 unbounded-wall-clock shape” arm the module-level docstring names on LimitsSpec::wall_clock itself — LimitsSpec::is_empty’s wall_clock().is_none() arm reads this predicate too, so an authored-but-unset :limits (:wall-clock ()) round-trips to a servico_m2_overlay emission structurally identical to one that omits the slot entirely).

The :limits :wall-clock slot carries the “per-outermost-call wall-clock deadline” wasmtime-shaped sandboxing contract (theory/INSPIRATIONS.md §III.1 — Lunatic’s supervised wasm-Store-per-process epoch-deadline accounting, translated onto pleme-io’s typed :limits slot) — the typed slot’s Option<Duration> accept-set (zero-floor rejected through LimitsError::WallClockZero because a zero deadline traps the first instruction; integer-millisecond granularity enforced through LimitsError::WallClockNotCanonical because the duration codec’s canonical form emits "1500ms" not "1.5s" and the operator’s wall-clock scheduler quantizes at milliseconds; upper-bounded by LIMITS_WALL_CLOCK_MAX (1h — the coarsest per-call deadline any operationally-reachable Servico can honor without spanning multiple scheduler epochs)) maps onto the wasmtime Store::epoch_deadline_* call the M2.5 wasm-engine wires per outermost call and, via crate::render::servico_m2_overlay, onto the pleme-computeunit Helm-library-chart values sub-block’s limits.wallClock key that lands as the ComputeUnit CR’s spec.limits.wallClock field.

Prior to this lift the .wall_clock field was accessed inline at two sites inside impl LimitsSpecLimitsSpec::is_empty’s self.wall_clock.is_none() arm and LimitsSpec::validate’s if let Some(w) = self.wall_clock { … } zero-floor + canonical-form + upper-cap bracket arm — two open-coded field-accesses that expressed no compile-time link back to the typed slot. A future extension of the :limits :wall-clock axis to a richer author surface — a per-instance ComputeUnit CR-side spec.limits.wallClock overlay the operator pins per-cluster, a wall-clock-vs-monotonic-clock discriminator once the wasm-engine grows a :limits (:wall-clock (:kind monotonic …)) axis, a split of the single per-outermost-call Duration budget into a {deadline, warn_at} pair once the wasm-engine grows a soft-deadline warning surface — would have had to be threaded through every open-coded copy in lockstep or the emptiness predicate and the validate call would silently disagree on which deadline a given LimitsSpec resolves to. Lifting the resolution to a typed method on the substrate primitive means every downstream consumer of the Servico’s per-:limits wall-clock-deadline surface reaches for exactly one typed dispatch — the resolver’s accept-set migrates as a unit on any future axis addition.

Third Option<Copy-T>-return accessor on the M2 slot family (peer of the sibling per-:limits LimitsSpec::memory (620c067) Option<u64> accessor and per-:limits LimitsSpec::fuel (795dee7) Option<u64> accessor — same typed-optional-scalar shape extended to the peer per-:limits wall-clock-deadline axis; sibling to crate::MeshPolicy::timeout (7073d0f) on the closed M3 mesh-slot Option<Duration> accessor axis — same typed-Duration shape extended from the M3 per-call-timeout to the M2 per-outermost-call deadline). The triple (memory(), fuel(), wall_clock()) jointly projects three of the four Option<Copy-T> axes every M2 :limits consumer that fans on wasm-linear-memory-cap + wasm-fuel-budget + wall-clock-deadline keys off. Three of the four :limits axes now route through a typed dispatch on the substrate primitive; the one remaining (cpu: Option<u32>) folds on the same one-line accessor + is_empty-arm-route + validate-arm-route + three-test pattern in the next run, closing the M2 :limits slot family’s Option<Copy-T> accessor axis. Named wall_clock() to match the storage field’s name; the accessor’s identity maps onto the canonical wasmtime-Store::epoch_deadline_*-shaped vocabulary the slot’s docstring already carries.

Source

pub const fn cpu(&self) -> Option<u32>

Substrate-canonical per-:limits :cpu Kubernetes-millicore soft cgroup-share scalar accessor every consumer of the Servico’s pod-spec resources.requests.cpu propagation keys off — returns the author-declared :limits :cpu typed millicore magnitude verbatim as an Option<u32>, copied out of the typed slot’s own Option<u32> storage (Option<u32> is Copy, so the accessor returns by value; no borrow of &self past the call). None when the slot is absent (the “no cpu share declared — scheduler-default applies, today the pre-M2 unbounded-cpu-share shape” arm the module-level docstring names on LimitsSpec::cpu itself — LimitsSpec::is_empty’s cpu().is_none() arm reads this predicate too, so an authored-but-unset :limits (:cpu ()) round-trips to a servico_m2_overlay emission structurally identical to one that omits the slot entirely).

The :limits :cpu slot carries the “per-process soft cgroup-v2 CPU share” Kubernetes-scheduler-shaped sandboxing hint (theory/INSPIRATIONS.md §III.1 — Lunatic’s supervised wasm-Store-per-process host-runtime CPU accounting, translated onto pleme-io’s typed :limits slot as a scheduler-facing millicore request the pod’s kubelet propagates to the container’s cgroup) — the typed slot’s Option<u32> accept-set (zero-floor rejected through LimitsError::CpuZero because a zero cgroup share starves the process; upper-bounded by LIMITS_CPU_MILLICORES_MAX (128 cores — the largest commercially- common non-metal cloud Kubernetes node vCPU count on managed GKE / EKS / AKS general-purpose SKUs)) maps onto the K8s pod spec’s spec.containers[].resources.requests.cpu field the M2.5 wasm-engine host-runtime lands on the ComputeUnit CR-side pod template and, via crate::render::servico_m2_overlay, onto the pleme-computeunit Helm-library-chart values sub-block’s limits.cpu key that lands as the ComputeUnit CR’s spec.limits.cpu field.

Prior to this lift the .cpu field was accessed inline at two sites inside impl LimitsSpecLimitsSpec::is_empty’s self.cpu.is_none() arm and LimitsSpec::validate’s if let Some(m) = self.cpu { … } zero-floor + upper-cap bracket arm — two open-coded field-accesses that expressed no compile-time link back to the typed slot. A future extension of the :limits :cpu axis to a richer author surface — a per-instance ComputeUnit CR-side spec.limits.cpu overlay the operator pins per-cluster, a split of the single u32 millicore request into a {request, limit} pair once the pod spec’s resources.requests.cpu / resources.limits.cpu distinction promotes past its current single-request author surface, a millicore → cgroup-v2 cpu.weight rescale once the operator’s scheduler-facing translation lands past its current kubelet passthrough — would have had to be threaded through every open-coded copy in lockstep or the emptiness predicate and the validate call would silently disagree on which cgroup share a given LimitsSpec resolves to. Lifting the resolution to a typed method on the substrate primitive means every downstream consumer of the Servico’s per-:limits cpu-share surface reaches for exactly one typed dispatch — the resolver’s accept-set migrates as a unit on any future axis addition.

Fourth and final Option<Copy-T>-return accessor on the M2 slot family (peer of the sibling per-:limits LimitsSpec::memory (620c067) Option<u64> accessor, per-:limits LimitsSpec::fuel (795dee7) Option<u64> accessor, and per-:limits LimitsSpec::wall_clock (8cb717b) Option<Duration> accessor — same typed-optional-scalar shape extended to the peer per-:limits cgroup-cpu-share axis; sibling to crate::MeshPolicy::mtls_required (c0110f1) / crate::MeshPolicy::retries (bdfb399) / crate::MeshPolicy::timeout (7073d0f) on the closed M3 mesh-slot Option<Copy-T> accessor family). The four-tuple (memory(), fuel(), wall_clock(), cpu()) jointly projects every Option<Copy-T> axis on the M2 :limits slot every consumer that fans on wasm-linear-memory-cap + wasm-fuel-budget + wall-clock-deadline + cgroup-cpu-share keys off — closes the M2 :limits slot family’s Option<Copy-T> accessor axis (the last unlifted :limits field-access site on the M2 slot family; every axis now routes through a typed dispatch on the substrate primitive, with no open-coded field access anywhere on the impl). Named cpu() to match the storage field’s name; the accessor’s identity maps onto the canonical Kubernetes-resources.requests.cpu- shaped vocabulary the slot’s docstring already carries.

Source

pub fn validate(&self) -> Result<(), LimitsError>

Reject operationally-meaningless zero values on every declared axis. Each axis remains optional — omitting a field expresses “no bound on this axis”; the bug being closed is carrying a zero value, which the wasm-engine consumes as “trap the first instruction” / “instantiation refused” / “immediate timeout” rather than the author’s intended “an unspecified bound”.

Mirrors the discipline applied to :politicas axes in AplicacaoSpec::validate and to SupervisorSpec::max_restarts — every typed value carried by a slot is either absent or meaningfully non-zero.

Trait Implementations§

Source§

impl Clone for LimitsSpec

Source§

fn clone(&self) -> LimitsSpec

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for LimitsSpec

Source§

impl Debug for LimitsSpec

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for LimitsSpec

Source§

fn default() -> LimitsSpec

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for LimitsSpec

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Eq for LimitsSpec

Source§

impl PartialEq for LimitsSpec

Source§

fn eq(&self, other: &LimitsSpec) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl Serialize for LimitsSpec

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for LimitsSpec

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.