use reqwest::Client;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::time::Duration;
use tokio::sync::Mutex;
use tokio::task::JoinHandle;
pub struct ConnectionManager {
client: Client,
base_url: String,
running: Arc<AtomicBool>,
handle: Arc<Mutex<Option<JoinHandle<()>>>>,
}
impl ConnectionManager {
pub fn new(client: Client, base_url: String) -> Self {
Self {
client,
base_url,
running: Arc::new(AtomicBool::new(false)),
handle: Arc::new(Mutex::new(None)),
}
}
pub async fn start_keepalive(&self, interval: Duration) {
if self.running.load(Ordering::Relaxed) {
return;
}
self.running.store(true, Ordering::Relaxed);
let client = self.client.clone();
let base_url = self.base_url.clone();
let running = self.running.clone();
let handle = tokio::spawn(async move {
while running.load(Ordering::Relaxed) {
let _ = client
.get(format!("{}/time", base_url))
.timeout(Duration::from_secs(5))
.send()
.await;
tokio::time::sleep(interval).await;
}
});
let mut handle_guard = self.handle.lock().await;
*handle_guard = Some(handle);
}
pub async fn stop_keepalive(&self) {
self.running.store(false, Ordering::Relaxed);
let mut handle_guard = self.handle.lock().await;
if let Some(handle) = handle_guard.take() {
handle.abort();
}
}
pub fn is_running(&self) -> bool {
self.running.load(Ordering::Relaxed)
}
pub async fn ping(&self) -> Result<(), reqwest::Error> {
self.client
.get(format!("{}/time", self.base_url))
.timeout(Duration::from_secs(5))
.send()
.await?;
Ok(())
}
}
impl Drop for ConnectionManager {
fn drop(&mut self) {
self.running.store(false, Ordering::Relaxed);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_connection_manager_creation() {
let client = reqwest::ClientBuilder::new().no_proxy().build().unwrap();
let manager = ConnectionManager::new(client, "https://clob.polymarket.com".to_string());
assert!(!manager.is_running());
}
#[tokio::test]
async fn test_keepalive_start_stop() {
let client = reqwest::ClientBuilder::new().no_proxy().build().unwrap();
let manager = ConnectionManager::new(client, "https://clob.polymarket.com".to_string());
manager.start_keepalive(Duration::from_secs(30)).await;
tokio::time::sleep(Duration::from_millis(100)).await;
assert!(manager.is_running());
manager.stop_keepalive().await;
tokio::time::sleep(Duration::from_millis(100)).await;
assert!(!manager.is_running());
}
}