Skip to main content

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}