openzeppelin_relayer/repositories/network/
mod.rs1use async_trait::async_trait;
22use redis::aio::ConnectionManager;
23use std::sync::Arc;
24
25mod network_in_memory;
26mod network_redis;
27
28pub use network_in_memory::InMemoryNetworkRepository;
29pub use network_redis::RedisNetworkRepository;
30
31use crate::models::{NetworkRepoModel, NetworkType, RepositoryError};
32use crate::repositories::{PaginatedResult, PaginationQuery, Repository};
33
34#[async_trait]
35pub trait NetworkRepository: Repository<NetworkRepoModel, String> {
36 async fn get_by_name(
38 &self,
39 network_type: NetworkType,
40 name: &str,
41 ) -> Result<Option<NetworkRepoModel>, RepositoryError>;
42
43 async fn get_by_chain_id(
45 &self,
46 network_type: NetworkType,
47 chain_id: u64,
48 ) -> Result<Option<NetworkRepoModel>, RepositoryError>;
49}
50
51#[derive(Debug, Clone)]
52pub enum NetworkRepositoryStorage {
53 InMemory(InMemoryNetworkRepository),
54 Redis(RedisNetworkRepository),
55}
56
57impl NetworkRepositoryStorage {
58 pub fn new_in_memory() -> Self {
59 Self::InMemory(InMemoryNetworkRepository::new())
60 }
61
62 pub fn new_redis(
63 connection_manager: Arc<ConnectionManager>,
64 key_prefix: String,
65 ) -> Result<Self, RepositoryError> {
66 let redis_repo = RedisNetworkRepository::new(connection_manager, key_prefix)?;
67 Ok(Self::Redis(redis_repo))
68 }
69}
70
71#[async_trait]
72impl Repository<NetworkRepoModel, String> for NetworkRepositoryStorage {
73 async fn create(&self, entity: NetworkRepoModel) -> Result<NetworkRepoModel, RepositoryError> {
74 match self {
75 NetworkRepositoryStorage::InMemory(repo) => repo.create(entity).await,
76 NetworkRepositoryStorage::Redis(repo) => repo.create(entity).await,
77 }
78 }
79
80 async fn get_by_id(&self, id: String) -> Result<NetworkRepoModel, RepositoryError> {
81 match self {
82 NetworkRepositoryStorage::InMemory(repo) => repo.get_by_id(id).await,
83 NetworkRepositoryStorage::Redis(repo) => repo.get_by_id(id).await,
84 }
85 }
86
87 async fn list_all(&self) -> Result<Vec<NetworkRepoModel>, RepositoryError> {
88 match self {
89 NetworkRepositoryStorage::InMemory(repo) => repo.list_all().await,
90 NetworkRepositoryStorage::Redis(repo) => repo.list_all().await,
91 }
92 }
93
94 async fn list_paginated(
95 &self,
96 query: PaginationQuery,
97 ) -> Result<PaginatedResult<NetworkRepoModel>, RepositoryError> {
98 match self {
99 NetworkRepositoryStorage::InMemory(repo) => repo.list_paginated(query).await,
100 NetworkRepositoryStorage::Redis(repo) => repo.list_paginated(query).await,
101 }
102 }
103
104 async fn update(
105 &self,
106 id: String,
107 entity: NetworkRepoModel,
108 ) -> Result<NetworkRepoModel, RepositoryError> {
109 match self {
110 NetworkRepositoryStorage::InMemory(repo) => repo.update(id, entity).await,
111 NetworkRepositoryStorage::Redis(repo) => repo.update(id, entity).await,
112 }
113 }
114
115 async fn delete_by_id(&self, id: String) -> Result<(), RepositoryError> {
116 match self {
117 NetworkRepositoryStorage::InMemory(repo) => repo.delete_by_id(id).await,
118 NetworkRepositoryStorage::Redis(repo) => repo.delete_by_id(id).await,
119 }
120 }
121
122 async fn count(&self) -> Result<usize, RepositoryError> {
123 match self {
124 NetworkRepositoryStorage::InMemory(repo) => repo.count().await,
125 NetworkRepositoryStorage::Redis(repo) => repo.count().await,
126 }
127 }
128
129 async fn has_entries(&self) -> Result<bool, RepositoryError> {
130 match self {
131 NetworkRepositoryStorage::InMemory(repo) => repo.has_entries().await,
132 NetworkRepositoryStorage::Redis(repo) => repo.has_entries().await,
133 }
134 }
135
136 async fn drop_all_entries(&self) -> Result<(), RepositoryError> {
137 match self {
138 NetworkRepositoryStorage::InMemory(repo) => repo.drop_all_entries().await,
139 NetworkRepositoryStorage::Redis(repo) => repo.drop_all_entries().await,
140 }
141 }
142}
143
144#[async_trait]
145impl NetworkRepository for NetworkRepositoryStorage {
146 async fn get_by_name(
147 &self,
148 network_type: NetworkType,
149 name: &str,
150 ) -> Result<Option<NetworkRepoModel>, RepositoryError> {
151 match self {
152 NetworkRepositoryStorage::InMemory(repo) => repo.get_by_name(network_type, name).await,
153 NetworkRepositoryStorage::Redis(repo) => repo.get_by_name(network_type, name).await,
154 }
155 }
156
157 async fn get_by_chain_id(
158 &self,
159 network_type: NetworkType,
160 chain_id: u64,
161 ) -> Result<Option<NetworkRepoModel>, RepositoryError> {
162 match self {
163 NetworkRepositoryStorage::InMemory(repo) => {
164 repo.get_by_chain_id(network_type, chain_id).await
165 }
166 NetworkRepositoryStorage::Redis(repo) => {
167 repo.get_by_chain_id(network_type, chain_id).await
168 }
169 }
170 }
171}
172
173#[cfg(test)]
174mockall::mock! {
175 pub NetworkRepository {}
176
177 #[async_trait]
178 impl Repository<NetworkRepoModel, String> for NetworkRepository {
179 async fn create(&self, entity: NetworkRepoModel) -> Result<NetworkRepoModel, RepositoryError>;
180 async fn get_by_id(&self, id: String) -> Result<NetworkRepoModel, RepositoryError>;
181 async fn list_all(&self) -> Result<Vec<NetworkRepoModel>, RepositoryError>;
182 async fn list_paginated(&self, query: PaginationQuery) -> Result<PaginatedResult<NetworkRepoModel>, RepositoryError>;
183 async fn update(&self, id: String, entity: NetworkRepoModel) -> Result<NetworkRepoModel, RepositoryError>;
184 async fn delete_by_id(&self, id: String) -> Result<(), RepositoryError>;
185 async fn count(&self) -> Result<usize, RepositoryError>;
186 async fn has_entries(&self) -> Result<bool, RepositoryError>;
187 async fn drop_all_entries(&self) -> Result<(), RepositoryError>;
188 }
189
190 #[async_trait]
191 impl NetworkRepository for NetworkRepository {
192 async fn get_by_name(&self, network_type: NetworkType, name: &str) -> Result<Option<NetworkRepoModel>, RepositoryError>;
193 async fn get_by_chain_id(&self, network_type: NetworkType, chain_id: u64) -> Result<Option<NetworkRepoModel>, RepositoryError>;
194 }
195}
196
197#[cfg(test)]
198mod tests {
199 use super::*;
200 use crate::utils::mocks::mockutils::create_mock_network;
201 #[tokio::test]
202 async fn test_trait_methods_accessibility() {
203 let repo: NetworkRepositoryStorage = NetworkRepositoryStorage::new_in_memory();
205
206 assert!(!repo.has_entries().await.unwrap());
208
209 let network = create_mock_network();
211 repo.create(network).await.unwrap();
212
213 assert!(repo.has_entries().await.unwrap());
215
216 repo.drop_all_entries().await.unwrap();
218
219 assert!(!repo.has_entries().await.unwrap());
221 assert_eq!(repo.count().await.unwrap(), 0);
222 }
223}