simulator_client/
client.rs1use std::time::Duration;
2
3use bon::Builder;
4use tokio_tungstenite::{
5 connect_async,
6 tungstenite::{client::IntoClientRequest, http::HeaderValue},
7};
8
9use crate::{
10 BacktestClientError, BacktestClientResult, BacktestSession, CreateSession,
11 urls::http_base_from_ws_url,
12};
13
14const DEFAULT_CONNECT_TIMEOUT: Duration = Duration::from_secs(10);
15
16#[derive(Debug, Clone, Builder)]
21#[builder(on(String, into))]
22pub struct BacktestClient {
23 url: String,
25 api_key: String,
27
28 #[builder(default = DEFAULT_CONNECT_TIMEOUT)]
30 connect_timeout: Duration,
31
32 request_timeout: Option<Duration>,
34
35 #[builder(default)]
37 log_raw: bool,
38}
39
40impl BacktestClient {
41 pub async fn create_session(
43 &self,
44 create: CreateSession,
45 ) -> BacktestClientResult<BacktestSession> {
46 let params = create.into_params()?;
47
48 let mut request = self.url.clone().into_client_request().map_err(|source| {
49 BacktestClientError::BuildRequest {
50 url: self.url.clone(),
51 source: Box::new(source),
52 }
53 })?;
54
55 request
56 .headers_mut()
57 .insert("X-API-Key", HeaderValue::from_str(&self.api_key)?);
58
59 let (stream, _) = tokio::time::timeout(self.connect_timeout, connect_async(request))
60 .await
61 .map_err(|_| BacktestClientError::Timeout {
62 action: "connecting",
63 duration: self.connect_timeout,
64 })?
65 .map_err(|source| BacktestClientError::Connect {
66 url: self.url.clone(),
67 source: Box::new(source),
68 })?;
69
70 let mut session = BacktestSession::new(stream, self.request_timeout, self.log_raw);
71 session
72 .create(params, http_base_from_ws_url(&self.url))
73 .await?;
74 Ok(session)
75 }
76}