1use std::sync::Arc;
5
6use actix_web::web::ThinData;
7
8use crate::{
9 jobs::{JobProducer, JobProducerTrait},
10 models::{
11 NetworkRepoModel, NotificationRepoModel, RelayerRepoModel, SignerRepoModel,
12 TransactionRepoModel,
13 },
14 repositories::{
15 ApiKeyRepositoryStorage, ApiKeyRepositoryTrait, NetworkRepository,
16 NetworkRepositoryStorage, NotificationRepositoryStorage, PluginRepositoryStorage,
17 PluginRepositoryTrait, RelayerRepository, RelayerRepositoryStorage, Repository,
18 SignerRepositoryStorage, TransactionCounterRepositoryStorage, TransactionCounterTrait,
19 TransactionRepository, TransactionRepositoryStorage,
20 },
21};
22
23#[derive(Debug)]
26pub struct AppState<
27 J: JobProducerTrait + Send + Sync + 'static,
28 RR: RelayerRepository + Repository<RelayerRepoModel, String> + Send + Sync + 'static,
29 TR: TransactionRepository + Repository<TransactionRepoModel, String> + Send + Sync + 'static,
30 NR: NetworkRepository + Repository<NetworkRepoModel, String> + Send + Sync + 'static,
31 NFR: Repository<NotificationRepoModel, String> + Send + Sync + 'static,
32 SR: Repository<SignerRepoModel, String> + Send + Sync + 'static,
33 TCR: TransactionCounterTrait + Send + Sync + 'static,
34 PR: PluginRepositoryTrait + Send + Sync + 'static,
35 AKR: ApiKeyRepositoryTrait + Send + Sync + 'static,
36> {
37 pub relayer_repository: Arc<RR>,
39 pub transaction_repository: Arc<TR>,
41 pub signer_repository: Arc<SR>,
43 pub notification_repository: Arc<NFR>,
45 pub network_repository: Arc<NR>,
47 pub transaction_counter_store: Arc<TCR>,
49 pub job_producer: Arc<J>,
51 pub plugin_repository: Arc<PR>,
53 pub api_key_repository: Arc<AKR>,
55}
56
57impl<J, RR, TR, NR, NFR, SR, TCR, PR, AKR> Clone for AppState<J, RR, TR, NR, NFR, SR, TCR, PR, AKR>
59where
60 J: JobProducerTrait + Send + Sync + 'static,
61 RR: RelayerRepository + Repository<RelayerRepoModel, String> + Send + Sync + 'static,
62 TR: TransactionRepository + Repository<TransactionRepoModel, String> + Send + Sync + 'static,
63 NR: NetworkRepository + Repository<NetworkRepoModel, String> + Send + Sync + 'static,
64 NFR: Repository<NotificationRepoModel, String> + Send + Sync + 'static,
65 SR: Repository<SignerRepoModel, String> + Send + Sync + 'static,
66 TCR: TransactionCounterTrait + Send + Sync + 'static,
67 PR: PluginRepositoryTrait + Send + Sync + 'static,
68 AKR: ApiKeyRepositoryTrait + Send + Sync + 'static,
69{
70 fn clone(&self) -> Self {
71 Self {
72 job_producer: Arc::clone(&self.job_producer),
73 relayer_repository: Arc::clone(&self.relayer_repository),
74 transaction_repository: Arc::clone(&self.transaction_repository),
75 signer_repository: Arc::clone(&self.signer_repository),
76 notification_repository: Arc::clone(&self.notification_repository),
77 network_repository: Arc::clone(&self.network_repository),
78 transaction_counter_store: Arc::clone(&self.transaction_counter_store),
79 plugin_repository: Arc::clone(&self.plugin_repository),
80 api_key_repository: Arc::clone(&self.api_key_repository),
81 }
82 }
83}
84
85pub type ThinDataAppState<J, RR, TR, NR, NFR, SR, TCR, PR, AKR> =
87 ThinData<AppState<J, RR, TR, NR, NFR, SR, TCR, PR, AKR>>;
88
89pub type DefaultAppState = AppState<
90 JobProducer,
91 RelayerRepositoryStorage,
92 TransactionRepositoryStorage,
93 NetworkRepositoryStorage,
94 NotificationRepositoryStorage,
95 SignerRepositoryStorage,
96 TransactionCounterRepositoryStorage,
97 PluginRepositoryStorage,
98 ApiKeyRepositoryStorage,
99>;
100
101impl<
102 J: JobProducerTrait,
103 RR: RelayerRepository + Repository<RelayerRepoModel, String> + Send + Sync + 'static,
104 TR: TransactionRepository + Repository<TransactionRepoModel, String> + Send + Sync + 'static,
105 NR: NetworkRepository + Repository<NetworkRepoModel, String> + Send + Sync + 'static,
106 NFR: Repository<NotificationRepoModel, String> + Send + Sync + 'static,
107 SR: Repository<SignerRepoModel, String> + Send + Sync + 'static,
108 TCR: TransactionCounterTrait + Send + Sync + 'static,
109 PR: PluginRepositoryTrait + Send + Sync + 'static,
110 AKR: ApiKeyRepositoryTrait + Send + Sync + 'static,
111 > AppState<J, RR, TR, NR, NFR, SR, TCR, PR, AKR>
112{
113 pub fn relayer_repository(&self) -> Arc<RR> {
119 self.relayer_repository.clone()
120 }
121
122 pub fn transaction_repository(&self) -> Arc<TR> {
128 Arc::clone(&self.transaction_repository)
129 }
130
131 pub fn signer_repository(&self) -> Arc<SR> {
137 Arc::clone(&self.signer_repository)
138 }
139
140 pub fn notification_repository(&self) -> Arc<NFR> {
146 Arc::clone(&self.notification_repository)
147 }
148
149 pub fn network_repository(&self) -> Arc<NR> {
155 Arc::clone(&self.network_repository)
156 }
157
158 pub fn transaction_counter_store(&self) -> Arc<TCR> {
164 Arc::clone(&self.transaction_counter_store)
165 }
166
167 pub fn job_producer(&self) -> Arc<J> {
173 Arc::clone(&self.job_producer)
174 }
175
176 pub fn plugin_repository(&self) -> Arc<PR> {
182 Arc::clone(&self.plugin_repository)
183 }
184
185 pub fn api_key_repository(&self) -> Arc<AKR> {
191 Arc::clone(&self.api_key_repository)
192 }
193}
194
195#[cfg(test)]
196mod tests {
197 use crate::{jobs::MockJobProducerTrait, repositories::TransactionRepositoryStorage};
198
199 use super::*;
200 use std::sync::Arc;
201
202 fn create_test_app_state() -> AppState<
203 MockJobProducerTrait,
204 RelayerRepositoryStorage,
205 TransactionRepositoryStorage,
206 NetworkRepositoryStorage,
207 NotificationRepositoryStorage,
208 SignerRepositoryStorage,
209 TransactionCounterRepositoryStorage,
210 PluginRepositoryStorage,
211 ApiKeyRepositoryStorage,
212 > {
213 let mut mock_job_producer = MockJobProducerTrait::new();
215
216 mock_job_producer
218 .expect_produce_transaction_request_job()
219 .returning(|_, _| Box::pin(async { Ok(()) }));
220
221 mock_job_producer
222 .expect_produce_submit_transaction_job()
223 .returning(|_, _| Box::pin(async { Ok(()) }));
224
225 mock_job_producer
226 .expect_produce_check_transaction_status_job()
227 .returning(|_, _| Box::pin(async { Ok(()) }));
228
229 mock_job_producer
230 .expect_produce_send_notification_job()
231 .returning(|_, _| Box::pin(async { Ok(()) }));
232
233 AppState {
234 relayer_repository: Arc::new(RelayerRepositoryStorage::new_in_memory()),
235 transaction_repository: Arc::new(TransactionRepositoryStorage::new_in_memory()),
236 signer_repository: Arc::new(SignerRepositoryStorage::new_in_memory()),
237 notification_repository: Arc::new(NotificationRepositoryStorage::new_in_memory()),
238 network_repository: Arc::new(NetworkRepositoryStorage::new_in_memory()),
239 transaction_counter_store: Arc::new(
240 TransactionCounterRepositoryStorage::new_in_memory(),
241 ),
242 job_producer: Arc::new(mock_job_producer),
243 plugin_repository: Arc::new(PluginRepositoryStorage::new_in_memory()),
244 api_key_repository: Arc::new(ApiKeyRepositoryStorage::new_in_memory()),
245 }
246 }
247
248 #[test]
249 fn test_relayer_repository_getter() {
250 let app_state = create_test_app_state();
251 let repo1 = app_state.relayer_repository();
252 let repo2 = app_state.relayer_repository();
253
254 assert!(Arc::ptr_eq(&repo1, &repo2));
256 assert!(Arc::ptr_eq(&repo1, &app_state.relayer_repository));
257 }
258
259 #[test]
260 fn test_transaction_repository_getter() {
261 let app_state = create_test_app_state();
262 let repo1 = app_state.transaction_repository();
263 let repo2 = app_state.transaction_repository();
264
265 assert!(Arc::ptr_eq(&repo1, &repo2));
266 assert!(Arc::ptr_eq(&repo1, &app_state.transaction_repository));
267 }
268
269 #[test]
270 fn test_signer_repository_getter() {
271 let app_state = create_test_app_state();
272 let repo1 = app_state.signer_repository();
273 let repo2 = app_state.signer_repository();
274
275 assert!(Arc::ptr_eq(&repo1, &repo2));
276 assert!(Arc::ptr_eq(&repo1, &app_state.signer_repository));
277 }
278
279 #[test]
280 fn test_notification_repository_getter() {
281 let app_state = create_test_app_state();
282 let repo1 = app_state.notification_repository();
283 let repo2 = app_state.notification_repository();
284
285 assert!(Arc::ptr_eq(&repo1, &repo2));
286 assert!(Arc::ptr_eq(&repo1, &app_state.notification_repository));
287 }
288
289 #[test]
290 fn test_transaction_counter_store_getter() {
291 let app_state = create_test_app_state();
292 let store1 = app_state.transaction_counter_store();
293 let store2 = app_state.transaction_counter_store();
294
295 assert!(Arc::ptr_eq(&store1, &store2));
296 assert!(Arc::ptr_eq(&store1, &app_state.transaction_counter_store));
297 }
298
299 #[test]
300 fn test_job_producer_getter() {
301 let app_state = create_test_app_state();
302 let producer1 = app_state.job_producer();
303 let producer2 = app_state.job_producer();
304
305 assert!(Arc::ptr_eq(&producer1, &producer2));
306 assert!(Arc::ptr_eq(&producer1, &app_state.job_producer));
307 }
308
309 #[test]
310 fn test_plugin_repository_getter() {
311 let app_state = create_test_app_state();
312 let store1 = app_state.plugin_repository();
313 let store2 = app_state.plugin_repository();
314
315 assert!(Arc::ptr_eq(&store1, &store2));
316 assert!(Arc::ptr_eq(&store1, &app_state.plugin_repository));
317 }
318
319 #[test]
320 fn test_api_key_repository_getter() {
321 let app_state = create_test_app_state();
322 let repo1 = app_state.api_key_repository();
323 let repo2 = app_state.api_key_repository();
324
325 assert!(Arc::ptr_eq(&repo1, &repo2));
326 assert!(Arc::ptr_eq(&repo1, &app_state.api_key_repository));
327 }
328}