Skip to main content

RunnerAttempt

Struct RunnerAttempt 

Source
pub struct RunnerAttempt {
    pub id: AttemptId,
    pub policy_id: PolicyId,
    pub created_at: Timestamp,
    /* private fields */
}
Expand description

One ephemeral runner, from directory allocation to cleanup.

The fields 04-subsystem-contracts.md names are all here. Two are not in that list and are added deliberately:

  • outcome, because b1’s Scope requires the attempt to “carry an outcome distinguishing ‘ran a job’ from ‘exited idle without work’”.
  • last_state_change_at, because recovery decisions measure elapsed time in the current state — an idle timeout runs from entering idle, not from created_at — and b1’s Definition of Done requires those decisions to be testable against a fake clock.

b2 persists both.

Fields§

§id: AttemptId§policy_id: PolicyId§created_at: Timestamp

Implementations§

Source§

impl RunnerAttempt

Source

pub fn to_persisted(&self) -> PersistedAttempt

Every stored column of this attempt, for b2 to write back.

The exact inverse of Self::from_persisted, so a round trip through the journal is expressible without reaching for a field accessor per column and without this type exposing its private fields for writing.

Source

pub fn allocate( id: AttemptId, policy_id: PolicyId, runtime_path: impl Into<PathBuf>, now: Timestamp, ) -> Self

The first step of e3’s per-attempt flow: a runtime directory is allocated and journalled before anything remote happens, so a crash leaves a recoverable trace rather than an invisible one. D3 keeps this the disposable path: an attempt allocated through it is AttemptWorkspace::Ephemeral, so every existing caller and test goes on producing the behaviour it produced before persistent slots existed. Self::allocate_in is the one that leases a slot.

Source

pub fn allocate_in( id: AttemptId, policy_id: PolicyId, runtime_path: impl Into<PathBuf>, workspace: AttemptWorkspace, now: Timestamp, ) -> Self

The same first step, recording which workspace the directory came from.

c2 calls this with AttemptWorkspace::PersistentSlot while holding the host allocation lock, so the slot lease is journalled “before package or GitHub effects” and a crash between the two leaves a recoverable trace rather than an orphaned slot.

Source

pub fn from_persisted(fields: PersistedAttempt) -> Result<Self, AttemptError>

Rebuild a journalled attempt.

§Errors

Any state/outcome/timestamp combination that this crate’s own transitions cannot produce, so a hand-edited journal cannot inject a failed attempt that claims to have run a job, or a finished one that never reached a terminal state.

Source

pub const fn state(&self) -> AttemptState

Source

pub const fn outcome(&self) -> Option<&AttemptOutcome>

Source

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

Source

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

Source

pub fn runtime_path(&self) -> &Path

Source

pub const fn workspace(&self) -> AttemptWorkspace

The immutable allocation fact: disposable, or the persistent slot leased.

There is no setter. Cleanup and recovery dispatch on this (02-target-architecture.md, “Cleanup and recovery”), so a value that could be changed after allocation would let the algorithm chosen for a directory disagree with the one it was created under.

Source

pub const fn holds_slot_lease(&self) -> bool

Whether this attempt holds a persistent slot lease.

Every uncleaned persistent attempt is a lease, including a terminal one whose cleanup failed — which is why this asks about the workspace and not about the state.

Source

pub const fn terminal_at(&self) -> Option<Timestamp>

Source

pub const fn last_state_change_at(&self) -> Timestamp

When the attempt entered its current state. Recovery timeouts run from here.

Source

pub const fn is_terminal(&self) -> bool

Source

pub const fn counts_against_capacity(&self) -> bool

Whether this attempt still holds one of the host’s capacity slots.

Source

pub fn jit_received(&mut self, now: Timestamp) -> Result<(), AttemptError>

allocated -> jit_received.

§Errors

AttemptError::IllegalTransition from any other state.

Source

pub fn started( &mut self, process_id: u32, now: Timestamp, ) -> Result<(), AttemptError>

jit_received -> starting, recording the child process identity.

§Errors

AttemptError::IllegalTransition from any other state.

Source

pub fn registered_idle( &mut self, github_runner_id: u64, now: Timestamp, ) -> Result<(), AttemptError>

starting -> idle: the runner registered and is awaiting its one assignment.

§Errors

AttemptError::IllegalTransition from any other state.

Source

pub fn assigned_job( &mut self, github_runner_id: u64, now: Timestamp, ) -> Result<(), AttemptError>

starting | idle -> busy: the runner was assigned its one job.

Both sources are real. A runner may be observed taking a job directly out of starting, or it may be seen idle first and pick the job up on a later pass — e3’s Scope step 4 walks the second sequence explicitly.

§Errors

AttemptError::IllegalTransition from any other state.

Source

pub fn conclude( &mut self, outcome: AttemptOutcome, now: Timestamp, ) -> Result<(), AttemptError>

Record the terminal outcome, moving to the state it implies.

§Errors

AttemptError::OutcomeUnreachable when the outcome does not belong to the current state — CompletedJob from anything but busy, or ExitedIdleWithoutWork from anything but idle — and AttemptError::IllegalTransition otherwise.

Source

pub fn clean(&mut self, now: Timestamp) -> Result<(), AttemptError>

finished | failed | orphaned -> cleaned.

§Errors

AttemptError::BusyCannotBeCleaned for a busy attempt — the scale-down case 04-subsystem-contracts.md forbids — and AttemptError::IllegalTransition for any other non-terminal state or for an already-cleaned attempt.

Trait Implementations§

Source§

impl Clone for RunnerAttempt

Source§

fn clone(&self) -> RunnerAttempt

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 Debug for RunnerAttempt

Source§

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

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

impl<'de> Deserialize<'de> for RunnerAttempt

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 RunnerAttempt

Source§

impl PartialEq for RunnerAttempt

Source§

fn eq(&self, other: &RunnerAttempt) -> 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 RunnerAttempt

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 RunnerAttempt

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<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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 = !

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

fn try_from(value: U) -> Result<T, !>

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.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more