ironfix_store/traits.rs
1/******************************************************************************
2 Author: Joaquín Béjar García
3 Email: jb@taunais.com
4 Date: 27/1/26
5******************************************************************************/
6
7//! Message store trait definition.
8//!
9//! This module defines the abstract interface for message storage implementations.
10
11use async_trait::async_trait;
12use ironfix_core::error::StoreError;
13use ironfix_core::message::OwnedMessage;
14
15/// Abstract interface for FIX message storage.
16///
17/// Implementations of this trait provide persistence for outgoing messages
18/// to support resend requests and session recovery.
19#[async_trait]
20pub trait MessageStore: Send + Sync {
21 /// Stores an outgoing message for potential resend.
22 ///
23 /// # Arguments
24 /// * `seq_num` - The message sequence number
25 /// * `message` - The raw message bytes
26 ///
27 /// # Errors
28 /// Returns `StoreError` if the message cannot be stored.
29 async fn store(&self, seq_num: u64, message: &[u8]) -> Result<(), StoreError>;
30
31 /// Retrieves messages for a resend request.
32 ///
33 /// # Arguments
34 /// * `begin` - Begin sequence number (inclusive)
35 /// * `end` - End sequence number (inclusive, or 0 for infinity)
36 ///
37 /// # Returns
38 /// A vector of messages in the requested range.
39 ///
40 /// # Errors
41 /// Returns `StoreError` if messages cannot be retrieved.
42 async fn get_range(&self, begin: u64, end: u64) -> Result<Vec<OwnedMessage>, StoreError>;
43
44 /// Returns the next sender sequence number.
45 fn next_sender_seq(&self) -> u64;
46
47 /// Returns the next expected target sequence number.
48 fn next_target_seq(&self) -> u64;
49
50 /// Sets the next sender sequence number.
51 ///
52 /// # Arguments
53 /// * `seq` - The new sequence number
54 fn set_next_sender_seq(&self, seq: u64);
55
56 /// Sets the next expected target sequence number.
57 ///
58 /// # Arguments
59 /// * `seq` - The new sequence number
60 fn set_next_target_seq(&self, seq: u64);
61
62 /// Resets the store, clearing all messages and resetting sequence numbers.
63 ///
64 /// # Errors
65 /// Returns `StoreError` if the reset fails.
66 async fn reset(&self) -> Result<(), StoreError>;
67
68 /// Returns the creation time of the store/session.
69 fn creation_time(&self) -> std::time::SystemTime;
70
71 /// Refreshes the store from persistent storage.
72 ///
73 /// # Errors
74 /// Returns `StoreError` if the refresh fails.
75 async fn refresh(&self) -> Result<(), StoreError> {
76 Ok(())
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83
84 struct MockStore;
85
86 #[async_trait]
87 impl MessageStore for MockStore {
88 async fn store(&self, _seq_num: u64, _message: &[u8]) -> Result<(), StoreError> {
89 Ok(())
90 }
91
92 async fn get_range(&self, _begin: u64, _end: u64) -> Result<Vec<OwnedMessage>, StoreError> {
93 Ok(vec![])
94 }
95
96 fn next_sender_seq(&self) -> u64 {
97 1
98 }
99
100 fn next_target_seq(&self) -> u64 {
101 1
102 }
103
104 fn set_next_sender_seq(&self, _seq: u64) {}
105
106 fn set_next_target_seq(&self, _seq: u64) {}
107
108 async fn reset(&self) -> Result<(), StoreError> {
109 Ok(())
110 }
111
112 fn creation_time(&self) -> std::time::SystemTime {
113 std::time::SystemTime::now()
114 }
115 }
116
117 #[tokio::test]
118 async fn test_mock_store() {
119 let store = MockStore;
120 assert_eq!(store.next_sender_seq(), 1);
121 assert_eq!(store.next_target_seq(), 1);
122 assert!(store.store(1, b"test").await.is_ok());
123 assert!(store.reset().await.is_ok());
124 }
125}