peillute/
message.rs

1//! Message handling for distributed transactions
2//!
3//! This module defines the message types and structures used for communication
4//! between nodes in the distributed system, including transaction messages,
5//! network control messages, and various financial operations.
6
7#[cfg(feature = "server")]
8/// Represents a financial transaction in the system
9#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
10pub struct Transaction {
11    /// Unique identifier for the transaction
12    pub id: u64,
13    /// ID of the user performing the transaction
14    pub user_id: String,
15    /// Transaction amount
16    pub amount: f64,
17    /// Description of the transaction
18    pub description: String,
19}
20
21#[cfg(feature = "server")]
22/// Types of network messages used for communication between nodes
23#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
24pub enum NetworkMessageCode {
25    /// Message for discovering other nodes in the network
26    Discovery,
27    /// Message containing a financial transaction
28    Transaction,
29    /// Message acknowledging receipt of a previous transaction
30    TransactionAcknowledgement,
31    /// Message acknowledging receipt of a previous message
32    Acknowledgment,
33    /// Message indicating an error condition
34    Error,
35    /// Message for gracefully disconnecting from the network
36    Disconnect,
37    /// Message requesting a state snapshot
38    SnapshotRequest,
39    /// Message containing a state snapshot
40    SnapshotResponse,
41    /// Request to acquire the global mutex
42    AcquireMutex,
43    /// Request to release the global mutex
44    ReleaseGlobalMutex,
45    /// Acknowledgment of the global mutex acquisition
46    AckGlobalMutex,
47    /// Acknowledgment of the global mutex acquisition
48    AckReleaseGlobalMutex,
49}
50
51#[cfg(feature = "server")]
52/// Represents a message exchanged between nodes in the network
53#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
54pub struct Message {
55    /// ID of the sending node
56    pub sender_id: String,
57    /// ID of the node that initiated the message
58    pub message_initiator_id: String,
59    /// Network address of the node that initiated the message
60    pub message_initiator_addr: std::net::SocketAddr,
61    /// Network address of the sending node
62    pub sender_addr: std::net::SocketAddr,
63    /// Logical clock state of the sending node
64    pub clock: crate::clock::Clock,
65    /// Optional command to be executed
66    pub command: Option<crate::control::Command>,
67    /// Message payload containing the actual data
68    pub info: MessageInfo,
69    /// Type of the message
70    pub code: NetworkMessageCode,
71}
72
73#[cfg(feature = "server")]
74/// Types of message payloads for different operations
75#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
76pub enum MessageInfo {
77    /// Acknowledgment of a new connection
78    Acknowledge(AcknowledgePayload),
79    /// Create a new user
80    CreateUser(CreateUser),
81    /// Deposit money into an account
82    Deposit(Deposit),
83    /// Withdraw money from an account
84    Withdraw(Withdraw),
85    /// Transfer money between accounts
86    Transfer(Transfer),
87    /// Make a payment
88    Pay(Pay),
89    /// Process a refund
90    Refund(Refund),
91    /// Response to a snapshot request
92    SnapshotResponse(SnapshotResponse),
93    /// Initiate a critical section
94    AcquireMutex(AcquireMutexPayload),
95    /// Release a critical section
96    ReleaseMutex(ReleaseMutexPayload),
97    /// Acknowledge a critical section
98    AckMutex(AckMutexPayload),
99    /// No payload
100    None,
101}
102
103#[cfg(feature = "server")]
104/// Payload for the AcquireMutex message
105#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
106pub struct AcknowledgePayload {
107    /// Logical clock state of the acknowledging node
108    pub global_fifo: std::collections::HashMap<String, crate::state::MutexStamp>,
109}
110
111#[cfg(feature = "server")]
112/// Payload for the AcquireMutex message
113#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
114pub struct AcquireMutexPayload;
115
116#[cfg(feature = "server")]
117/// Payload for the ReleaseMutex message
118#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
119#[cfg(feature = "server")]
120/// Payload for the AckMutex message
121pub struct ReleaseMutexPayload;
122
123#[cfg(feature = "server")]
124/// Payload for the AckMutex message
125#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)]
126pub struct AckMutexPayload {
127    pub clock: i64,
128}
129
130#[cfg(feature = "server")]
131/// Response to a state snapshot request
132#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
133pub struct SnapshotResponse {
134    /// ID of the responding node
135    pub site_id: String,
136    /// Logical clock state of the responding node
137    pub clock: crate::clock::Clock,
138    /// Transaction log summary
139    pub tx_log: Vec<crate::snapshot::TxSummary>,
140}
141
142#[cfg(feature = "server")]
143/// Request to create a new user
144#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
145pub struct CreateUser {
146    /// Name of the user to create
147    pub name: String,
148}
149
150#[cfg(feature = "server")]
151impl CreateUser {
152    /// Creates a new CreateUser request
153    pub fn new(name: String) -> Self {
154        Self { name }
155    }
156}
157
158#[cfg(feature = "server")]
159/// Request to deposit money into an account
160#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
161pub struct Deposit {
162    /// Name of the account
163    pub name: String,
164    /// Amount to deposit
165    pub amount: f64,
166}
167
168#[cfg(feature = "server")]
169impl Deposit {
170    /// Creates a new Deposit request
171    pub fn new(name: String, amount: f64) -> Self {
172        Self { name, amount }
173    }
174}
175
176#[cfg(feature = "server")]
177/// Request to withdraw money from an account
178#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
179pub struct Withdraw {
180    /// Name of the account
181    pub name: String,
182    /// Amount to withdraw
183    pub amount: f64,
184}
185
186#[cfg(feature = "server")]
187impl Withdraw {
188    /// Creates a new Withdraw request
189    pub fn new(name: String, amount: f64) -> Self {
190        Self { name, amount }
191    }
192}
193
194#[cfg(feature = "server")]
195/// Request to transfer money between accounts
196#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
197pub struct Transfer {
198    /// Name of the source account
199    pub name: String,
200    /// Name of the destination account
201    pub beneficiary: String,
202    /// Amount to transfer
203    pub amount: f64,
204}
205
206#[cfg(feature = "server")]
207impl Transfer {
208    /// Creates a new Transfer request
209    pub fn new(name: String, beneficiary: String, amount: f64) -> Self {
210        Self {
211            name,
212            beneficiary,
213            amount,
214        }
215    }
216}
217
218#[cfg(feature = "server")]
219/// Request to make a payment
220#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
221pub struct Pay {
222    /// Name of the account
223    pub name: String,
224    /// Amount to pay
225    pub amount: f64,
226}
227
228#[cfg(feature = "server")]
229impl Pay {
230    /// Creates a new Pay request
231    pub fn new(name: String, amount: f64) -> Self {
232        Self { name, amount }
233    }
234}
235
236#[cfg(feature = "server")]
237/// Request to process a refund
238#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
239pub struct Refund {
240    /// Name of the account
241    pub name: String,
242    /// Timestamp of the original transaction
243    pub transac_time: i64,
244    /// ID of the node that processed the original transaction
245    pub transac_node: String,
246}
247
248#[cfg(feature = "server")]
249impl Refund {
250    /// Creates a new Refund request
251    pub fn new(name: String, transac_time: i64, transac_node: String) -> Self {
252        Self {
253            name,
254            transac_time,
255            transac_node,
256        }
257    }
258}
259
260#[cfg(test)]
261#[cfg(feature = "server")]
262mod tests {
263    use super::*;
264
265    #[test]
266    fn test_transaction_debug() {
267        let transaction = Transaction {
268            id: 1,
269            user_id: "test_user".to_string(),
270            amount: 100.0,
271            description: "Test transaction".to_string(),
272        };
273        assert_eq!(
274            format!("{:?}", transaction),
275            "Transaction { id: 1, user_id: \"test_user\", amount: 100.0, description: \"Test transaction\" }"
276        );
277    }
278
279    #[test]
280    fn test_message_debug() {
281        let clock = crate::clock::Clock::new();
282
283        let message = Message {
284            sender_id: "A".to_string(),
285            sender_addr: "127.0.0.1:8080".parse().unwrap(),
286            message_initiator_id: "A".to_string(),
287            message_initiator_addr: "127.0.0.1:8080".parse().unwrap(),
288            clock: clock,
289            command: None,
290            info: MessageInfo::None,
291            code: NetworkMessageCode::Transaction,
292        };
293        assert!(format!("{:?}", message).contains("Message { sender_id: \"A\""));
294    }
295}