ibapi/trace/
async.rs

1use crate::trace::common::{storage::async_ops, Interaction};
2
3/// Gets the last interaction with the server, if any
4///
5/// Returns `None` if no interactions have been recorded yet.
6///
7/// # Example
8/// ```no_run
9/// use ibapi::trace;
10///
11/// # async fn example() {
12/// if let Some(interaction) = trace::last_interaction().await {
13///     println!("Last request: {}", interaction.request);
14///     println!("Responses: {:?}", interaction.responses);
15/// }
16/// # }
17/// ```
18pub async fn last_interaction() -> Option<Interaction> {
19    async_ops::get_last_interaction().await.map(|arc| (*arc).clone())
20}
21
22/// Records a new request, starting a new interaction
23///
24/// This function starts tracking a new server interaction. Any subsequent
25/// calls to `record_response` will add responses to this interaction until
26/// a new request is recorded.
27///
28/// # Arguments
29/// * `message` - The request message being sent to the server
30///
31/// # Example
32/// ```no_run
33/// use ibapi::trace;
34///
35/// # async fn example() {
36/// trace::record_request("REQ|123|AAPL|".to_string()).await;
37/// # }
38/// ```
39pub async fn record_request(message: String) {
40    async_ops::start_new_interaction(message).await;
41}
42
43/// Records a response message for the current interaction
44///
45/// Adds a response to the most recent interaction started by `record_request`.
46/// If no interaction has been started, this function does nothing.
47///
48/// # Arguments
49/// * `message` - The response message received from the server
50///
51/// # Example
52/// ```no_run
53/// use ibapi::trace;
54///
55/// # async fn example() {
56/// trace::record_request("REQ|123|AAPL|".to_string()).await;
57/// trace::record_response("RESP|123|150.00|".to_string()).await;
58/// trace::record_response("RESP|123|151.00|".to_string()).await;
59/// # }
60/// ```
61pub async fn record_response(message: String) {
62    async_ops::add_response_to_current(message).await;
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68    use crate::trace::common::storage::async_ops;
69    use serial_test::serial;
70
71    #[tokio::test]
72    #[serial]
73    async fn test_no_interaction_initially() {
74        // Clear to ensure clean initial state
75        async_ops::clear().await;
76        assert!(last_interaction().await.is_none());
77    }
78
79    #[tokio::test]
80    #[serial]
81    async fn test_record_and_retrieve_interaction() {
82        // Record a request - this replaces any previous interaction
83        record_request("TEST_REQUEST".to_string()).await;
84
85        // Should be able to get it back
86        let interaction = last_interaction().await.expect("Should have interaction");
87        assert_eq!(interaction.request, "TEST_REQUEST");
88        assert_eq!(interaction.responses.len(), 0);
89    }
90
91    #[tokio::test]
92    #[serial]
93    async fn test_record_request_and_responses() {
94        // Record a request - this replaces any previous interaction
95        record_request("REQUEST_1".to_string()).await;
96
97        // Record some responses
98        record_response("RESPONSE_1".to_string()).await;
99        record_response("RESPONSE_2".to_string()).await;
100
101        // Check the interaction
102        let interaction = last_interaction().await.expect("Should have interaction");
103        assert_eq!(interaction.request, "REQUEST_1");
104        assert_eq!(interaction.responses.len(), 2);
105        assert_eq!(interaction.responses[0], "RESPONSE_1");
106        assert_eq!(interaction.responses[1], "RESPONSE_2");
107    }
108
109    #[tokio::test]
110    #[serial]
111    async fn test_new_request_replaces_old() {
112        // First interaction
113        record_request("REQUEST_1".to_string()).await;
114        record_response("RESPONSE_1".to_string()).await;
115
116        // Second interaction - this replaces the first
117        record_request("REQUEST_2".to_string()).await;
118        record_response("RESPONSE_2".to_string()).await;
119
120        // Should only have the second interaction
121        let interaction = last_interaction().await.expect("Should have interaction");
122        assert_eq!(interaction.request, "REQUEST_2");
123        assert_eq!(interaction.responses.len(), 1);
124        assert_eq!(interaction.responses[0], "RESPONSE_2");
125    }
126}