Skip to main content

AccountStateMap

Struct AccountStateMap 

Source
pub struct AccountStateMap {
    pub ordered_keys: Vec<AccountKey>,
    pub by_key: HashMap<AccountKey, AccountState>,
}

Fields§

§ordered_keys: Vec<AccountKey>§by_key: HashMap<AccountKey, AccountState>

Implementations§

Source§

impl AccountStateMap

Source

pub fn empty_for_test() -> Self

Empty map for the testing feature’s Workspace::testing_stub. Production code paths reach this map only through the gateway’s selection walk, which a test fixture should never exercise.

Source

pub fn new(accounts: &[LoadedAccount]) -> Self

Source

pub fn seed_from_cache(&mut self, cached: &BTreeMap<String, UsageSnapshot>)

Seed the in-memory map from a previously-persisted cache. Each known account that appears in cached gets its usage populated; unknown cache entries (account removed from forge.toml) are ignored. Does NOT clear last_error or next_probe_at - the cache is purely seed data; the live poller still drives backoff. Used by Workspace::new so usage reads have data on cold boot.

Source

pub fn snapshots_for_cache(&self) -> BTreeMap<String, UsageSnapshot>

Snapshot the per-account usage for writing to the on-disk cache. Accounts with no live snapshot are omitted so the cache file doesn’t grow placeholders.

Source

pub fn env(&self, key: &AccountKey) -> Option<&HashMap<String, String>>

The account’s env map: global [env] extended by its own [accounts.env]. Consumed by the spawn path (stamped onto the child) and the usage poller / loader (base url, bearer, setup token). None for unknown keys.

Source

pub fn provider(&self, key: &AccountKey) -> Option<Provider>

Declared forge_primitives::account::Provider for key, the input the probe plan and the preflight repair copy both branch on. None for unknown keys.

Source

pub fn auth(&self, key: &AccountKey) -> Option<AccountAuth>

How the account proves who it is, which is the only thing that changes what an auth-repair hint tells the user to do. Base-url wins: such an account authenticates with the flat token beside its base_url. Every other account’s credential is its setup token, so both its token-mode and its token-less shapes repair the same way. None for unknown keys.

Source

pub fn set_usage(&mut self, key: &AccountKey, snapshot: UsageSnapshot)

Replace the cached usage snapshot for key and clear any stale last_error. Resets the consecutive-failure counter and clears the next-probe gate so this account returns to the default cadence. Also transitions loading to Ready - a successful probe is the terminal-success state for the boot-time loading task. Silent no-op when key isn’t registered (defensive - invariant says every poller key was inserted in new()).

Source

pub fn set_loading(&mut self, key: &AccountKey, loading: LoadingState)

Drive a LoadingState transition for key, used by the boot-time loading task. Setting Bailed clears the cached usage so no stale bar is drawn (replaces the PR #238 3-strike counter; bailed accounts have no live snapshot by construction).

Source

pub fn set_limit_reading(&mut self, key: &AccountKey, snapshot: UsageSnapshot)

Keep the windows a failed probe still carried. It never touches loading or last_error: a rate-limited probe does not heal the account, and nothing selection or a cooldown reads may move.

Source

pub fn latest_reading(&self, key: &AccountKey) -> Option<&UsageSnapshot>

The newest reading the account gave, for a view’s bars: a rate-limited response’s windows when one landed after the last successful probe, else that probe’s snapshot. Absent while both are.

Source

pub fn disarm_override(&mut self, key: &AccountKey)

Disarm the scheduler hook for key after firing an override probe attempt. One-shot semantics: the hook fires once per arming (i.e. once per fresh snapshot). Subsequent stale-reset state must wait for the next successful probe (which re-arms via set_usage) or until the existing backoff timer (next_probe_at) elapses.

Source

pub fn set_last_error( &mut self, key: &AccountKey, status: UsageFetchStatus, retry_after: Option<Duration>, )

Record the latest poll-attempt failure for key and schedule the next probe.

retry_after (when Some) is the server-provided hold-down duration - typically Anthropic’s Retry-After header on 429. We honour it verbatim because the server knows when its per-account bucket will reset; guessing with our own backoff either over- or under-shoots and keeps the limit hot. When None (network failures, unknown HTTP status, server didn’t send Retry-After), fall back to a local exponential schedule.

The cached usage snapshot is preserved so the panel keeps showing the last known-good bars (a fresh 429 doesn’t blank them out).

Source

pub fn should_probe_now(&self, key: &AccountKey) -> bool

true when the poller may probe key now. false when the account is in an active backoff window from a recent failure. Cold-cache accounts (no last_error) always return true.

Source

pub fn all_loaded(&self) -> bool

true when every account in the map has reached a terminal LoadingState (Ready or Bailed). The boot wave and the cron spawn path gate on this. Empty maps return true (vacuous; no accounts means no work to wait on - relevant in the testing-stub path). A retired account counts as settled: the edit removed it, so nothing will ever load it.

Source

pub fn is_saturated(&self, key: &AccountKey) -> bool

True when key’s loaded usage snapshot shows it at-or-beyond the plan cap - the same saturation signal unusable_reason classifies on. A Ready-but-saturated account logs in fine but trips the rate limit on its next request, so the selection walk prefers other accounts when one is available.

Source

pub fn unusable_reason(&self, key: &AccountKey) -> Option<Unusable>

Why key is out of the usable tier, None when pickable: what the walk reads to demote an account. Bailed outranks the probe classes: it is the loading task’s terminal verdict, and a bailed account has no cached windows to saturate with. A snapshot whose source is not the account backend’s is treated as absent, the same refusal budget() applies - the redb cache survives a provider edit and is re-seeded at boot, and without this a stale windowed snapshot would classify a spend row as saturated.

Source

pub fn loading_state(&self, key: &AccountKey) -> LoadingState

Snapshot the current LoadingState for key. Returns LoadingState::Loading by default for unknown keys (defensive - a caller may hold a key that hasn’t been registered in the map).

Source

pub fn scheduler_should_probe(&self, key: &AccountKey) -> bool

Combined scheduler signal: probe key on the current cycle if the normal backoff gate (should_probe_now) is open OR the one-shot reset-clear override hook (has_just_cleared_cap_window) is firing. Both sides of the OR carry through to the workspace poller, which calls this method to decide which accounts to probe each tick. Centralising the OR here keeps a future refactor from accidentally dropping one half of the signal - the unit test pins the truth table that the scheduler relies on, regardless of whether the call site spells out both predicates inline.

Source

pub fn has_just_cleared_cap_window(&self, key: &AccountKey) -> bool

true when at least one cached window shows the account just transitioned out of its cap (utilization at-or-above 100%, resets_at now in the past) AND the override hook is armed. The scheduler ORs this with should_probe_now so a fresh probe lands on the next poll cycle after the reset moment, instead of waiting through the remainder of an active backoff window. Without the hook, an account 429’d with a multi-hour Retry-After keeps painting the stale “100%” bar for hours past the actual reset because the next probe is gated until the backoff timer elapses.

The override_armed gate enforces one-shot semantics: each successful probe arms the hook exactly once, and the scheduler disarms it after firing. A persistently failing probe series won’t keep tripping the override every cycle.

Source

pub fn usage(&self, key: &AccountKey) -> Option<&UsageSnapshot>

Look up the cached usage snapshot for key. None when the poller hasn’t yet succeeded for this account.

Source

pub fn usage_error(&self, key: &AccountKey) -> Option<UsageFetchStatus>

Look up the latest poll-attempt failure for key. None when the most recent attempt succeeded (or no attempt has been made yet).

Source

pub fn clear_last_error(&mut self, key: &AccountKey)

Drop the recorded failure for key, so a bail that never recorded its own cause falls back to the unrecorded default rather than wearing a stale class.

Trait Implementations§

Source§

impl Debug for AccountStateMap

Hand-written so a field added later cannot print through it until it is deliberately listed; the states it holds redact themselves.

Source§

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

Formats the value using the given formatter. Read more

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

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

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

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

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.

§

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

§

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
§

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

impl<T> WithSubscriber for T

§

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
§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

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