use std::path::PathBuf;
use std::sync::Arc;
use dashmap::DashMap;
use crate::storage::{StorageConfig, StorageManager};
use digdigdig3::core::traits::WebSocketConnector;
use digdigdig3::core::types::{AccountType, ExchangeError, ExchangeId};
use super::rate::ReplayRate;
use super::ws::ReplayWebSocket;
#[derive(Debug, Clone)]
pub struct ReplayConfig {
pub storage_root: PathBuf,
pub rate: ReplayRate,
pub from_ms: Option<i64>,
pub to_ms: Option<i64>,
}
pub struct ReplayHub {
storage: Arc<StorageManager>,
config: ReplayConfig,
ws_pool: DashMap<(ExchangeId, AccountType), Arc<dyn WebSocketConnector>>,
}
impl ReplayHub {
pub async fn new(config: ReplayConfig) -> Result<Self, ExchangeError> {
let storage_config = StorageConfig {
root: config.storage_root.clone(),
default_retention_days: u32::MAX,
orderbook_snapshot_interval_secs: 0,
};
let storage = StorageManager::new(storage_config)
.map_err(|e| ExchangeError::Network(format!("replay storage init: {e}")))?;
Ok(Self {
storage: Arc::new(storage),
config,
ws_pool: DashMap::new(),
})
}
pub async fn connect_full(
&self,
id: ExchangeId,
accounts: &[AccountType],
_testnet: bool,
) -> Result<(), ExchangeError> {
for &acct in accounts {
let ws = ReplayWebSocket::new(id, acct, self.storage.clone(), self.config.clone());
ws.connect(acct)
.await
.map_err(|e| ExchangeError::Network(format!("replay connect: {e}")))?;
self.ws_pool.insert((id, acct), Arc::new(ws));
}
Ok(())
}
pub fn ws(&self, id: ExchangeId, acct: AccountType) -> Option<Arc<dyn WebSocketConnector>> {
self.ws_pool.get(&(id, acct)).map(|v| Arc::clone(&v))
}
pub fn shutdown(&self, id: ExchangeId) {
self.ws_pool.retain(|(eid, _), _| *eid != id);
}
pub fn list_connected(&self) -> Vec<(ExchangeId, AccountType)> {
self.ws_pool.iter().map(|r| *r.key()).collect()
}
pub fn is_connected(&self, id: ExchangeId, acct: AccountType) -> bool {
self.ws_pool.contains_key(&(id, acct))
}
}