pub struct HttpStore { /* private fields */ }Expand description
A tollgate-server client implementing LeaseAllocator,
SnapshotSource, UsageSink and KeySource over HTTP(S).
Every call carries the configured bearer credential, if any, and runs
under one request deadline that also covers obtaining that credential.
Server problem codes map back to the domain errors a direct backend
returns. Snapshot pushes are not supported, so the snapshot manager relies
on periodic refresh. Shared as an Arc by every background component;
reconfigure rotates credentials and TLS material in
place.
Implementations§
Source§impl HttpStore
impl HttpStore
Sourcepub fn new(base_url: impl Into<String>) -> Result<Arc<Self>, StoreError>
pub fn new(base_url: impl Into<String>) -> Result<Arc<Self>, StoreError>
Connect with default deadlines. Unauthenticated calls are refused by
tollgate-server; use with_config to supply credentials or mTLS.
Sourcepub fn with_timeouts(
base_url: impl Into<String>,
connect_timeout: Duration,
request_timeout: Duration,
) -> Result<Arc<Self>, StoreError>
pub fn with_timeouts( base_url: impl Into<String>, connect_timeout: Duration, request_timeout: Duration, ) -> Result<Arc<Self>, StoreError>
Connect with the given deadlines and otherwise default settings, so
no credentials: tollgate-server refuses unauthenticated calls. See
HttpStoreConfig for what each deadline bounds.
§Errors
StoreError for an unusable URL or deadline, as
with_config.
Sourcepub fn with_config(
base_url: impl Into<String>,
config: HttpStoreConfig,
) -> Result<Arc<Self>, StoreError>
pub fn with_config( base_url: impl Into<String>, config: HttpStoreConfig, ) -> Result<Arc<Self>, StoreError>
Connect to base_url with config’s deadlines, TLS material and
credential provider. No request is made here.
§Errors
StoreError when the URL is not HTTP(S), carries userinfo, a query
or a fragment, or uses plaintext http to anything but a loopback
address or with TLS material configured; when a deadline is zero or
unrepresentable; or when the CA or identity PEM is invalid.
Sourcepub fn reconfigure(&self, config: HttpStoreConfig) -> Result<(), StoreError>
pub fn reconfigure(&self, config: HttpStoreConfig) -> Result<(), StoreError>
Rotate TLS roots, the client certificate and/or credential provider as one generation. In-flight calls retain their original generation; future calls use the new one through the same Arc held by background managers.
Trait Implementations§
Source§impl KeySource for HttpStore
impl KeySource for HttpStore
Source§fn active_keys_page<'life0, 'async_trait>(
&'life0 self,
_now: Timestamp,
after: Option<KeyId>,
limit: NonZeroUsize,
) -> Pin<Box<dyn Future<Output = Result<KeyPage, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn active_keys_page<'life0, 'async_trait>(
&'life0 self,
_now: Timestamp,
after: Option<KeyId>,
limit: NonZeroUsize,
) -> Pin<Box<dyn Future<Output = Result<KeyPage, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
now; HTTP servers choose their own clock and return it as as_of.
Reads must be coherent with the returned revision, including for an
empty result. Never return a partial successful page after a failure.Source§impl LeaseAllocator for HttpStore
impl LeaseAllocator for HttpStore
Source§fn acquire<'life0, 'async_trait>(
&'life0 self,
account: AccountId,
requested: CostUnits,
ttl: SignedDuration,
_now: Timestamp,
) -> Pin<Box<dyn Future<Output = Result<Allocation, AllocateError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn acquire<'life0, 'async_trait>(
&'life0 self,
account: AccountId,
requested: CostUnits,
ttl: SignedDuration,
_now: Timestamp,
) -> Pin<Box<dyn Future<Output = Result<Allocation, AllocateError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
GrantPolicy and may be smaller than requested;
the fencing token comes from a strictly increasing per-account
sequence. It remains a capability for this lease only; allocating a
newer token does not invalidate another active lease.Source§fn release<'life0, 'async_trait>(
&'life0 self,
lease_id: LeaseId,
fencing_token: FencingToken,
unspent: CostUnits,
_now: Timestamp,
) -> Pin<Box<dyn Future<Output = Result<(), AllocateError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn release<'life0, 'async_trait>(
&'life0 self,
lease_id: LeaseId,
fencing_token: FencingToken,
unspent: CostUnits,
_now: Timestamp,
) -> Pin<Box<dyn Future<Output = Result<(), AllocateError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
(lease_id, fencing_token) pair,
credit unspent back, and close the lease. Callers should flush usage
first when possible; events arriving after release are accepted only
when they fit its provisional settlement loss.Source§fn consolidate<'life0, 'async_trait>(
&'life0 self,
lease_id: LeaseId,
fencing_token: FencingToken,
unspent: CostUnits,
requested: CostUnits,
needed: CostUnits,
ttl: SignedDuration,
_now: Timestamp,
) -> Pin<Box<dyn Future<Output = Result<Allocation, AllocateError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn consolidate<'life0, 'async_trait>(
&'life0 self,
lease_id: LeaseId,
fencing_token: FencingToken,
unspent: CostUnits,
requested: CostUnits,
needed: CostUnits,
ttl: SignedDuration,
_now: Timestamp,
) -> Pin<Box<dyn Future<Output = Result<Allocation, AllocateError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn reclaim_expired_batch<'life0, 'async_trait>(
&'life0 self,
_now: Timestamp,
_limit: NonZeroUsize,
) -> Pin<Box<dyn Future<Output = Result<ReclaimBatch, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn reclaim_expired_batch<'life0, 'async_trait>(
&'life0 self,
_now: Timestamp,
_limit: NonZeroUsize,
) -> Pin<Box<dyn Future<Output = Result<ReclaimBatch, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
limit active leases whose TTL (plus the policy’s
reclaim grace) has lapsed and whose holder never released them. Read moreSource§fn reclaim_expired<'life0, 'async_trait>(
&'life0 self,
now: Timestamp,
) -> Pin<Box<dyn Future<Output = Result<Vec<ReclaimedLease>, StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
Self: 'async_trait,
fn reclaim_expired<'life0, 'async_trait>(
&'life0 self,
now: Timestamp,
) -> Pin<Box<dyn Future<Output = Result<Vec<ReclaimedLease>, StoreError>> + Send + 'async_trait>>where
'life0: 'async_trait,
Self: 'async_trait,
Source§impl SnapshotSource for HttpStore
impl SnapshotSource for HttpStore
Source§fn principals<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Option<Vec<Principal>>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn principals<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Option<Vec<Principal>>, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Over HTTP this is the only way an instance learns the principal set:
subscribe above is a closed channel, so there are no deltas to
accumulate and the periodic refresh carries everything (GL-48).
A server whose backend cannot enumerate answers 501, which maps back
to None — “stay on your configured set” — rather than to an empty
catalogue, which would mean “forget everyone”.
Source§fn snapshot<'life0, 'async_trait>(
&'life0 self,
principal: Principal,
) -> Pin<Box<dyn Future<Output = Result<SnapshotResolution, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn snapshot<'life0, 'async_trait>(
&'life0 self,
principal: Principal,
) -> Pin<Box<dyn Future<Output = Result<SnapshotResolution, StoreError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn subscribe(&self) -> Receiver<SnapshotPush>
fn subscribe(&self) -> Receiver<SnapshotPush>
snapshot() fetch after a lag error
observes at least the newest generation.Source§impl UsageSink for HttpStore
impl UsageSink for HttpStore
Source§fn ingest<'life0, 'life1, 'async_trait>(
&'life0 self,
events: &'life1 [UsageEvent],
_now: Timestamp,
) -> Pin<Box<dyn Future<Output = Result<IngestReport, IngestError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn ingest<'life0, 'life1, 'async_trait>(
&'life0 self,
events: &'life1 [UsageEvent],
_now: Timestamp,
) -> Pin<Box<dyn Future<Output = Result<IngestReport, IngestError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
request_id; every event must match its
stored (lease_id, account_id, fencing_token) capability before lease
state and accounting capacity are checked. Partial acceptance is
normal — the report says what happened. Read more