px_core/exchange/fetcher.rs
1use std::future::Future;
2use std::pin::Pin;
3
4use crate::OpenPxError;
5
6/// Result of a checkpointed fetch operation.
7#[derive(Debug)]
8pub struct FetchResult {
9 /// Remaining markets that weren't flushed to a checkpoint (< checkpoint_interval)
10 pub markets: Vec<serde_json::Value>,
11 /// Final cursor value for logging/debugging
12 pub final_cursor: Option<String>,
13 /// Total number of markets fetched across all pages
14 pub total_fetched: usize,
15}
16
17/// Callback type for checkpoint operations.
18/// Receives the batch of markets and the current cursor value.
19pub type CheckpointCallback = Box<
20 dyn Fn(
21 &[serde_json::Value],
22 &str,
23 ) -> Pin<Box<dyn Future<Output = Result<(), OpenPxError>> + Send>>
24 + Send
25 + Sync,
26>;
27
28/// Trait for fetching raw market data from exchanges.
29/// Used by the Bronze layer to collect complete API responses.
30#[allow(async_fn_in_trait)]
31pub trait MarketFetcher: Send + Sync {
32 /// Exchange identifier (e.g., "kalshi", "polymarket")
33 fn exchange_id(&self) -> &'static str;
34
35 /// Fetch all markets as raw JSON values.
36 /// Handles pagination internally and returns all available markets.
37 async fn fetch_markets(&self) -> Result<Vec<serde_json::Value>, OpenPxError>;
38
39 /// Fetch markets with checkpoint callback.
40 /// Called every `checkpoint_interval` records with accumulated data.
41 ///
42 /// # Arguments
43 /// * `start_cursor` - Optional cursor/offset to resume from
44 /// * `checkpoint_interval` - Number of records before triggering checkpoint
45 /// * `on_checkpoint` - Async callback invoked with batch data and cursor
46 ///
47 /// # Returns
48 /// FetchResult containing remaining unflushed markets and metadata
49 async fn fetch_markets_with_checkpoints(
50 &self,
51 start_cursor: Option<String>,
52 checkpoint_interval: usize,
53 on_checkpoint: CheckpointCallback,
54 ) -> Result<FetchResult, OpenPxError>;
55
56 /// Extract the exchange-specific status from a raw market JSON.
57 fn extract_status(&self, raw: &serde_json::Value) -> String;
58}