alpaca_data/transport/
observer.rs

1use std::{fmt, sync::Arc, time::Duration};
2
3use crate::transport::meta::ResponseMeta;
4
5/// Immutable callback hook for successful HTTP responses.
6pub trait TransportObserver: Send + Sync {
7    /// Receives metadata about a successful response after transport retries finish.
8    fn on_response(&self, meta: &ObservedResponseMeta);
9}
10
11/// Read-only metadata emitted to [`TransportObserver`] implementations.
12#[derive(Clone, Debug, Eq, PartialEq)]
13pub struct ObservedResponseMeta {
14    /// Stable endpoint name such as `stocks.latest_bars`.
15    pub endpoint_name: &'static str,
16    /// Fully resolved request URL.
17    pub url: String,
18    /// Final HTTP status code.
19    pub status: u16,
20    /// Alpaca request identifier when the server returned one.
21    pub request_id: Option<String>,
22    /// Number of retry attempts that happened before this terminal response.
23    pub attempt_count: u32,
24    /// Total elapsed request time across retries.
25    pub elapsed: Duration,
26}
27
28impl From<&ResponseMeta> for ObservedResponseMeta {
29    fn from(meta: &ResponseMeta) -> Self {
30        Self {
31            endpoint_name: meta.endpoint_name,
32            url: meta.url.clone(),
33            status: meta.status,
34            request_id: meta.request_id.clone(),
35            attempt_count: meta.attempt_count,
36            elapsed: meta.elapsed,
37        }
38    }
39}
40
41#[derive(Clone)]
42pub(crate) struct ObserverHandle {
43    observer: Arc<dyn TransportObserver>,
44}
45
46impl ObserverHandle {
47    pub(crate) fn new(observer: Arc<dyn TransportObserver>) -> Self {
48        Self { observer }
49    }
50
51    pub(crate) fn on_response(&self, meta: &ResponseMeta) {
52        let observed = ObservedResponseMeta::from(meta);
53        self.observer.on_response(&observed);
54    }
55}
56
57impl fmt::Debug for ObserverHandle {
58    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59        f.write_str("ObserverHandle(..)")
60    }
61}