openzeppelin_relayer/models/
app_state.rs

1//! This module defines the `AppState` struct, which encapsulates the application's state.
2//! It includes various repositories and services necessary for the application's operation.
3//! The `AppState` provides methods to access these components in a thread-safe manner.
4use std::sync::Arc;
5
6use crate::{
7    jobs::{JobProducer, JobProducerTrait},
8    repositories::{
9        InMemoryNetworkRepository, InMemoryNotificationRepository, InMemoryPluginRepository,
10        InMemoryRelayerRepository, InMemorySignerRepository, InMemoryTransactionCounter,
11        InMemoryTransactionRepository, RelayerRepositoryStorage,
12    },
13};
14
15/// Represents the application state, holding various repositories and services
16/// required for the application's operation.
17#[derive(Clone, Debug)]
18pub struct AppState<J: JobProducerTrait> {
19    /// Repository for managing relayer data.
20    pub relayer_repository: Arc<RelayerRepositoryStorage<InMemoryRelayerRepository>>,
21    /// Repository for managing transaction data.
22    pub transaction_repository: Arc<InMemoryTransactionRepository>,
23    /// Repository for managing signer data.
24    pub signer_repository: Arc<InMemorySignerRepository>,
25    /// Repository for managing notification data.
26    pub notification_repository: Arc<InMemoryNotificationRepository>,
27    /// Repository for managing network data.
28    pub network_repository: Arc<InMemoryNetworkRepository>,
29    /// Store for managing transaction counters.
30    pub transaction_counter_store: Arc<InMemoryTransactionCounter>,
31    /// Producer for managing job creation and execution.
32    pub job_producer: Arc<J>,
33    /// Repository for managing plugins.
34    pub plugin_repository: Arc<InMemoryPluginRepository>,
35}
36
37pub type DefaultAppState = AppState<JobProducer>;
38
39impl<J: JobProducerTrait> AppState<J> {
40    /// Returns a clone of the relayer repository.
41    ///
42    /// # Returns
43    ///
44    /// An `Arc` pointing to the `RelayerRepositoryStorage`.
45    pub fn relayer_repository(&self) -> Arc<RelayerRepositoryStorage<InMemoryRelayerRepository>> {
46        Arc::clone(&self.relayer_repository)
47    }
48
49    /// Returns a clone of the transaction repository.
50    ///
51    /// # Returns
52    ///
53    /// An `Arc` pointing to the `InMemoryTransactionRepository`.
54    pub fn transaction_repository(&self) -> Arc<InMemoryTransactionRepository> {
55        Arc::clone(&self.transaction_repository)
56    }
57
58    /// Returns a clone of the signer repository.
59    ///
60    /// # Returns
61    ///
62    /// An `Arc` pointing to the `InMemorySignerRepository`.
63    pub fn signer_repository(&self) -> Arc<InMemorySignerRepository> {
64        Arc::clone(&self.signer_repository)
65    }
66
67    /// Returns a clone of the notification repository.
68    ///
69    /// # Returns
70    ///
71    /// An `Arc` pointing to the `InMemoryNotificationRepository`.
72    pub fn notification_repository(&self) -> Arc<InMemoryNotificationRepository> {
73        Arc::clone(&self.notification_repository)
74    }
75
76    /// Returns a clone of the network repository.
77    ///
78    /// # Returns
79    ///
80    /// An `Arc` pointing to the `InMemoryNetworkRepository`.
81    pub fn network_repository(&self) -> Arc<InMemoryNetworkRepository> {
82        Arc::clone(&self.network_repository)
83    }
84
85    /// Returns a clone of the transaction counter store.
86    ///
87    /// # Returns
88    ///
89    /// An `Arc` pointing to the `InMemoryTransactionCounter`.
90    pub fn transaction_counter_store(&self) -> Arc<InMemoryTransactionCounter> {
91        Arc::clone(&self.transaction_counter_store)
92    }
93
94    /// Returns a clone of the job producer.
95    ///
96    /// # Returns
97    ///
98    /// An `Arc` pointing to the `JobProducer`.
99    pub fn job_producer(&self) -> Arc<J> {
100        Arc::clone(&self.job_producer)
101    }
102
103    /// Returns a clone of the plugin repository.
104    ///
105    /// # Returns
106    ///
107    /// An `Arc` pointing to the `InMemoryPluginRepository`.
108    pub fn plugin_repository(&self) -> Arc<InMemoryPluginRepository> {
109        Arc::clone(&self.plugin_repository)
110    }
111}
112
113#[cfg(test)]
114mod tests {
115    use crate::jobs::MockJobProducerTrait;
116
117    use super::*;
118    use std::sync::Arc;
119
120    fn create_test_app_state() -> AppState<MockJobProducerTrait> {
121        // Create a mock job producer
122        let mut mock_job_producer = MockJobProducerTrait::new();
123
124        // Set up expectations for the mock
125        mock_job_producer
126            .expect_produce_transaction_request_job()
127            .returning(|_, _| Box::pin(async { Ok(()) }));
128
129        mock_job_producer
130            .expect_produce_submit_transaction_job()
131            .returning(|_, _| Box::pin(async { Ok(()) }));
132
133        mock_job_producer
134            .expect_produce_check_transaction_status_job()
135            .returning(|_, _| Box::pin(async { Ok(()) }));
136
137        mock_job_producer
138            .expect_produce_send_notification_job()
139            .returning(|_, _| Box::pin(async { Ok(()) }));
140
141        AppState {
142            relayer_repository: Arc::new(RelayerRepositoryStorage::in_memory(
143                InMemoryRelayerRepository::default(),
144            )),
145            transaction_repository: Arc::new(InMemoryTransactionRepository::default()),
146            signer_repository: Arc::new(InMemorySignerRepository::default()),
147            notification_repository: Arc::new(InMemoryNotificationRepository::default()),
148            network_repository: Arc::new(InMemoryNetworkRepository::default()),
149            transaction_counter_store: Arc::new(InMemoryTransactionCounter::default()),
150            job_producer: Arc::new(mock_job_producer),
151            plugin_repository: Arc::new(InMemoryPluginRepository::new()),
152        }
153    }
154
155    #[test]
156    fn test_relayer_repository_getter() {
157        let app_state = create_test_app_state();
158        let repo1 = app_state.relayer_repository();
159        let repo2 = app_state.relayer_repository();
160
161        // Verify that we get a new Arc pointing to the same underlying data
162        assert!(Arc::ptr_eq(&repo1, &repo2));
163        assert!(Arc::ptr_eq(&repo1, &app_state.relayer_repository));
164    }
165
166    #[test]
167    fn test_transaction_repository_getter() {
168        let app_state = create_test_app_state();
169        let repo1 = app_state.transaction_repository();
170        let repo2 = app_state.transaction_repository();
171
172        assert!(Arc::ptr_eq(&repo1, &repo2));
173        assert!(Arc::ptr_eq(&repo1, &app_state.transaction_repository));
174    }
175
176    #[test]
177    fn test_signer_repository_getter() {
178        let app_state = create_test_app_state();
179        let repo1 = app_state.signer_repository();
180        let repo2 = app_state.signer_repository();
181
182        assert!(Arc::ptr_eq(&repo1, &repo2));
183        assert!(Arc::ptr_eq(&repo1, &app_state.signer_repository));
184    }
185
186    #[test]
187    fn test_notification_repository_getter() {
188        let app_state = create_test_app_state();
189        let repo1 = app_state.notification_repository();
190        let repo2 = app_state.notification_repository();
191
192        assert!(Arc::ptr_eq(&repo1, &repo2));
193        assert!(Arc::ptr_eq(&repo1, &app_state.notification_repository));
194    }
195
196    #[test]
197    fn test_transaction_counter_store_getter() {
198        let app_state = create_test_app_state();
199        let store1 = app_state.transaction_counter_store();
200        let store2 = app_state.transaction_counter_store();
201
202        assert!(Arc::ptr_eq(&store1, &store2));
203        assert!(Arc::ptr_eq(&store1, &app_state.transaction_counter_store));
204    }
205
206    #[test]
207    fn test_job_producer_getter() {
208        let app_state = create_test_app_state();
209        let producer1 = app_state.job_producer();
210        let producer2 = app_state.job_producer();
211
212        assert!(Arc::ptr_eq(&producer1, &producer2));
213        assert!(Arc::ptr_eq(&producer1, &app_state.job_producer));
214    }
215
216    #[test]
217    fn test_plugin_repository_getter() {
218        let app_state = create_test_app_state();
219        let store1 = app_state.plugin_repository();
220        let store2 = app_state.plugin_repository();
221
222        assert!(Arc::ptr_eq(&store1, &store2));
223        assert!(Arc::ptr_eq(&store1, &app_state.plugin_repository));
224    }
225}