pub struct Station { /* private fields */ }Expand description
Phase 5 Station. Unified Series<T> + DiskStore<T> plumbing under all
stream classes. One multiplexer actor per SeriesKey (= exchange × account
× symbol × kind). N consumers share via broadcast::channel.
Implementations§
Source§impl Station
impl Station
pub fn builder() -> StationBuilder
pub fn storage_root(&self) -> &Path
pub fn active_streams(&self) -> usize
Sourcepub fn hub(&self) -> Arc<ExchangeHub> ⓘ
pub fn hub(&self) -> Arc<ExchangeHub> ⓘ
Shared ExchangeHub backing this Station’s connectors.
Exposed so a consumer that also needs raw REST history (e.g. a chart
doing scroll-left pagination) can route backfill::fetch_history /
backfill::klines_recent through the SAME connector pool the Station’s
live subscriptions use — instead of dialing a second, parallel hub.
One pool means one dial-wave, one rate-limit budget, one warm-up.
ExchangeHub::clone is O(1) (Arc-pooled internally).
Sourcepub fn series<T: DataPoint + 'static>(
&self,
key: &SeriesKey,
) -> Option<Arc<RwLock<Series<T>>>>
pub fn series<T: DataPoint + 'static>( &self, key: &SeriesKey, ) -> Option<Arc<RwLock<Series<T>>>>
Return a sync handle to the in-memory ring for key.
Returns Some(Arc<RwLock<Series<T>>>) when a forwarder for key is
currently live (active subscription or within the 30 s grace window) and
the concrete element type matches T. Returns None when no active
forwarder exists for this key or when the stored type differs from T
(type mismatch is silently treated as absent rather than panicking).
Render-time consumers (chart panels, dashboards) use this to peek at the
running ring without awaiting an Event. The handle is independent of
SubscriptionHandle::recv() — events still flow through there for
state-mutation paths; this getter is read-only.
Sourcepub fn register_consumer(&self, quota: ConsumerQuota) -> ConsumerHandle
pub fn register_consumer(&self, quota: ConsumerQuota) -> ConsumerHandle
Register a consumer with the given quota. Drop the returned
[ConsumerHandle] to release all of the consumer’s active
subscriptions atomically.
This is opt-in: Station::subscribe continues to work without
quotas. A consumer that wants caps registers and uses
[ConsumerHandle::subscribe]; one that does not keeps calling
Station::subscribe directly.
Sourcepub fn connector_events(&self) -> Receiver<Event>
pub fn connector_events(&self) -> Receiver<Event>
A broadcast receiver for connector lifecycle events
(ConnectorReady / SymbolsLoaded). Returns events emitted from any
source — warmup(), on-demand subscribe-time connector init, REST
exchange-info refresh.
Independent of SubscriptionHandle event streams. Capacity 256.
Lag drops oldest.
Sourcepub fn symbols(&self, exchange: ExchangeId) -> Vec<SymbolInfo>
pub fn symbols(&self, exchange: ExchangeId) -> Vec<SymbolInfo>
Snapshot of cached SymbolInfo for exchange across all account types.
Empty if warmup hasn’t yet been called or REST hasn’t completed.
Sourcepub fn ws_health(&self, key: &SeriesKey) -> Option<WsHealth>
pub fn ws_health(&self, key: &SeriesKey) -> Option<WsHealth>
Snapshot the live health metrics for the WS forwarder backing key.
Returns None if no forwarder exists for this key (no active or
grace-window subscription).
Sync, non-blocking — suitable for periodic diagnostics polls or per-frame UI overlays (latency badges). Each field is a best-effort snapshot:
connected: always accurate — derived from mux presence.rtt_ms:Noneuntil per-connector RTT handle wiring is added (incremental; OKX is the first candidate).last_message_ms:Noneuntil per-forwarder atomic timestamp wiring is added (incremental).
Sourcepub fn ws_health_for_exchange(&self, exchange: ExchangeId) -> Option<WsHealth>
pub fn ws_health_for_exchange(&self, exchange: ExchangeId) -> Option<WsHealth>
Aggregate health across all forwarders for exchange.
rtt_ms: median of non-NoneRTT values across forwarders.last_message_ms: max of non-Nonelast-message timestamps (most-recent message seen on any forwarder for this exchange).connected:trueif at least one forwarder is connected.
Returns None if there are no active forwarders for exchange.
Sourcepub async fn warmup(&self, exchanges: &[ExchangeId]) -> WarmupReport
pub async fn warmup(&self, exchanges: &[ExchangeId]) -> WarmupReport
Eagerly connect to every exchange in exchanges and pre-load their
full symbol list. Subscribes nothing — produces only
Event::ConnectorReady (one per exchange that finishes
connect_public) and Event::SymbolsLoaded (one per exchange whose
REST get_exchange_info succeeds for at least one account type) on
the broadcast channel returned by Station::connector_events().
Idempotent: running concurrently or repeatedly is safe. Already-connected exchanges short-circuit. Already-cached symbol lists re-broadcast from cache without REST.
Runs to completion — returns a [WarmupReport] of outcomes.
Sourcepub async fn subscribe(&self, set: SubscriptionSet) -> Result<SubscribeReport>
pub async fn subscribe(&self, set: SubscriptionSet) -> Result<SubscribeReport>
Subscribe to every (exchange, symbol, account, stream) combination in
set. Continue-on-error: per-stream failures are collected in
SubscribeReport::failed and do not abort the rest of the batch.
The returned handle carries events for every stream in ok. A
stream whose subscribe failed will simply not emit events through
the handle.
The whole call returns Err ONLY for batch-level failures (empty
set). Per-stream failures (StreamNotSupported, connect_websocket,
symbol normalize) are reported via report.failed.