Skip to main content

onetaskgraph_plugin_api/
metering.rs

1//! What a source says its own requests to its backend have cost.
2
3use schemars::JsonSchema;
4use serde::{Deserialize, Serialize};
5
6/// Everything one source has sent to its backend since it was built, and what that spent
7/// against each budget the backend meters it by.
8///
9/// **A running total, never a figure per call.** What one piece of work cost is the
10/// difference between a reading taken before it and one taken after, which is how the
11/// engine reports what a copy spent; a source that reset its figures between readings
12/// would make that difference meaningless.
13///
14/// **Source-owned, in an open vocabulary.** Only the source knows what it sent and how its
15/// backend meters it, so the budget and unit names are the source's own. The engine adds
16/// figures up by name and interprets none of them.
17#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
18pub struct Metering {
19    /// How many requests this source has sent to its backend.
20    pub requests: u64,
21    /// What those requests spent, one entry per budget.
22    #[serde(default)]
23    pub budgets: Vec<Metered>,
24}
25
26/// What one source's requests have spent against one budget, split by where each figure
27/// came from.
28///
29/// Two amounts rather than one beside a flag: a figure the backend reported or a request
30/// counted is a measurement, while a figure the source modelled is a lower bound on what the
31/// backend charged. A caller adding readings up has to keep the two apart to say which a
32/// total is.
33#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
34pub struct Metered {
35    /// The budget, as the backend names it — `graphql`, `rest`.
36    // llmlint: ignore[invalid_states_unrepresentable] An open vocabulary the engine interprets none of, and the contract this lands states it as a plain string (`budget`, `unit`: strings), restated by a consumer repository; a newtype here would move the api crate every plugin re-tests against and the plugin protocol's wire shape for no value it could refuse but the empty name, which the engine refuses where a reading enters it (`difference` in onetaskgraph-core's copy.rs), reporting that source as not metering.
37    pub budget: String,
38    /// What the budget is metered in — `points`, `requests`.
39    // llmlint: ignore[invalid_states_unrepresentable] As `budget` above: open vocabulary, a plain string by the stated contract, and the empty name refused where the engine reads it.
40    pub unit: String,
41    /// How much was spent against it that the backend reported, or that is a count of
42    /// requests against a budget metered in requests.
43    #[serde(default)]
44    pub measured: u64,
45    /// How much was spent against it that this source modelled rather than measured, which
46    /// is a lower bound on what the backend charged for it.
47    #[serde(default)]
48    pub modelled: u64,
49}