batata_client/api/
remote.rs

1use std::collections::HashMap;
2
3use prost_types::Any;
4use serde::{Deserialize, Serialize};
5
6use crate::api::{Metadata, Payload};
7use crate::common::constants::INTERNAL_MODULE;
8
9/// Base trait for all request types
10pub trait RequestTrait {
11    /// Get request headers
12    fn headers(&self) -> HashMap<String, String>;
13
14    /// Get request type identifier
15    fn request_type(&self) -> &'static str {
16        ""
17    }
18
19    /// Serialize request body to bytes
20    fn body(&self) -> Vec<u8>
21    where
22        Self: Serialize,
23    {
24        serde_json::to_vec(self).unwrap_or_default()
25    }
26
27    /// Insert headers into the request
28    fn insert_headers(&mut self, headers: HashMap<String, String>);
29
30    /// Get unique request identifier
31    fn request_id(&self) -> String {
32        String::default()
33    }
34
35    /// Convert to gRPC Payload
36    fn to_payload(&self, client_ip: &str) -> Payload
37    where
38        Self: Serialize,
39    {
40        let mut headers = self.headers();
41        headers.insert("requestId".to_string(), self.request_id());
42
43        Payload {
44            metadata: Some(Metadata {
45                r#type: self.request_type().to_string(),
46                client_ip: client_ip.to_string(),
47                headers,
48            }),
49            body: Some(Any {
50                type_url: String::new(),
51                value: self.body(),
52            }),
53        }
54    }
55
56    /// Deserialize request from gRPC payload
57    fn from_payload<T>(value: &Payload) -> T
58    where
59        T: for<'a> Deserialize<'a> + Default,
60    {
61        value
62            .body
63            .as_ref()
64            .and_then(|body| serde_json::from_slice::<T>(&body.value).ok())
65            .unwrap_or_default()
66    }
67}
68
69/// Base trait for all response types
70pub trait ResponseTrait {
71    /// Get response type identifier
72    fn response_type(&self) -> &'static str {
73        ""
74    }
75
76    /// Set request identifier for correlation
77    fn set_request_id(&mut self, request_id: String);
78
79    /// Get error code (default: success)
80    fn error_code(&self) -> i32 {
81        ResponseCode::Success.code()
82    }
83
84    /// Get result code indicating operation status
85    fn result_code(&self) -> i32;
86
87    /// Get response message
88    fn message(&self) -> String {
89        String::default()
90    }
91
92    /// Check if response indicates success
93    fn is_success(&self) -> bool {
94        self.result_code() == ResponseCode::Success.code()
95    }
96}
97
98/// Response status codes
99#[derive(Debug, Clone, Copy, PartialEq, Eq)]
100pub enum ResponseCode {
101    Success = 200,
102    Fail = 500,
103}
104
105impl ResponseCode {
106    pub fn code(&self) -> i32 {
107        *self as i32
108    }
109
110    pub fn desc(&self) -> &'static str {
111        match self {
112            ResponseCode::Success => "Response ok",
113            ResponseCode::Fail => "Response fail",
114        }
115    }
116}
117
118/// Client capabilities information
119#[derive(Clone, Debug, Default, Serialize, Deserialize)]
120#[serde(rename_all = "camelCase")]
121pub struct ClientAbilities {}
122
123/// Base request structure
124#[derive(Clone, Debug, Default, Serialize, Deserialize)]
125#[serde(rename_all = "camelCase")]
126pub struct Request {
127    #[serde(skip)]
128    pub headers: HashMap<String, String>,
129    pub request_id: String,
130}
131
132impl Request {
133    pub fn new() -> Self {
134        Self {
135            headers: HashMap::new(),
136            request_id: crate::common::generate_request_id(),
137        }
138    }
139}
140
141impl RequestTrait for Request {
142    fn headers(&self) -> HashMap<String, String> {
143        self.headers.clone()
144    }
145
146    fn insert_headers(&mut self, headers: HashMap<String, String>) {
147        self.headers.extend(headers);
148    }
149
150    fn request_id(&self) -> String {
151        self.request_id.clone()
152    }
153}
154
155/// Internal request with module information
156#[derive(Clone, Debug, Default, Serialize, Deserialize)]
157#[serde(rename_all = "camelCase")]
158pub struct InternalRequest {
159    #[serde(flatten)]
160    pub request: Request,
161    pub module: String,
162}
163
164impl InternalRequest {
165    pub fn new() -> Self {
166        Self {
167            request: Request::new(),
168            module: INTERNAL_MODULE.to_string(),
169        }
170    }
171}
172
173impl RequestTrait for InternalRequest {
174    fn headers(&self) -> HashMap<String, String> {
175        self.request.headers()
176    }
177
178    fn insert_headers(&mut self, headers: HashMap<String, String>) {
179        self.request.insert_headers(headers);
180    }
181
182    fn request_id(&self) -> String {
183        self.request.request_id.clone()
184    }
185}
186
187/// Base response structure
188#[derive(Clone, Debug, Default, Serialize, Deserialize)]
189#[serde(rename_all = "camelCase")]
190pub struct Response {
191    pub result_code: i32,
192    pub error_code: i32,
193    pub success: bool,
194    pub message: String,
195    pub request_id: String,
196}
197
198impl Response {
199    pub fn new() -> Self {
200        Self {
201            result_code: ResponseCode::Success.code(),
202            success: true,
203            ..Default::default()
204        }
205    }
206}
207
208impl ResponseTrait for Response {
209    fn set_request_id(&mut self, request_id: String) {
210        self.request_id = request_id;
211    }
212
213    fn error_code(&self) -> i32 {
214        self.error_code
215    }
216
217    fn result_code(&self) -> i32 {
218        self.result_code
219    }
220
221    fn message(&self) -> String {
222        self.message.clone()
223    }
224}
225
226// ==================== Connection Setup ====================
227
228/// Connection setup request
229#[derive(Clone, Debug, Default, Serialize, Deserialize)]
230#[serde(rename_all = "camelCase")]
231pub struct ConnectionSetupRequest {
232    #[serde(flatten)]
233    pub internal_request: InternalRequest,
234    pub client_version: String,
235    pub tenant: String,
236    pub labels: HashMap<String, String>,
237    pub client_abilities: ClientAbilities,
238}
239
240impl ConnectionSetupRequest {
241    pub fn new() -> Self {
242        Self {
243            internal_request: InternalRequest::new(),
244            client_version: crate::common::CLIENT_VERSION.to_string(),
245            labels: HashMap::new(),
246            ..Default::default()
247        }
248    }
249
250    pub fn with_labels(mut self, labels: HashMap<String, String>) -> Self {
251        self.labels = labels;
252        self
253    }
254
255    pub fn with_tenant(mut self, tenant: String) -> Self {
256        self.tenant = tenant;
257        self
258    }
259}
260
261impl RequestTrait for ConnectionSetupRequest {
262    fn headers(&self) -> HashMap<String, String> {
263        self.internal_request.headers()
264    }
265
266    fn request_type(&self) -> &'static str {
267        "ConnectionSetupRequest"
268    }
269
270    fn insert_headers(&mut self, headers: HashMap<String, String>) {
271        self.internal_request.insert_headers(headers);
272    }
273
274    fn request_id(&self) -> String {
275        self.internal_request.request_id()
276    }
277}
278
279// ==================== Server Check ====================
280
281/// Server check request
282#[derive(Clone, Debug, Default, Serialize, Deserialize)]
283#[serde(rename_all = "camelCase")]
284pub struct ServerCheckRequest {
285    #[serde(flatten)]
286    pub internal_request: InternalRequest,
287}
288
289impl ServerCheckRequest {
290    pub fn new() -> Self {
291        Self {
292            internal_request: InternalRequest::new(),
293        }
294    }
295}
296
297impl RequestTrait for ServerCheckRequest {
298    fn headers(&self) -> HashMap<String, String> {
299        self.internal_request.headers()
300    }
301
302    fn request_type(&self) -> &'static str {
303        "ServerCheckRequest"
304    }
305
306    fn insert_headers(&mut self, headers: HashMap<String, String>) {
307        self.internal_request.insert_headers(headers);
308    }
309
310    fn request_id(&self) -> String {
311        self.internal_request.request_id()
312    }
313}
314
315/// Server check response
316#[derive(Clone, Debug, Default, Serialize, Deserialize)]
317#[serde(rename_all = "camelCase")]
318pub struct ServerCheckResponse {
319    #[serde(flatten)]
320    pub response: Response,
321    pub connection_id: String,
322    pub support_ability_negotiation: bool,
323}
324
325impl ResponseTrait for ServerCheckResponse {
326    fn response_type(&self) -> &'static str {
327        "ServerCheckResponse"
328    }
329
330    fn set_request_id(&mut self, request_id: String) {
331        self.response.request_id = request_id;
332    }
333
334    fn error_code(&self) -> i32 {
335        self.response.error_code
336    }
337
338    fn result_code(&self) -> i32 {
339        self.response.result_code
340    }
341
342    fn message(&self) -> String {
343        self.response.message.clone()
344    }
345}
346
347// ==================== Health Check ====================
348
349/// Health check request
350#[derive(Clone, Debug, Default, Serialize, Deserialize)]
351#[serde(rename_all = "camelCase")]
352pub struct HealthCheckRequest {
353    #[serde(flatten)]
354    pub internal_request: InternalRequest,
355}
356
357impl HealthCheckRequest {
358    pub fn new() -> Self {
359        Self {
360            internal_request: InternalRequest::new(),
361        }
362    }
363}
364
365impl RequestTrait for HealthCheckRequest {
366    fn headers(&self) -> HashMap<String, String> {
367        self.internal_request.headers()
368    }
369
370    fn request_type(&self) -> &'static str {
371        "HealthCheckRequest"
372    }
373
374    fn insert_headers(&mut self, headers: HashMap<String, String>) {
375        self.internal_request.insert_headers(headers);
376    }
377
378    fn request_id(&self) -> String {
379        self.internal_request.request_id()
380    }
381}
382
383/// Health check response
384#[derive(Clone, Debug, Default, Serialize, Deserialize)]
385#[serde(rename_all = "camelCase")]
386pub struct HealthCheckResponse {
387    #[serde(flatten)]
388    pub response: Response,
389}
390
391impl ResponseTrait for HealthCheckResponse {
392    fn response_type(&self) -> &'static str {
393        "HealthCheckResponse"
394    }
395
396    fn set_request_id(&mut self, request_id: String) {
397        self.response.request_id = request_id;
398    }
399
400    fn error_code(&self) -> i32 {
401        self.response.error_code
402    }
403
404    fn result_code(&self) -> i32 {
405        self.response.result_code
406    }
407}
408
409// ==================== Client Detection ====================
410
411/// Client detection request (sent by server)
412#[derive(Clone, Debug, Default, Serialize, Deserialize)]
413#[serde(rename_all = "camelCase")]
414pub struct ClientDetectionRequest {
415    #[serde(flatten)]
416    pub internal_request: InternalRequest,
417}
418
419impl RequestTrait for ClientDetectionRequest {
420    fn headers(&self) -> HashMap<String, String> {
421        self.internal_request.headers()
422    }
423
424    fn request_type(&self) -> &'static str {
425        "ClientDetectionRequest"
426    }
427
428    fn insert_headers(&mut self, headers: HashMap<String, String>) {
429        self.internal_request.insert_headers(headers);
430    }
431
432    fn request_id(&self) -> String {
433        self.internal_request.request_id()
434    }
435}
436
437/// Client detection response
438#[derive(Clone, Debug, Default, Serialize, Deserialize)]
439#[serde(rename_all = "camelCase")]
440pub struct ClientDetectionResponse {
441    #[serde(flatten)]
442    pub response: Response,
443}
444
445impl ClientDetectionResponse {
446    pub fn new() -> Self {
447        Self {
448            response: Response::new(),
449        }
450    }
451}
452
453impl ResponseTrait for ClientDetectionResponse {
454    fn response_type(&self) -> &'static str {
455        "ClientDetectionResponse"
456    }
457
458    fn set_request_id(&mut self, request_id: String) {
459        self.response.request_id = request_id;
460    }
461
462    fn error_code(&self) -> i32 {
463        self.response.error_code
464    }
465
466    fn result_code(&self) -> i32 {
467        self.response.result_code
468    }
469}
470
471// ==================== Connect Reset ====================
472
473/// Connect reset request (sent by server)
474#[derive(Clone, Debug, Default, Serialize, Deserialize)]
475#[serde(rename_all = "camelCase")]
476pub struct ConnectResetRequest {
477    #[serde(flatten)]
478    pub internal_request: InternalRequest,
479    pub server_ip: String,
480    pub server_port: String,
481}
482
483impl RequestTrait for ConnectResetRequest {
484    fn headers(&self) -> HashMap<String, String> {
485        self.internal_request.headers()
486    }
487
488    fn request_type(&self) -> &'static str {
489        "ConnectResetRequest"
490    }
491
492    fn insert_headers(&mut self, headers: HashMap<String, String>) {
493        self.internal_request.insert_headers(headers);
494    }
495
496    fn request_id(&self) -> String {
497        self.internal_request.request_id()
498    }
499}