Skip to main content

RefreshState

Enum RefreshState 

Source
pub enum RefreshState {
    Ready(Box<InventorySnapshot>),
    RateLimited(RateLimited),
    Unauthorized,
    LockedOut {
        retry_after: Duration,
    },
    Forbidden {
        message: Option<String>,
    },
    Offline,
    Failed {
        status: Option<u16>,
        message: String,
    },
    Cancelled,
}
Expand description

One refresh’s outcome, as a value that can be stored, compared and rendered.

InventoryError cannot be any of those things — it owns a reqwest::Error and a serde_json::Error, neither of which is Clone — and the TUI needs a state it can hold in a snapshot and diff against the previous frame. So the error is summarised into this enum exactly once, at the gateway boundary, rather than each screen inventing its own summary.

g2’s Definition of Done names “loading, empty, unauthorized, rate-limited, and offline states”; four of those are variants here, and “loading” and “empty” are the caller’s (no state yet, and a Ready snapshot with nothing in it).

Variants§

§

Ready(Box<InventorySnapshot>)

The refresh completed. Note that an empty snapshot is still Ready: “this target has no runners” is an answer, and rendering it as a failure is how an idle host looks broken.

§

RateLimited(RateLimited)

GitHub is rate limiting this credential.

§

Unauthorized

The stored credential was rejected. Terminal until auth login.

§

LockedOut

GitHub’s temporary authentication lockout. The credential is fine.

Fields

§retry_after: Duration
§

Forbidden

A permissions answer. Re-authenticating will not change it.

Fields

§message: Option<String>
§

Offline

GitHub could not be reached.

§

Failed

Anything else GitHub answered.

Fields

§status: Option<u16>
§message: String
§

Cancelled

The caller withdrew the refresh.

Implementations§

Source§

impl RefreshState

Source

pub fn from_result(result: Result<InventorySnapshot, InventoryError>) -> Self

Summarise a completed refresh.

Source

pub fn from_error(error: &InventoryError) -> Self

Summarise a failure without consuming it.

Source

pub fn is_ready(&self) -> bool

Source

pub fn snapshot(&self) -> Option<&InventorySnapshot>

Source

pub fn retry_delay(&self, now: Timestamp) -> Option<Duration>

How long to wait before trying again, or None when waiting is not what this state needs.

04-subsystem-contracts.md: “Rate limiting increases the refresh delay and is displayed, never hidden.” This is the increase. It is deliberately None for RefreshState::Unauthorized and RefreshState::Forbidden, which no amount of waiting fixes.

§An absolute floor, not an addend

The scheduling rule is next_attempt_at = now + retry_delay. It is not the ordinary refresh interval plus this — adding the two would double the wait for no benefit, because the gateway enforces the same window itself: a request issued inside it is answered InventoryError::RateLimited without a socket being opened (RestInventory::rate_limit_backoff).

Trying too early is therefore cheap and self-correcting rather than harmful. A suppressed request returns before RateLimited::detect is ever reached, so an early attempt cannot ratchet the window outward by this gateway’s own silence, and repeated attempts converge on the instant GitHub named. What an addend buys is one wasted interval per limit; what it costs is a dashboard that stays dark longer than GitHub asked for.

Note also that a RefreshState::RateLimited read back from RestInventory::rate_limit_state carries the time remaining, not the delay GitHub originally asked for — so this value shrinks as the window elapses, which is another reason it reads as a deadline rather than as an increment.

Trait Implementations§

Source§

impl Clone for RefreshState

Source§

fn clone(&self) -> RefreshState

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 RefreshState

Source§

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

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

impl Display for RefreshState

Source§

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

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

impl Eq for RefreshState

Source§

impl PartialEq for RefreshState

Source§

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

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

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

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for RefreshState

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<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> 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> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
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> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. 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