pub struct LseVaultClient { /* private fields */ }Expand description
Authenticated client for the London Strategic Edge vault.
Wraps the internal transport shared with the provider’s other host, pointed at the vault, and
adds the vault’s own configuration and endpoints: usage here, paged candles in
historical, the catalog in reference, bulk export
in export.
§Request rationing is per client, not per call
Every request this client issues — candle page, export submit, status poll, artifact download —
first passes a gate that bounds requests in flight to
with_concurrency and spaces their starts by
with_pace. That gate is shared by clones, so driving N concurrent
fetches from one client (Arc it, or clone it) keeps the aggregate inside those two bounds
rather than multiplying them by N. Two clients built separately by new share nothing and
ration independently — one client per API key is the usable unit.
§⚠️ Licensing
Data retrieved through this client is not redistributable. See the module documentation and https://londonstrategicedge.com/terms.
Implementations§
Source§impl LseVaultClient
impl LseVaultClient
Sourcepub async fn submit_export(
&self,
request: &LseExportRequest,
) -> Result<LseExportJob, LseError>
pub async fn submit_export( &self, request: &LseExportRequest, ) -> Result<LseExportJob, LseError>
Submit an export job.
Returns as soon as the provider accepts the job (202); the artifact is built
asynchronously. Poll with export_status, or use
await_export.
§⚠️ This spends allowance whether or not it succeeds
The allowance is five exports per hour and a rejection still consumes one, which is why
LseExportRequest validates at construction. Poll
usage to see where you are — the position is deliberately not
fetched here, since that would add a network round trip to every submission.
§Errors
LseError::InvalidInputif the range lies wholly in the future. The provider answers such a request with a valid, empty artifact and no error, so it spends an export to learn nothing — the same economics as the empty rangeLseExportRange::newrejects, which is why it is rejected too. Checked here rather than at construction because the answer depends on when the question is asked; seeLseExportRange::is_wholly_afterfor the day of slack that keeps a caller’s local “today” from tripping it.LseError::QuotaExceededwhen the export allowance is exhausted, carrying the allowance position at the point of rejection.LseError::Apifor any other non-success status, with the provider’s diagnostic unwrapped from its envelope.LseError::Deserializeif the response will not decode.
Sourcepub async fn export_status(
&self,
job_id: &str,
) -> Result<LseExportJobStatus, LseError>
pub async fn export_status( &self, job_id: &str, ) -> Result<LseExportJobStatus, LseError>
Fetch the current state of an export job.
Polling costs nothing from the export allowance — only from the per-minute call budget.
§Errors
LseError::RateLimitedon a429— deliberately notLseError::QuotaExceeded, which is whatsubmit_exportanddownload_exportreport. Those two spend metered allowance (an export, and bytes respectively), so a429there means the allowance is gone; a status read spends neither, so a429here is the per-minute limit. Reporting it as an exhausted allowance would also add ausage()round trip to every iteration of a polling loop, and would assert a provider behaviour that has not been measured on this endpoint.LseError::Apifor any other non-success status, including the404an unknown job id returns.LseError::Deserializeif the response will not decode.
Sourcepub async fn await_export(
&self,
job_id: &str,
poll_interval: Duration,
timeout: Duration,
) -> Result<LseExportJobStatus, LseError>
pub async fn await_export( &self, job_id: &str, poll_interval: Duration, timeout: Duration, ) -> Result<LseExportJobStatus, LseError>
Poll an export job until it reaches a terminal state.
§Cadence is the caller’s
poll_interval and timeout are both supplied by the caller and neither is defaulted:
this integration exposes the allowance signal and never decides pacing on the consumer’s
behalf.
timeout bounds the call whatever poll_interval is — the sleep is cut short at the deadline
rather than run in full — so a long interval paired with a short timeout reports
LseError::ExportTimeout promptly instead of blocking for an interval first. One status
request is still in flight when the deadline passes, so the call can overrun it by that
request’s duration. A poll_interval or timeout so large that it would overflow the clock
(Duration::MAX, used as a “no timeout” / “wait for the deadline” sentinel) saturates rather
than panicking.
§Errors
LseError::ExportFailedif the job reachesfailedorexpired.LseError::ExportTimeoutiftimeoutelapses first. The job keeps building — the identifier stays valid, so a laterexport_statuscan pick it up without spending another export.- Anything
export_statusreturns.
Sourcepub async fn download_export(
&self,
job: &LseExportJobStatus,
destination: impl AsRef<Path>,
request: &LseExportRequest,
) -> Result<LseExport, LseError>
pub async fn download_export( &self, job: &LseExportJobStatus, destination: impl AsRef<Path>, request: &LseExportRequest, ) -> Result<LseExport, LseError>
Download a ready export artifact to destination.
§Transfer bound
The shared client applies a 30 s total deadline, which reqwest runs through to the end
of the response body — right for a page of JSON, fatal for an artifact, since a transfer
longer than 30 s would abort mid-body however healthy the connection. This request therefore
overrides it with a six-hour backstop (enough for a 7 GB artifact on a ~3 Mbit/s link) and
relies on the client’s per-read timeout to detect an actual stall in seconds. An
interrupted transfer resumes rather than restarting, so a slower link than that still
converges across calls.
§Resume and integrity
Downloads into destination + .<job id>.part, resuming an interrupted transfer with a
Range request (the provider advertises Accept-Ranges: bytes and answers 206). The
in-progress file is scoped to the job, not to the destination alone, so a leftover can
only ever be a prefix of the artifact this call is fetching — one job never resumes onto
another’s bytes. A 206 is
accepted only if its Content-Range starts at the byte that was asked for; a 416 is
treated as “the .part already holds the whole artifact” rather than as a failure, so a
transfer interrupted between the final write and the rename still converges. On completion
the artifact is verified against the job’s sha256 and bytes, then atomically renamed
into place. On a mismatch an error is returned and the destination is left untouched,
so it never contains a corrupt file.
Verification covers only the dimensions the job actually reports. Both fields are
Option, and every measured ready job carried both — but that is an observation, not a
guarantee the provider makes. A ready job missing one is downloaded and renamed with that
check skipped, and a warn! naming the skipped check is emitted. Skipping is deliberate:
refusing an artifact the provider considers ready, over metadata this integration merely
expects, would forbid a correct download with no way around it. A job reporting neither
field additionally ignores any pre-existing .part and transfers the artifact in full, so
what lands at destination is at least something this call fetched end to end rather than a
leftover accepted on the strength of its filename. A download consumes no export allowance,
so that costs bandwidth only.
§⚠️ Caller obligation: one download per destination at a time
Concurrent calls sharing a destination are not supported. Each reads the .part file’s
length to decide where to resume from, then opens it; two overlapping calls interleave writes
against independently-primed hashers, corrupting the .part or failing verification
spuriously. Serialise them, or give each its own destination.
A .part that failed verification is kept when it is incomplete and discarded when it is
corrupt, which is decided by which check failed rather than by whether this call happened
to append anything. Shorter than the artifact means a truncated transfer, so the bytes are a
valid prefix and a re-call resumes from them — for a multi-gigabyte artifact that is the
difference between finishing and starting over. Longer than the artifact, or the right length
at the wrong digest with nothing left to fetch, means corrupt: the file is removed so a
re-call restarts rather than failing identically forever. LseError::IntegrityMismatch
reports which happened via discarded.
§⚠️ Caller obligation: reclaiming abandoned .part files
Nothing here ever deletes a .part except the corrupt-file path above. A .part is
named for its job (see the resume section), which is what makes resuming safe — and what
makes an abandoned one unreachable: a process killed mid-transfer leaves its .part behind,
and a re-export of the same range gets a new job id, so the next call writes a new file
and never looks at the old one. A 7 GB export killed at 6 GB occupies 6 GB indefinitely.
This integration deliberately offers no cleanup or enumeration API: deleting files it did
not write this call is a policy decision, and “which of these is still wanted” depends on
whether the caller intends to resume — which only the caller knows. Reclaiming them is
therefore yours. They are identifiable without help: they sit next to the destination, so a
glob of <destination>.*.part finds every candidate. Matching a specific job needs one
step of care — the id embedded in the name is the job id with every character outside
[A-Za-z0-9._-] replaced by _, since a provider-supplied id is not assumed path-safe — so
apply the same substitution before deciding which ids to spare.
Downloads consume no export allowance, so discarding a .part you no longer want costs
bandwidth on the next attempt and nothing else.
The URL is built from the client’s base URL and the job id rather than from the job’s
download_url, preserving this client’s invariant that it only ever requests URLs it
constructed itself.
§⚠️ A ready job may legitimately contain zero rows
Check LseExportJobStatus::rows. A zero-row artifact is a well-formed Parquet file with
the full schema, so nothing downstream will complain.
§Errors
LseError::InvalidInputif the job is notready.LseError::IntegrityMismatchif the downloaded bytes do not match the job’ssha256orbytes.LseError::Iofor any filesystem failure.LseError::QuotaExceeded/LseError::Apias forsubmit_export.
Source§impl LseVaultClient
impl LseVaultClient
Sourcepub fn fetch_candles<'a>(
&'a self,
symbol: &'a str,
interval: CandleInterval,
start: DateTime<Utc>,
end: DateTime<Utc>,
) -> impl Stream<Item = Result<Candle, LseError>> + 'a
pub fn fetch_candles<'a>( &'a self, symbol: &'a str, interval: CandleInterval, start: DateTime<Utc>, end: DateTime<Utc>, ) -> impl Stream<Item = Result<Candle, LseError>> + 'a
Fetch historical candles for symbol at interval, paginating automatically.
Returns a Stream that processes each page as it arrives rather than buffering the whole
range. For a convenience Vec, see collect_candles.
§Symbol
The vault keys candles on the display symbol — EUR/USD, AAPL, BP.L, ES.F — not
on a dataset slug. Nothing here needs slug.
§Range contract
Yields exactly the candles whose close_time falls in [start, end]
(both inclusive), matched on close_time — the field consumers receive — consistent
with the library’s other historical fetches.
The vault’s own range is expressed on the bar’s open time with an exclusive upper
bound, so this method maps both bounds (lower widens to capture the bar whose
close_time == start; upper is extended past the final bar’s open) and then trims exactly
on close_time. The trim also absorbs the cursor’s second-precision truncation of
sub-second start/end values.
close_time is computed library-side as the exclusive period-end boundary
(open_time + interval) via the shared boundary helper; the provider reports only the open
instant.
§Sparseness differs by resolution — and a closed market is not the same as no bar
Intraday: periods with no activity are omitted entirely, so consecutive candles are not guaranteed to be one interval apart. This is the opposite of Binance’s REST klines, which server-side gap-fill. Consumers needing a dense grid must fill it themselves.
Daily: the series is not sparse. Non-trading days are emitted as flat bars —
open == high == low == close — for every sampled Saturday and for the US Independence Day
observance; only Sundays are absent. So a backtest sees a tradeable price on a closed market,
and the flat OHLC is the only signal. Do not infer “no bar means the market was closed”: see
the module’s data characteristics.
§Volume — ⚠️ not a figure to size on without reconciling it
FX candles carry no volume: the vault omits the field, which surfaces as
volume: None rather than a zero. trade_count is None for every
dataset — the vault reports none.
Where volume is published it is unreliable in both directions, and by margins large
enough to invert a result rather than blur it: a majority of sampled one-minute equity bars
report 0 in minutes the tick tape shows real trades, and ETF bars have been reported
carrying three to four orders of magnitude too much — one QQQ minute published at some
5,700× that session’s entire consolidated volume. Equity totals over the same period ran
well under the consolidated tape. Every one of those bars is structurally valid, so neither
this method nor any shape check on its output can tell them from correct ones. See the
module’s data characteristics for the measurements and their
provenance. Reconcile against a second source before trusting a volume-derived quantity.
§Coverage — a range the symbol does not cover is not an error
The provider publishes a first tick and a coverage span per symbol per dataset, and the two
vary widely: an ETF has been reported carrying three months of spot history where equities
reach back two decades. Those fields live in the catalog on the discovery host, which this
integration does not wrap, so this method cannot check start against them. A range
beginning before a symbol’s coverage yields the bars that exist and nothing to say the
remainder was never published — indistinguishable here from a genuinely quiet period.
Establish a symbol’s depth from the catalog before choosing a range to backfill.
§Arguments
symbol- Display symbol, e.g."EUR/USD"or"AAPL".interval- Resolution. The provider serves 14 ofCandleInterval’s variants; an unserved one is rejected up front withLseError::UnsupportedIntervalrather than relayed as a400.start/end- Inclusiveclose_timebounds.
§Errors
Each yielded item is a Result. On 429 the stream yields LseError::RateLimited and
ends — resume by re-calling with start set past the last close_time received. An
inverted range is LseError::InvalidInput. Other failures surface as
LseError::Api / Http / Deserialize.
A page carrying a bar that closes past end ends the stream with
LseError::UnexpectedCandleRange rather than trimming it away: the upper bound is exact
by construction, so such a bar means the range parameters were not honoured. Every in-range
bar on that page is yielded first. Note the lower bound is not symmetric — it is widened
deliberately, so bars closing before start are trimmed without comment.
A page whose opens step backwards ends the stream with
LseError::NonMonotonicCandlePage, and one whose bars are spaced closer than interval
with LseError::UnexpectedCandleResolution. Both are checked before any bar of that
page is yielded — unlike the range violation above, nothing from such a page is emitted.
§Request count
Because the row cap is applied silently, a short page cannot be distinguished from the end
of the data. Pagination therefore continues until a page comes back empty or the cursor
passes the requested range, which costs at most one extra request per fetch. Treating a
short page as terminal would be faster and would silently truncate the result if the
provider ever lowered its cap below the rows requested per page — the figure the provider
itself reports as max_rows_per_request,
measured at 5,000 and overridable with
with_page_limit.
Sourcepub async fn collect_candles(
&self,
symbol: &str,
interval: CandleInterval,
start: DateTime<Utc>,
end: DateTime<Utc>,
) -> Result<Vec<Candle>, LseError>
pub async fn collect_candles( &self, symbol: &str, interval: CandleInterval, start: DateTime<Utc>, end: DateTime<Utc>, ) -> Result<Vec<Candle>, LseError>
Fetch historical candles into a Vec.
Convenience over fetch_candles with the same range contract, for
slices small enough to hold in memory. Buffers the whole range — prefer the stream for
long backfills at fine resolutions.
§Errors
Fails on the first error, discarding any candles already received. See
fetch_candles.
Source§impl LseVaultClient
impl LseVaultClient
Sourcepub fn fetch_option_candles<'a>(
&'a self,
ticker: &'a str,
start: DateTime<Utc>,
end: DateTime<Utc>,
) -> impl Stream<Item = Result<LseOptionCandle, LseError>> + 'a
pub fn fetch_option_candles<'a>( &'a self, ticker: &'a str, start: DateTime<Utc>, end: DateTime<Utc>, ) -> impl Stream<Item = Result<LseOptionCandle, LseError>> + 'a
Fetch one-minute candles for one option contract, paginating automatically.
Same range contract as fetch_candles: yields exactly the bars whose
close_time falls in [start, end] (both inclusive), ascending,
with the same ordering, resolution and range checks and the same errors. Minutes with no
print are absent rather than zero-filled.
§Arguments
ticker- The OSI contract symbol, e.g."SPY260922P00773000". Case-insensitive.start/end- Inclusiveclose_timebounds.
§Errors
See fetch_candles. A ticker the provider does not know yields an
empty stream, not an error. A row whose ticker is not an OSI symbol is an
LseError::Deserialize.
Sourcepub async fn collect_option_candles(
&self,
ticker: &str,
start: DateTime<Utc>,
end: DateTime<Utc>,
) -> Result<Vec<LseOptionCandle>, LseError>
pub async fn collect_option_candles( &self, ticker: &str, start: DateTime<Utc>, end: DateTime<Utc>, ) -> Result<Vec<LseOptionCandle>, LseError>
Fetch option candles into a Vec. Buffers the whole range.
§Errors
Fails on the first error, discarding any candles already received. See
fetch_option_candles.
Sourcepub fn fetch_option_flow<'a>(
&'a self,
underlying: Option<&'a str>,
start: DateTime<Utc>,
end: DateTime<Utc>,
) -> impl Stream<Item = Result<LseOptionPrint, LseError>> + 'a
pub fn fetch_option_flow<'a>( &'a self, underlying: Option<&'a str>, start: DateTime<Utc>, end: DateTime<Utc>, ) -> impl Stream<Item = Result<LseOptionPrint, LseError>> + 'a
Fetch every option print in [start, end), oldest first, walking the range automatically.
§Range and order
Yields exactly the prints whose time falls in [start, end) —
half-open, so adjacent ranges tile without overlap — ordered by time and then by
id. Sub-second bounds are honoured by trimming: the provider accepts
only whole seconds, so the requested range is widened to them and cut back here.
§How the range is walked
The provider answers newest-first and silently truncates at a 5,000-row cap, with no offset or cursor, so a range can only be read in windows small enough to come back whole. This method walks forward in adaptive windows: a window that returns a full page is halved and read again, and one that comes back sparse lets the next window grow. Each complete window is emitted oldest-first, so memory holds at most one page. The extra requests fall only on windows that hit the cap.
A full page is the only sign of truncation, so the fetch first reads the provider’s own
max_rows_per_request from
usage — one extra request per fetch — and treats the smaller of that and
with_page_limit as a full page. A page limit set above the
provider’s cap therefore cannot hide a truncated window.
§Known limitation
The walk trusts the reported cap to be the one /options/flow enforces. They agreed when
measured, and the live options canary asserts they still do; were the provider to enforce a
lower cap than it reports, a truncated window would read as complete.
§Arguments
underlying- Restrict to one underlying (case-insensitive), orNonefor every underlying the provider carries. The endpoint cannot filter by contract — it silently ignores atickerparameter — so select contracts from the result.start/end- The half-open time range.
§Errors
Each yielded item is a Result, and the stream ends after the first error.
LseError::InvalidInputfor an inverted range, or one ending withinOPTION_FLOW_SETTLE_MARGINof now: the provider can serve a recent window incomplete with a200, and returning it would hand back a short tape that looks final.LseError::OptionFlowWindowSaturatedwhen a single second holds more prints than one page can carry, so the window cannot be narrowed further without losing some.LseError::UnexpectedOptionFlowRowwhen a row falls outside the window or underlying it was requested for — the provider ignoring a parameter, which it is known to do silently. Checked before any row of that window is yielded.- On
429,LseError::RateLimited; resume by re-calling withstartset to the last print’s time. Prints sharing that time are then yielded again; de-duplicate onid. - Otherwise
LseError::Api/Http/Deserialize— the last also when the reported row cap is zero, or when a row’s ticker is not an OSI symbol. Like the row checks above, that fails the whole window before any of it is yielded.
Sourcepub async fn collect_option_flow(
&self,
underlying: Option<&str>,
start: DateTime<Utc>,
end: DateTime<Utc>,
) -> Result<Vec<LseOptionPrint>, LseError>
pub async fn collect_option_flow( &self, underlying: Option<&str>, start: DateTime<Utc>, end: DateTime<Utc>, ) -> Result<Vec<LseOptionPrint>, LseError>
Fetch option prints into a Vec, oldest first. Buffers the whole range — a full session
for one busy underlying is several hundred thousand prints; prefer the stream for long
ranges.
§Errors
Fails on the first error, discarding any prints already received. See
fetch_option_flow.
Source§impl LseVaultClient
impl LseVaultClient
Sourcepub async fn fetch_catalog(&self) -> Result<Vec<LseCatalogEntry>, LseError>
pub async fn fetch_catalog(&self) -> Result<Vec<LseCatalogEntry>, LseError>
Fetches the whole catalog.
The endpoint is unpaginated and returns every entry in one response — 22,966 at the last measurement, and 9.1 MB of JSON — all of it buffered and decoded, so treat this as an occasional call rather than something to poll.
It is a discovery and validation helper: it does not register instruments, which the caller declares explicitly as with every other connector.
Timestamps are returned unparsed, so a single malformed first_tick surfaces through
LseCatalogEntry::first_tick_time on that one entry instead of failing the whole
fetch.
§Errors
Returns LseError::Api for a non-success status, LseError::RateLimited on a 429,
LseError::Http on a transport failure, and LseError::Deserialize if the response
does not match LseCatalogEntry.
§⚠️ Licensing
The response is provider data and must not be redistributed or committed. See the module documentation.
Source§impl LseVaultClient
impl LseVaultClient
Sourcepub fn new(api_key: &str) -> Result<Self, LseError>
pub fn new(api_key: &str) -> Result<Self, LseError>
Create a client with an explicit API key.
§Redirects are not followed
The key rides every request as a client-wide x-api-key default header, and reqwest’s
cross-host header stripping covers Authorization, Cookie, Cookie2,
Proxy-Authorization and WWW-Authenticate — not a custom header. Under reqwest’s
default Policy::limited(10) a single server-issued
302 would therefore re-issue the request, live key attached, against whatever host the
vault named. The download endpoint is exactly the shape that hands off to object storage,
and in a CI workflow that key is a repository secret.
Policy::none makes the “this client only ever requests
URLs it builds itself” invariant structural rather than a property of the vault’s current
behaviour — a followed redirect is a server-supplied URL. An unexpected 3xx surfaces as a
typed error instead of being followed, and it applies wholesale: a same-origin 301/308
(trailing-slash normalisation by a proxy or CDN) is surfaced too, so a base URL set via
with_base_url must serve responses directly.
§Errors
Returns LseError::InvalidCredential if the key cannot be encoded as an HTTP header
value (e.g. non-ASCII bytes), or LseError::Http if the HTTP client cannot be built.
Sourcepub fn from_env() -> Result<Self, LseError>
pub fn from_env() -> Result<Self, LseError>
Create a client from the LSE_API_KEY environment variable.
§Errors
Returns LseError::EnvVar if the variable is unset or does not hold valid UTF-8, plus
anything new returns. Neither message ever contains the variable’s value.
Sourcepub fn with_base_url(self, base_url: impl Into<String>) -> Self
pub fn with_base_url(self, base_url: impl Into<String>) -> Self
Override the vault base URL, for tests against a mock server or a proxy.
Infallible by design: this client only ever requests URLs it builds itself from this base — the vault returns bare arrays with no cursor, so there is never a server-supplied URL to follow and no trusted origin to derive.
Sourcepub fn with_client(self, client: Client) -> Self
pub fn with_client(self, client: Client) -> Self
Inject a pre-built reqwest::Client.
§⚠️ The injected client must carry the x-api-key header itself
This replaces the authenticated client built by new, auth header included.
It is intended for transport configuration (proxy, TLS, a shared connection pool) where the
caller supplies credentials; a client without the header will see every request 401.
§⚠️ It must also carry its own timeouts
new configures a 30s total timeout and a 30s read timeout; reqwest’s
default is neither. Replacing the client drops both, and a timeout-less client
interacts badly with the request gate:
a permit is held for the whole request, so with the default concurrency of 2, two stalled
connections exhaust the gate permanently — for this client and every clone of it, with no
error, no log, and nothing to observe but a run that stops making progress. Set
timeout and
read_timeout on any client passed here.
§⚠️ And its own redirect policy
new sets
Policy::none so the API key cannot ride a server-issued
redirect to another host; reqwest’s default is Policy::limited(10), which strips only the
standard auth headers and would forward a custom x-api-key intact. A client supplied here
that carries the key must set Policy::none itself, or a single 302 from the vault (or
from a proxy in front of it) leaks the credential with no error and no log.
Sourcepub fn with_pace(self, pace: Duration) -> Self
pub fn with_pace(self, pace: Duration) -> Self
Override the minimum delay between the starts of two requests.
Applies to every request this client issues, not just successive pages of one fetch, and
is enforced against the gate this client
shares with its clones — so N concurrent fetches still start one request per pace between
them.
Pass Duration::ZERO to disable pacing entirely, at which point staying within the
provider’s calls_per_minute allowance becomes the
caller’s responsibility. The default is derived from that documented allowance.
Sourcepub fn with_page_limit(self, limit: NonZeroU32) -> Self
pub fn with_page_limit(self, limit: NonZeroU32) -> Self
Override how many rows a paged fetch requests per page.
The default is the provider’s measured
max_rows_per_request; raise it only against a key whose
usage reports a higher one. Requesting more than your key allows is not
an error — the vault caps the page silently, and pagination handles a short page — so an
over-large value costs nothing but degrades into more, smaller pages. The option print walk,
which cannot page past a short page, bounds this by the cap usage reports. Requesting fewer than
the cap is a legitimate way to bound per-page memory or response latency.
§Why NonZeroU32, where with_concurrency clamps
A concurrency of 0 parks every request — visibly broken, so clamping to 1 is a safe
reading of a caller slip. A page limit of 0 is worse than broken: the vault answers 200
with an empty page, which pagination reads as the end of the data, so the fetch completes
successfully having returned nothing. That is a silent wrong answer, and the type system
rules it out rather than a clamp papering over it.
Sourcepub fn with_concurrency(self, concurrency: usize) -> Self
pub fn with_concurrency(self, concurrency: usize) -> Self
Override how many requests this client may have in flight at once.
The default is the provider’s measured vault_concurrency;
raise it only against a key whose usage reports a higher one. 0 is
clamped to 1, since a client that can never issue a request is never what was meant.
§⚠️ Call this before cloning
This installs a fresh gate. Clones taken before the call keep the old one and ration separately from this client, which defeats the point of sharing; clones taken after share the new gate as usual.
Sourcepub async fn usage(&self) -> Result<QuotaStatus, LseError>
pub async fn usage(&self) -> Result<QuotaStatus, LseError>
Fetch the current allowance position.
The allowance is shared between streaming and bulk export, so a consumer running both
must budget against this single pool. See QuotaStatus for what is and is not reported —
notably, no window reset time is available.
§Errors
See LseError.
Trait Implementations§
Source§impl Clone for LseVaultClient
impl Clone for LseVaultClient
Auto Trait Implementations§
impl !RefUnwindSafe for LseVaultClient
impl !UnwindSafe for LseVaultClient
impl Freeze for LseVaultClient
impl Send for LseVaultClient
impl Sync for LseVaultClient
impl Unpin for LseVaultClient
impl UnsafeUnpin for LseVaultClient
Blanket Implementations§
Source§impl<T> AttachedTransformer<()> for T
impl<T> AttachedTransformer<()> for T
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreimpl<T> JsonSchemaMaybe for T
Source§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.Source§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.