Skip to main content

ActivityCount

Struct ActivityCount 

Source
pub struct ActivityCount { /* private fields */ }
Expand description

In-progress workflow runs, per repository and in total.

Not the busy-runner count. A workflow run is work GitHub has accepted and started; a busy runner is a machine executing a job. One run can occupy several runners, a run can be in progress with none of its jobs assigned yet, and a busy runner may be executing a job for a workflow this product does not poll at all. 04-subsystem-contracts.md and g2 both require them rendered as distinct aggregates, and they are distinct types here so that they cannot be added together by accident.

§A count can be short in two different ways, and both have to say so

A repository can fail to answer at all (ActivityCount::unavailable), and a repository can answer with a number that is only a floor (ActivityCount::truncated) — the fallback walk stopped at MAX_ACTIVITY_FALLBACK_PAGES, or GitHub’s own total was wider than the u32 this product renders. ActivityCount::is_complete is false for either, because 04-subsystem-contracts.md forbids exactly this shape of mistake on the other read model — “must never treat a first page as a complete inventory” — and a count truncated at page four is the same defect wearing a different endpoint.

Implementations§

Source§

impl ActivityCount

Source

pub fn new(per_repository: BTreeMap<OwnerRepo, u32>) -> Self

Source

pub fn of(repository: OwnerRepo, count: u32) -> Self

One repository’s count, for the common single-repository case.

Source

pub fn with_truncated(self, repository: OwnerRepo) -> Self

Mark repository’s count a floor rather than a total.

The programmable counterpart to what the fallback walk does when it stops at MAX_ACTIVITY_FALLBACK_PAGES, and it exists so that the incomplete case is reachable from outside this module at all. Self::new and Self::of were the only public constructors; both yield an empty truncated and an empty unavailable, and the fields are private — so Self::is_complete could only ever be true for a caller holding a hand-built count, and every downstream consumer that renders the false path had no way to write a test for it.

Source

pub fn with_unavailable( self, repository: OwnerRepo, reason: impl Into<String>, ) -> Self

Record a repository the count could not read, and why.

The counterpart to Self::with_truncated for the other cause of an incomplete count — see Self::is_complete for why the two are not interchangeable. Deliberately does not insert a zero into Self::per_repository: a repository that could not be counted is unknown, not idle, and flattening it to zero is the exact defect UnavailableRepository exists to prevent.

Source

pub fn total(&self) -> u32

In-progress workflow runs across every repository in scope.

A floor rather than a total when Self::truncated is non-empty, and short by an unknown amount when Self::unavailable is. Both make Self::is_complete false, which is the one question a caller rendering this number has to ask.

Source

pub fn per_repository(&self) -> &BTreeMap<OwnerRepo, u32>

Source

pub fn for_repository(&self, repository: &OwnerRepo) -> Option<u32>

This repository’s count, or None when it was not in scope.

Source

pub fn unavailable(&self) -> &[UnavailableRepository]

Source

pub fn truncated(&self) -> &BTreeSet<OwnerRepo>

Repositories whose count is a floor, not a total.

The counterpart to RunnerInventory::truncated, and here for the same reason: a number clipped by a page ceiling that does not say it was clipped is indistinguishable from a real one, and g2 renders this number with no other way to find out.

Source

pub fn is_truncated(&self, repository: &OwnerRepo) -> bool

Whether this repository’s count is a floor rather than a total.

Source

pub fn is_complete(&self) -> bool

true when every repository in scope answered and every answer was exact.

Deliberately one question rather than two. A caller that has to remember to ask about truncation separately is a caller that will forget, which is the same argument is_repository_local_failure makes about stepping over the only repository in scope.

§false has two causes, and they have opposite remedies

One question is right for rendering the number. It is not enough for acting on it, because the two ways a count can be incomplete point in opposite directions:

  • Self::truncated — the count is a lower bound. The repository answered and there is at least this much work in progress, so scaling up from it is sound; the real figure is only ever larger.
  • Self::unavailable — the count is unknown. Nothing was learned about that repository, and a missing count is not a zero. Scaling on it is guessing.

So a caller that reads false as a uniform “do nothing” stalls scale-up on a repository that is demonstrably busy — the truncated case is evidence of load, not absence of it. Ask this question to decide whether to caveat the number; ask Self::truncated versus Self::unavailable to decide what to do about it.

Trait Implementations§

Source§

impl Clone for ActivityCount

Source§

fn clone(&self) -> ActivityCount

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 ActivityCount

Source§

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

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

impl Default for ActivityCount

Source§

fn default() -> ActivityCount

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

impl Eq for ActivityCount

Source§

impl PartialEq for ActivityCount

Source§

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

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, 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