pub struct EdgeConfig { /* private fields */ }Expand description
Runtime configuration shared by every cloned metering service.
Implementations§
Source§impl EdgeConfig
impl EdgeConfig
Sourcepub fn new(tenants: Arc<dyn TenantStore>) -> Self
pub fn new(tenants: Arc<dyn TenantStore>) -> Self
Construct an edge using API-key tenants and a no-op billing recorder.
Sourcepub fn with_strict_protocol_version(self, strict: bool) -> Self
pub fn with_strict_protocol_version(self, strict: bool) -> Self
Refuse requests that predate the mirrored headers instead of reading their body.
By default a legacy request is classified from its JSON-RPC body, which is what
lets clients older than mcp_usage_core::version::HEADER_VALIDATION_SINCE -
still the majority - reach the origin at all. The body is the document the origin
executes, so pricing on it cannot be gamed the way pricing on unvalidated headers
can; the cost is one bounded JSON parse per legacy request.
Set this when a deployment would rather serve only modern clients than spend that parse, or when an upstream proxy already guarantees the revision.
Sourcepub fn with_recorder(self, recorder: SharedRecorder) -> Self
pub fn with_recorder(self, recorder: SharedRecorder) -> Self
Install the hot-path usage recorder.
Sourcepub fn with_task_store(self, tasks: Arc<dyn TaskAttributionStore>) -> Self
pub fn with_task_store(self, tasks: Arc<dyn TaskAttributionStore>) -> Self
Install a durable task-attribution store.
Sourcepub fn with_meter_name(self, meter_name: impl Into<String>) -> Self
pub fn with_meter_name(self, meter_name: impl Into<String>) -> Self
Set the provider meter event name.
Sourcepub fn with_cache(self, max_entries: usize, max_ttl: Duration) -> Self
pub fn with_cache(self, max_entries: usize, max_ttl: Duration) -> Self
Configure cache capacity and the maximum honored server TTL.
Sourcepub fn with_public_cache_sharing(self, share: bool) -> Self
pub fn with_public_cache_sharing(self, share: bool) -> Self
Share results the origin marks cacheScope: "public" across tenants.
Disabled by default. A "public" result is an assertion by the origin
that the body does not depend on who asked for it; honoring it puts one
entry in a bucket every authorization context reads, so an origin that
mislabels a tenant-specific result turns that mistake into a cross-tenant
disclosure at the edge. Cacheable methods include resources/read, so
the blast radius is resource contents, not just discovery listings.
Enable this only when the origin’s public results are genuinely tenant-independent. Leaving it off costs cache hit rate and nothing else: a cache may always decline to reuse a response.
Sourcepub fn with_credential_forwarding(self, forward: bool) -> Self
pub fn with_credential_forwarding(self, forward: bool) -> Self
Forward the API key to the inner service after authenticating it.
Disabled by default: the edge consumes the credential, so passing it on hands the inner service a secret it was not issued. That is harmless when the origin runs in-process, and an exposure the moment this layer fronts an origin in another trust domain.
Enable it when the origin performs its own check against the same key.
Sourcepub fn with_max_request_body(self, bytes: usize) -> Self
pub fn with_max_request_body(self, bytes: usize) -> Self
Bound bytes accepted from one MCP request body.
Sourcepub fn with_max_response_capture(self, bytes: usize) -> Self
pub fn with_max_response_capture(self, bytes: usize) -> Self
Bound bytes retained while observing a response. Oversized responses continue streaming but fail toward not charging and not caching.
Sourcepub fn metrics(&self) -> Arc<EdgeMetrics> ⓘ
pub fn metrics(&self) -> Arc<EdgeMetrics> ⓘ
Shared edge counters.
Sourcepub fn deferred(&self) -> Arc<DeferredCompletions> ⓘ
pub fn deferred(&self) -> Arc<DeferredCompletions> ⓘ
Terminal accounting parked because it could not finish without awaiting.
Only a durable task store parks anything: its futures perform real I/O,
and the body is released from Drop, where nothing may await. Every
subsequent authenticated request runs a bounded number of them, so an
application that ignores this still converges. Draining explicitly is
better, and draining after graceful shutdown is what stops a departing
process from taking durable-task charges with it.
Take the handle before passing the configuration to the layer.
Sourcepub fn with_deferred_drain_per_request(self, completions: usize) -> Self
pub fn with_deferred_drain_per_request(self, completions: usize) -> Self
Bound how much parked accounting each authenticated request runs.
Zero leaves draining entirely to EdgeConfig::deferred. Raising it
clears a backlog sooner at the cost of latency on the requests that do
the work.
Sourcepub fn with_deferred_capacity(self, capacity: usize) -> Self
pub fn with_deferred_capacity(self, capacity: usize) -> Self
Bound how many completions may be parked before the oldest is discarded.
Sourcepub fn with_auth_failure_limit(
self,
max_failures: u64,
window: Duration,
) -> Result<Self, EdgeConfigError>
pub fn with_auth_failure_limit( self, max_failures: u64, window: Duration, ) -> Result<Self, EdgeConfigError>
Refuse further guessing after max_failures bad credentials in window.
Disabled by default, because the useful ceiling depends entirely on how
many clients an edge serves. Only failures consume the budget, so a
caller with a valid key is never affected: exhausting it turns a wrong
key’s 401 into a 429 and nothing more.
This bounds sustained guessing across the whole edge. It is not per-client limiting, which needs a client identity this layer cannot trust, and belongs in the proxy in front of it.
§Errors
Returns EdgeConfigError::InvalidAuthFailureWindow when window is
zero.