nullnet_libdatastore/client.rs
1use crate::datastore::store_service_client::StoreServiceClient;
2use crate::utils::{authorize_request, validate_response_and_convert_to_reponse_data};
3use crate::{datastore::*, DatastoreConfig, ResponseData};
4use nullnet_liberror::{location, Error, ErrorHandler, Location};
5use tonic::transport::{Channel, ClientTlsConfig};
6
7/// A client for interacting with the datastore service.
8#[derive(Debug, Clone)]
9pub struct DatastoreClient {
10 /// Configuration for connecting to the datastore.
11 config: DatastoreConfig,
12}
13
14impl DatastoreClient {
15 /// Creates a new instance of `DatastoreClient`.
16 ///
17 /// # Arguments
18 /// * `config` - The configuration settings for connecting to the datastore.
19 #[must_use]
20 pub fn new(config: DatastoreConfig) -> Self {
21 Self { config }
22 }
23
24 /// Establishes a connection to the datastore service.
25 ///
26 /// # Returns
27 /// * `Ok(StoreServiceClient<Channel>)` - The client for interacting with the datastore service.
28 /// * `Err(Error)` - If the connection fails.
29 async fn connect(&self) -> Result<StoreServiceClient<Channel>, Error> {
30 let protocol = if self.config.tls { "https" } else { "http" };
31 let host = self.config.host.as_str();
32 let port = self.config.port;
33
34 let mut endpoint = Channel::from_shared(format!("{protocol}://{host}:{port}"))
35 .handle_err(location!())?
36 .connect_timeout(std::time::Duration::from_secs(10));
37
38 if self.config.tls {
39 endpoint = endpoint
40 .tls_config(ClientTlsConfig::new().with_native_roots())
41 .handle_err(location!())?;
42 }
43
44 let channel: Channel = endpoint.connect().await.handle_err(location!())?;
45
46 Ok(StoreServiceClient::new(channel))
47 }
48
49 /// Logs in to the datastore service with the provided request.
50 ///
51 /// # Arguments
52 /// * `request` - The login request containing the necessary credentials.
53 ///
54 /// # Returns
55 /// * `Ok(LoginResponse)` - The response received after a successful login.
56 /// * `Err(Error)` - If the login fails or if an error occurs during the process.
57 #[allow(clippy::missing_errors_doc)]
58 pub async fn login(&self, request: LoginRequest) -> Result<LoginResponse, Error> {
59 let mut client_inner = self.connect().await?;
60
61 let response = client_inner.login(request).await.handle_err(location!())?;
62
63 Ok(response.into_inner())
64 }
65
66 /// Creates multiple records in the datastore with the provided request.
67 ///
68 /// # Arguments
69 /// * `request` - The batch create request containing the records to be created.
70 /// * `token` - The authorization token to authorize the request.
71 ///
72 /// # Returns
73 /// * `Ok(ResponseData)` - The response data containing the result of the operation.
74 /// * `Err(Error)` - If the operation fails or if an error occurs during the process.
75 #[allow(clippy::missing_errors_doc)]
76 pub async fn batch_create(
77 &self,
78 request: BatchCreateRequest,
79 token: &str,
80 ) -> Result<ResponseData, Error> {
81 let mut client_inner = self.connect().await?;
82 let request = authorize_request(request, token)?;
83
84 let response = client_inner
85 .batch_create(request)
86 .await
87 .handle_err(location!())?;
88
89 validate_response_and_convert_to_reponse_data(response.into_inner())
90 }
91
92 /// Creates a single record in the datastore with the provided request.
93 ///
94 /// # Arguments
95 /// * `request` - The create request containing the record to be created.
96 /// * `token` - The authorization token to authorize the request.
97 ///
98 /// # Returns
99 /// * `Ok(ResponseData)` - The response data containing the result of the operation.
100 /// * `Err(Error)` - If the operation fails or if an error occurs during the process.
101 #[allow(clippy::missing_errors_doc)]
102 pub async fn create(&self, request: CreateRequest, token: &str) -> Result<ResponseData, Error> {
103 let mut client_inner = self.connect().await?;
104 let request = authorize_request(request, token)?;
105
106 let response = client_inner.create(request).await.handle_err(location!())?;
107
108 validate_response_and_convert_to_reponse_data(response.into_inner())
109 }
110
111 /// Deletes a record from the datastore with the provided request.
112 ///
113 /// # Arguments
114 /// * `request` - The delete request containing the identifier of the record to be deleted.
115 /// * `token` - The authorization token to authorize the request.
116 ///
117 /// # Returns
118 /// * `Ok(ResponseData)` - The response data containing the result of the operation.
119 /// * `Err(Error)` - If the operation fails or if an error occurs during the process.
120 #[allow(clippy::missing_errors_doc)]
121 pub async fn delete(&self, request: DeleteRequest, token: &str) -> Result<ResponseData, Error> {
122 let mut client_inner = self.connect().await?;
123 let request = authorize_request(request, token)?;
124
125 let response = client_inner.delete(request).await.handle_err(location!())?;
126
127 validate_response_and_convert_to_reponse_data(response.into_inner())
128 }
129
130 /// Deletes multiple records from the datastore with the provided request.
131 ///
132 /// # Arguments
133 /// * `request` - The batch delete request containing the identifiers of the records to be deleted.
134 /// * `token` - The authorization token to authorize the request.
135 ///
136 /// # Returns
137 /// * `Ok(ResponseData)` - The response data containing the result of the operation.
138 /// * `Err(Error)` - If the operation fails or if an error occurs during the process.
139 #[allow(clippy::missing_errors_doc)]
140 pub async fn batch_delete(
141 &self,
142 request: BatchDeleteRequest,
143 token: &str,
144 ) -> Result<ResponseData, Error> {
145 let mut client_inner = self.connect().await?;
146 let request = authorize_request(request, token)?;
147
148 let response = client_inner
149 .batch_delete(request)
150 .await
151 .handle_err(location!())?;
152
153 validate_response_and_convert_to_reponse_data(response.into_inner())
154 }
155
156 /// Updates a record in the datastore with the provided request.
157 ///
158 /// # Arguments
159 /// * `request` - The update request containing the record's updated data.
160 /// * `token` - The authorization token to authorize the request.
161 ///
162 /// # Returns
163 /// * `Ok(ResponseData)` - The response data containing the result of the operation.
164 /// * `Err(Error)` - If the operation fails or if an error occurs during the process.
165 #[allow(clippy::missing_errors_doc)]
166 pub async fn update(&self, request: UpdateRequest, token: &str) -> Result<ResponseData, Error> {
167 let mut client_inner = self.connect().await?;
168 let request = authorize_request(request, token)?;
169
170 let response = client_inner.update(request).await.handle_err(location!())?;
171
172 validate_response_and_convert_to_reponse_data(response.into_inner())
173 }
174
175 /// Updates multiple records in the datastore with the provided request.
176 ///
177 /// # Arguments
178 /// * `request` - The batch update request containing the updated data for multiple records.
179 /// * `token` - The authorization token to authorize the request.
180 ///
181 /// # Returns
182 /// * `Ok(ResponseData)` - The response data containing the result of the operation.
183 /// * `Err(Error)` - If the operation fails or if an error occurs during the process.
184 #[allow(clippy::missing_errors_doc)]
185 pub async fn batch_update(
186 &self,
187 request: BatchUpdateRequest,
188 token: &str,
189 ) -> Result<ResponseData, Error> {
190 let mut client_inner = self.connect().await?;
191 let request = authorize_request(request, token)?;
192
193 let response = client_inner
194 .batch_update(request)
195 .await
196 .handle_err(location!())?;
197
198 validate_response_and_convert_to_reponse_data(response.into_inner())
199 }
200
201 /// Retrieves records from the datastore based on the specified filter.
202 ///
203 /// # Arguments
204 /// * `request` - The request containing the filter criteria.
205 /// * `token` - The authorization token to authorize the request.
206 ///
207 /// # Returns
208 /// * `Ok(ResponseData)` - The response data containing the records that match the filter.
209 /// * `Err(Error)` - If the operation fails or if an error occurs during the process.
210 #[allow(clippy::missing_errors_doc)]
211 pub async fn get_by_filter(
212 &self,
213 request: GetByFilterRequest,
214 token: &str,
215 ) -> Result<ResponseData, Error> {
216 let mut client_inner = self.connect().await?;
217 let request = authorize_request(request, token)?;
218
219 let response = client_inner
220 .get_by_filter(request)
221 .await
222 .handle_err(location!())?;
223
224 validate_response_and_convert_to_reponse_data(response.into_inner())
225 }
226
227 /// Performs aggregation on records in the datastore based on the provided request.
228 ///
229 /// # Arguments
230 /// * `request` - The aggregation request specifying the criteria for aggregation.
231 /// * `token` - The authorization token to authorize the request.
232 ///
233 /// # Returns
234 /// * `Ok(ResponseData)` - The response data containing the result of the aggregation.
235 /// * `Err(Error)` - If the operation fails or if an error occurs during the process.
236 #[allow(clippy::missing_errors_doc)]
237 pub async fn aggregate(
238 &self,
239 request: AggregateRequest,
240 token: &str,
241 ) -> Result<ResponseData, Error> {
242 let mut client_inner = self.connect().await?;
243 let request = authorize_request(request, token)?;
244
245 let response = client_inner
246 .aggregate(request)
247 .await
248 .handle_err(location!())?;
249
250 validate_response_and_convert_to_reponse_data(response.into_inner())
251 }
252
253 /// Retrieves a record from the datastore by its identifier.
254 ///
255 /// # Arguments
256 /// * `request` - The request containing the identifier of the record to be retrieved.
257 /// * `token` - The authorization token to authorize the request.
258 ///
259 /// # Returns
260 /// * `Ok(ResponseData)` - The response data containing the requested record.
261 /// * `Err(Error)` - If the operation fails or if an error occurs during the process.
262 #[allow(clippy::missing_errors_doc)]
263 pub async fn get_by_id(
264 &self,
265 request: GetByIdRequest,
266 token: &str,
267 ) -> Result<ResponseData, Error> {
268 let mut client_inner = self.connect().await?;
269 let request = authorize_request(request, token)?;
270
271 let response = client_inner
272 .get_by_id(request)
273 .await
274 .handle_err(location!())?;
275
276 validate_response_and_convert_to_reponse_data(response.into_inner())
277 }
278}