Skip to main content

DemandGateway

Trait DemandGateway 

Source
pub trait DemandGateway:
    Debug
    + Send
    + Sync {
    // Required methods
    fn queued_demand<'life0, 'life1, 'life2, 'async_trait>(
        &'life0 self,
        scope: &'life1 ActivityScope,
        cancel: &'life2 CancelToken,
    ) -> Pin<Box<dyn Future<Output = Result<QueuedDemand, InventoryError>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait;
    fn now(&self) -> Timestamp;

    // Provided method
    fn run_workflow<'life0, 'life1, 'life2, 'async_trait>(
        &'life0 self,
        _repository: &'life1 OwnerRepo,
        _run_id: u64,
        _cancel: &'life2 CancelToken,
    ) -> Pin<Box<dyn Future<Output = Result<Option<String>, InventoryError>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait { ... }
}
Expand description

The demand read model.

A trait for crate::rest::InventoryGateway’s reason: e1 and g2 are tested against runner_manager_testkit::github::FakeGithub with no network and no wiremock in their dependency graphs. RestDemand is the one implementation that talks to GitHub.

§Why the scope type is c3’s ActivityScope and not a new one

The name says “activity” and this is demand, so the reuse is worth justifying rather than leaving to look like an oversight.

ActivityScope is not a description of the in-progress count; it is the answer to “which repositories does one per-repository workflow-runs aggregate cover”, and demand asks that question with exactly the same answer. Both hit /repos/{o}/{r}/actions/runs, both have no organization-wide form, and both take the repository list from the same caller-held set — c3 documents that the list “has to come from the caller, [because] f1 and e1 already hold it, from crate::AuthenticatedClient::discover_installations, and re-discovering it on every refresh would cost more requests than the count itself”.

A DemandScope beside it would be that type with a different name, and the cost of the duplicate is concrete rather than aesthetic: e1 polls both read models in one refresh, and two scope types are two chances for them to disagree about which repositories are in scope — which would make the demand total and the activity total describe different sets while being rendered side by side. What is not shared is the cost function: ActivityScope::requests_per_refresh prices the activity count, and demand_requests_per_poll prices this one, because those really are two different numbers.

Required Methods§

Source

fn queued_demand<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, scope: &'life1 ActivityScope, cancel: &'life2 CancelToken, ) -> Pin<Box<dyn Future<Output = Result<QueuedDemand, InventoryError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Queued workflow runs across scope.

§Errors

Every variant of InventoryError.

Source

fn now(&self) -> Timestamp

The instant a reading is stamped with.

Provided Methods§

Source

fn run_workflow<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, _repository: &'life1 OwnerRepo, _run_id: u64, _cancel: &'life2 CancelToken, ) -> Pin<Box<dyn Future<Output = Result<Option<String>, InventoryError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

The workflow file (.github/workflows/ci.yml) of one run. Nothing else on a run names its workflow stably: its name and a job’s workflow_name can be a title that changes at every dispatch.

§Errors

Every variant of InventoryError.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementations on Foreign Types§

Source§

impl<T: DemandGateway + ?Sized> DemandGateway for Arc<T>

One gateway shared by every target loop on a host. Sharing is what lets RestDemand read a repository once for every target that covers it, and silence every loop at once inside a rate-limit quiet period.

Source§

fn queued_demand<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, scope: &'life1 ActivityScope, cancel: &'life2 CancelToken, ) -> Pin<Box<dyn Future<Output = Result<QueuedDemand, InventoryError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Source§

fn run_workflow<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, repository: &'life1 OwnerRepo, run_id: u64, cancel: &'life2 CancelToken, ) -> Pin<Box<dyn Future<Output = Result<Option<String>, InventoryError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Source§

fn now(&self) -> Timestamp

Implementors§