1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
use std::collections::HashMap;
use std::iter::FromIterator;
use std::time::{Duration, SystemTime, UNIX_EPOCH};

use super::networker;
use super::types::{self, Message, PoolSetup, TimingResult};

mod base;
pub use base::{PoolRequest, PoolRequestImpl};

/// Assembled ledger transaction request
mod prepared_request;
pub use prepared_request::{PreparedRequest, RequestMethod};

/// Get a new unique request ID
pub fn new_request_id() -> i64 {
    SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .expect("Time has gone backwards")
        .as_nanos() as i64
}

/// Events received by `Request` instances as pending dispatches are resolved
#[derive(Debug)]
pub enum RequestEvent {
    Received(
        String,  // node alias
        String,  // message
        Message, // parsed
    ),
    Timeout(
        String, // node_alias
    ),
}

/// Extended request events produced by a `Networker` and processed by the event stream producer
#[derive(Debug)]
pub enum RequestExtEvent {
    Init,
    Sent(
        String,     // node alias
        SystemTime, // send time
    ),
    Received(
        String,     // node alias
        String,     // message
        Message,    // parsed
        SystemTime, // received time
    ),
    Timeout(
        String, // node_alias
    ),
}

/// Basic state enum for ledger transaction requests
#[derive(Debug, PartialEq, Eq)]
enum RequestState {
    NotStarted,
    Active,
    Terminated,
}

impl std::fmt::Display for RequestState {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let state = match self {
            Self::NotStarted => "NotStarted",
            Self::Active => "Active",
            Self::Terminated => "Terminated",
        };
        f.write_str(state)
    }
}

#[derive(Debug)]
pub(crate) struct RequestTiming {
    replies: HashMap<String, (SystemTime, f32)>,
}

impl RequestTiming {
    pub fn new() -> Self {
        Self {
            replies: HashMap::new(),
        }
    }

    pub fn sent(&mut self, node_alias: &str, send_time: SystemTime) {
        self.replies
            .insert(node_alias.to_owned(), (send_time, -1.0));
    }

    pub fn received(&mut self, node_alias: &str, recv_time: SystemTime) {
        if let Some(node) = self.replies.get_mut(node_alias) {
            let duration = recv_time
                .duration_since(node.0)
                .unwrap_or(Duration::new(0, 0))
                .as_secs_f32();
            node.1 = duration;
        }
    }

    pub fn result(&self) -> Option<TimingResult> {
        if self.replies.is_empty() {
            None
        } else {
            Some(HashMap::from_iter(
                self.replies.iter().map(|(k, (_, v))| (k.clone(), *v)),
            ))
        }
    }
}