forester_http/
client.rs

1use crate::api::ForesterHttpApi;
2use reqwest::Response;
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5use std::time::Duration;
6
7/// the client to the Forester instance of http server
8/// It accepts the api and timeout to request
9///
10/// ```no-run
11/// use forester_http::client::ForesterHttpClient;
12///
13/// async fn main() {
14///     let client = ForesterHttpClient::new("http://localhost:10000".to_string());
15///     client.new_trace_event(1, "test".to_string());
16/// }
17///
18/// ```
19pub struct ForesterHttpClient {
20    api: ForesterHttpApi,
21    timeout: Option<Duration>,
22}
23
24impl ForesterHttpClient {
25    pub fn new(base: String) -> Self {
26        let api = ForesterHttpApi::new(base);
27        Self { api, timeout: None }
28    }
29    pub async fn new_with(base: String, timeout: Duration) -> Self {
30        let api = ForesterHttpApi::new(base);
31        Self {
32            api,
33            timeout: Some(timeout),
34        }
35    }
36
37    /// creates a new trace event
38    pub async fn new_trace_event(&self, tick: usize, text: String) -> Result<Response, TickError> {
39        Ok(self
40            .client()?
41            .post(&self.api.trace_event())
42            .json(&CustomEvent { text, tick })
43            .send()
44            .await?)
45    }
46    /// prints the trace or if the file is big the tail of the trace (last 100 lines)
47    pub async fn print_trace(&self) -> Result<Response, TickError> {
48        Ok(self.client()?.get(&self.api.print_trace()).send().await?)
49    }
50    /// lock the key in the blackboard
51    pub async fn lock(&self, id: String) -> Result<Response, TickError> {
52        Ok(self.client()?.get(&self.api.lock(id)).send().await?)
53    }
54    /// unlock the key in the blackboard
55    pub async fn unlock(&self, id: String) -> Result<Response, TickError> {
56        Ok(self.client()?.get(&self.api.unlock(id)).send().await?)
57    }
58    /// check if the key is locked in the blackboard
59    pub async fn locked(&self, id: String) -> Result<Response, TickError> {
60        Ok(self.client()?.get(&self.api.locked(id)).send().await?)
61    }
62    /// check if the key is in the blackboard
63    pub async fn contains(&self, id: String) -> Result<Response, TickError> {
64        Ok(self.client()?.get(&self.api.contains(id)).send().await?)
65    }
66    /// take the key from the blackboard.
67    pub async fn take(&self, id: String) -> Result<Response, TickError> {
68        Ok(self.client()?.get(&self.api.take(id)).send().await?)
69    }
70    /// get the key from the blackboard.
71    pub async fn get(&self, id: String) -> Result<Response, TickError> {
72        Ok(self.client()?.get(&self.api.get(id)).send().await?)
73    }
74    /// put the key to the blackboard.
75    pub async fn put(&self, id: String, value: Value) -> Result<Response, TickError> {
76        Ok(self
77            .client()?
78            .post(&self.api.put(id))
79            .json(&value)
80            .send()
81            .await?)
82    }
83
84    fn client(&self) -> Result<reqwest::Client, TickError> {
85        match self.timeout {
86            Some(timeout) => Ok(reqwest::Client::builder().timeout(timeout).build()?),
87            None => Ok(reqwest::Client::new()),
88        }
89    }
90}
91
92/// Error
93#[derive(Debug)]
94pub struct TickError {
95    pub message: String,
96}
97
98impl From<reqwest::Error> for TickError {
99    fn from(value: reqwest::Error) -> Self {
100        Self::new(format!("{:?}", value))
101    }
102}
103
104impl TickError {
105    pub fn new(message: String) -> Self {
106        Self { message }
107    }
108}
109
110/// The event that will be recorded to tracer
111#[derive(Debug, Deserialize, Serialize)]
112pub struct CustomEvent {
113    text: String,
114    tick: usize,
115}
116
117#[cfg(test)]
118mod tests {
119    use super::*;
120    use crate::client::ForesterHttpClient;
121
122    #[test]
123    fn trace_event_then_print_event() {
124        let client = ForesterHttpClient::new("http://localhost:10000".to_string());
125        let resp = client.new_trace_event(1, "test".to_string()).unwrap();
126        assert_eq!(resp.status(), 200);
127        let resp = client.print_trace().unwrap();
128        assert_eq!(resp.status(), 200);
129        let text = resp.text().unwrap();
130        assert_eq!("[1]custom: test\r\n", text)
131    }
132}