Skip to content

Commit 278f19f

Browse files
committed
post review fixes
1 parent 05367a0 commit 278f19f

File tree

11 files changed

+202
-107
lines changed

11 files changed

+202
-107
lines changed

backend/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ tracing = "0.1"
2424
file-rotate = "0.7"
2525
tracing-appender = "0.2"
2626
tracing-subscriber = "0.3"
27+
# tracing-forest = { version = "0.1", features = ["tokio"] }
2728

2829
## Error Handling
2930
error-stack = "0.4"

backend/src/connector/api.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,6 @@ pub enum GetConfigurationResponse {
156156
}
157157

158158
/// API
159-
#[async_trait]
160159
pub trait Api<C: Send + Sync> {
161160
fn poll_ready(
162161
&self,
@@ -226,7 +225,6 @@ pub trait Api<C: Send + Sync> {
226225
}
227226

228227
/// API where `Context` isn't passed on every API call
229-
#[async_trait]
230228
pub trait ApiNoContext<C: Send + Sync> {
231229
fn poll_ready(&self, _cx: &mut Context) -> Poll<Result<(), ServiceError>>;
232230

@@ -297,7 +295,6 @@ impl<T: Api<C> + Send + Sync, C: Clone + Send + Sync> ContextWrapperExt<C> for T
297295
}
298296
}
299297

300-
#[async_trait]
301298
impl<T: Api<C> + Send + Sync, C: Clone + Send + Sync> ApiNoContext<C> for ContextWrapper<T, C> {
302299
fn poll_ready(&self, cx: &mut Context) -> Poll<Result<(), ServiceError>> {
303300
self.api().poll_ready(cx)
@@ -404,9 +401,10 @@ impl<T: Api<C> + Send + Sync, C: Clone + Send + Sync> ApiNoContext<C> for Contex
404401

405402
pub mod prelude {
406403
pub use super::{
407-
APIError, Api, GetAlienDirResponse, GetConfigurationResponse, GetDisksResponse,
408-
GetMetricsResponse, GetNodesResponse, GetPartitionResponse, GetPartitionsResponse,
409-
GetRecordsResponse, GetReplicasLocalDirsResponse, GetSpaceInfoResponse, GetStatusResponse,
410-
GetVDiskResponse, GetVDisksResponse, GetVersionResponse,
404+
APIError, Api, GetAlienDirResponse, GetAlienResponse, GetConfigurationResponse,
405+
GetDisksResponse, GetMetricsResponse, GetNodesResponse, GetPartitionResponse,
406+
GetPartitionsResponse, GetRecordsResponse, GetReplicasLocalDirsResponse,
407+
GetSpaceInfoResponse, GetStatusResponse, GetVDiskResponse, GetVDisksResponse,
408+
GetVersionResponse,
411409
};
412410
}

backend/src/connector/client.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
unused_variables
2323
)]
2424

25+
use hyper::body::to_bytes;
26+
2527
use super::{api::prelude::*, prelude::*};
2628

2729
/// Error type for failing to create a Client
@@ -255,8 +257,7 @@ where
255257
body_handler: impl Fn(R) -> T + Send,
256258
) -> Result<T, APIError> {
257259
let body = response.into_body();
258-
let body = body
259-
.into_raw()
260+
let body = to_bytes(body)
260261
.await
261262
.change_context(APIError::ResponseError)?;
262263
let body = std::str::from_utf8(&body).change_context(APIError::ResponseError)?;
@@ -268,6 +269,7 @@ where
268269
Ok(body_handler(body))
269270
}
270271
}
272+
271273
impl<S, C, Cr> Client<S, C, Cr>
272274
where
273275
Cr: Credentials + Clone,
@@ -286,10 +288,10 @@ where
286288
.change_context(APIError::RequestFailed)
287289
.attach_printable("No Response received")?
288290
.change_context(APIError::RequestFailed)
291+
.attach_printable("Hyper error")
289292
}
290293
}
291294

292-
#[async_trait]
293295
impl<S, C, Cr> Api<C> for Client<S, C, Cr>
294296
where
295297
Cr: Credentials + Clone,

backend/src/connector/context.rs

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -86,38 +86,3 @@ where
8686
self.inner.call(req)
8787
}
8888
}
89-
90-
/// Additional function for `hyper::Body`
91-
pub trait BodyExt {
92-
/// Raw body type
93-
type Raw;
94-
95-
/// Error if we can't gather up the raw body
96-
type Error;
97-
98-
/// Collect the body into a raw form
99-
fn into_raw(
100-
self,
101-
) -> futures::future::BoxFuture<'static, std::result::Result<Self::Raw, Self::Error>>;
102-
}
103-
104-
impl<T, E> BodyExt for T
105-
where
106-
T: Stream<Item = std::result::Result<Bytes, E>> + Unpin + Send + 'static,
107-
{
108-
type Raw = Vec<u8>;
109-
type Error = E;
110-
111-
fn into_raw(
112-
mut self,
113-
) -> futures::future::BoxFuture<'static, std::result::Result<Self::Raw, Self::Error>> {
114-
Box::pin(async {
115-
let mut raw = Vec::new();
116-
while let (Some(chunk), rest) = self.into_future().await {
117-
raw.extend_from_slice(&chunk?);
118-
self = rest;
119-
}
120-
Ok(raw)
121-
})
122-
}
123-
}

backend/src/connector/error.rs

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
use super::prelude::*;
2+
3+
impl From<GetAlienResponse> for StatusCode {
4+
fn from(value: GetAlienResponse) -> Self {
5+
match value {
6+
GetAlienResponse::AlienNodeName(_) => StatusCode::OK,
7+
}
8+
}
9+
}
10+
11+
impl From<GetAlienDirResponse> for StatusCode {
12+
fn from(value: GetAlienDirResponse) -> Self {
13+
match value {
14+
GetAlienDirResponse::Directory(_) => StatusCode::OK,
15+
GetAlienDirResponse::PermissionDenied(_) => StatusCode::FORBIDDEN,
16+
GetAlienDirResponse::NotAcceptableBackend(_) => StatusCode::NOT_ACCEPTABLE,
17+
}
18+
}
19+
}
20+
21+
impl From<GetDisksResponse> for StatusCode {
22+
fn from(value: GetDisksResponse) -> Self {
23+
match value {
24+
GetDisksResponse::AJSONArrayWithDisksAndTheirStates(_) => StatusCode::OK,
25+
GetDisksResponse::PermissionDenied(_) => StatusCode::FORBIDDEN,
26+
}
27+
}
28+
}
29+
30+
impl From<GetMetricsResponse> for StatusCode {
31+
fn from(value: GetMetricsResponse) -> Self {
32+
match value {
33+
GetMetricsResponse::Metrics(_) => StatusCode::OK,
34+
}
35+
}
36+
}
37+
38+
impl From<GetNodesResponse> for StatusCode {
39+
fn from(value: GetNodesResponse) -> Self {
40+
match value {
41+
GetNodesResponse::AJSONArrayOfNodesInfoAndVdisksOnThem(_) => StatusCode::OK,
42+
GetNodesResponse::PermissionDenied => StatusCode::FORBIDDEN,
43+
}
44+
}
45+
}
46+
47+
impl From<GetPartitionResponse> for StatusCode {
48+
fn from(value: GetPartitionResponse) -> Self {
49+
match value {
50+
GetPartitionResponse::AJSONWithPartitionInfo(_) => StatusCode::OK,
51+
GetPartitionResponse::PermissionDenied(_) => StatusCode::FORBIDDEN,
52+
GetPartitionResponse::NotFound(_) => StatusCode::NOT_FOUND,
53+
}
54+
}
55+
}
56+
57+
impl From<GetRecordsResponse> for StatusCode {
58+
fn from(value: GetRecordsResponse) -> Self {
59+
match value {
60+
GetRecordsResponse::RecordsCount(_) => StatusCode::OK,
61+
GetRecordsResponse::PermissionDenied(_) => StatusCode::FORBIDDEN,
62+
GetRecordsResponse::NotFound(_) => StatusCode::NOT_FOUND,
63+
}
64+
}
65+
}
66+
67+
impl From<GetReplicasLocalDirsResponse> for StatusCode {
68+
fn from(value: GetReplicasLocalDirsResponse) -> Self {
69+
match value {
70+
GetReplicasLocalDirsResponse::AJSONArrayWithDirs(_) => StatusCode::OK,
71+
GetReplicasLocalDirsResponse::PermissionDenied(_) => StatusCode::FORBIDDEN,
72+
GetReplicasLocalDirsResponse::NotFound(_) => StatusCode::NOT_FOUND,
73+
}
74+
}
75+
}
76+
77+
impl From<GetStatusResponse> for StatusCode {
78+
fn from(value: GetStatusResponse) -> Self {
79+
match value {
80+
GetStatusResponse::AJSONWithNodeInfo(_) => StatusCode::OK,
81+
}
82+
}
83+
}
84+
85+
impl From<GetVDiskResponse> for StatusCode {
86+
fn from(value: GetVDiskResponse) -> Self {
87+
match value {
88+
GetVDiskResponse::AJSONWithVdiskInfo(_) => StatusCode::OK,
89+
GetVDiskResponse::PermissionDenied(_) => StatusCode::FORBIDDEN,
90+
GetVDiskResponse::NotFound(_) => StatusCode::NOT_FOUND,
91+
}
92+
}
93+
}
94+
95+
impl From<GetVDisksResponse> for StatusCode {
96+
fn from(value: GetVDisksResponse) -> Self {
97+
match value {
98+
GetVDisksResponse::AJSONArrayOfVdisksInfo(_) => StatusCode::OK,
99+
GetVDisksResponse::PermissionDenied => StatusCode::FORBIDDEN,
100+
}
101+
}
102+
}
103+
104+
impl From<GetVersionResponse> for StatusCode {
105+
fn from(value: GetVersionResponse) -> Self {
106+
match value {
107+
GetVersionResponse::VersionInfo(_) => StatusCode::OK,
108+
}
109+
}
110+
}
111+
112+
impl From<GetConfigurationResponse> for StatusCode {
113+
fn from(value: GetConfigurationResponse) -> Self {
114+
match value {
115+
GetConfigurationResponse::ConfigurationObject(_) => StatusCode::OK,
116+
GetConfigurationResponse::PermissionDenied => StatusCode::FORBIDDEN,
117+
}
118+
}
119+
}
120+
121+
pub trait AsApiError {
122+
fn as_invalid_status(self) -> APIError;
123+
}
124+
125+
impl<T: Into<StatusCode>> AsApiError for T {
126+
fn as_invalid_status(self) -> APIError {
127+
APIError::InvalidStatusCode(self.into())
128+
}
129+
}

backend/src/connector/mod.rs

Lines changed: 20 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,35 @@
11
mod prelude {
2+
pub use super::api::prelude::*;
23
pub use super::{
3-
context::{BodyExt, ContextWrapper, DropContextService, Has},
4+
context::{ContextWrapper, DropContextService, Has},
45
ClientError, Connector,
56
};
67
pub use crate::{models::shared::XSpanIdString, prelude::*, services::auth::HttpClient};
78
pub use axum::{
89
headers::{authorization::Credentials, Authorization, HeaderMapExt},
910
http::{HeaderName, HeaderValue},
1011
};
11-
pub use futures::{Stream, StreamExt};
12-
pub use hyper::{body::Bytes, service::Service, Response, Uri};
12+
pub use futures::StreamExt;
13+
pub use hyper::{service::Service, Response, Uri};
1314
pub use std::{
1415
str::FromStr,
1516
sync::Arc,
1617
task::{Context, Poll},
1718
};
1819
}
1920

20-
use api::{APIError, ApiNoContext, ContextWrapperExt};
21+
use api::{ApiNoContext, ContextWrapperExt};
2122
use client::Client;
2223
use context::ClientContext;
2324
use prelude::*;
2425

26+
use self::error::AsApiError;
27+
2528
pub mod api;
2629
pub mod client;
2730
pub mod context;
2831
pub mod dto;
32+
pub mod error;
2933

3034
pub type ApiInterface = dyn ApiNoContext<ClientContext> + Send + Sync;
3135

@@ -122,7 +126,6 @@ impl<Client: ApiNoContext<ClientContext> + Send + Sync + Clone> std::fmt::Debug
122126
}
123127

124128
impl<ApiInterface: ApiNoContext<ClientContext> + Send + Sync> BobClient<ApiInterface> {
125-
// impl BobClient<C> {
126129
/// Creates new [`BobClient`] from [`BobConnectionData`]
127130
///
128131
/// # Errors
@@ -140,19 +143,22 @@ impl<ApiInterface: ApiNoContext<ClientContext> + Send + Sync> BobClient<ApiInter
140143
let context: ClientContext = ClientContext {
141144
timeout,
142145
auth_data: auth,
143-
xspan: XSpanIdString::default(),
146+
xspan: XSpanIdString::gen(),
144147
};
145-
let client =
146-
Client::try_new_http(&hostname.to_string()).change_context(ClientError::InitClient)?;
147-
let nodes = client
148+
let client = Client::try_new_http(&hostname.to_string())
149+
.change_context(ClientError::InitClient)
150+
.attach_printable(format!("Hostname: {}", hostname.to_string()))?;
151+
let nodes_resp = client
148152
.clone()
149153
.with_context(context.clone())
150154
.get_nodes()
151155
.await
152-
.change_context(ClientError::Inaccessible)?;
153-
let api::GetNodesResponse::AJSONArrayOfNodesInfoAndVdisksOnThem(nodes) = nodes else {
154-
Err(APIError::InvalidStatusCode(StatusCode::FORBIDDEN))
155-
.change_context(ClientError::PermissionDenied)?
156+
.change_context(ClientError::Inaccessible)
157+
.attach_printable(format!("Hostname: {}", hostname.to_string()))?;
158+
let api::GetNodesResponse::AJSONArrayOfNodesInfoAndVdisksOnThem(nodes) = nodes_resp else {
159+
Err(nodes_resp.as_invalid_status())
160+
.change_context(ClientError::Inaccessible)
161+
.attach_printable(format!("Hostname: {}", hostname.to_string()))?
156162
};
157163

158164
let cluster: HashMap<NodeName, Arc<_>> = nodes
@@ -212,7 +218,7 @@ impl<ApiInterface: ApiNoContext<ClientContext> + Send + Sync> BobClient<ApiInter
212218
}
213219
}
214220

215-
/// Probes connection to the Bob's main connected node
221+
/// Probes connection to all Bob's connected nodes
216222
///
217223
/// Returns `StatusCode::OK` on success
218224
///
@@ -242,31 +248,6 @@ impl<ApiInterface: ApiNoContext<ClientContext> + Send + Sync> BobClient<ApiInter
242248
futures::future::join_all(v).await
243249
}
244250

245-
/// Probes Node's connection
246-
///
247-
/// # Errors
248-
///
249-
/// This function will return an error if no client present for the specified Node's name,
250-
/// the client was unable to receive response or the client doesn't have authority to do request.
251-
pub async fn probe_socket(&self, name: &NodeName) -> Result<StatusCode, ClientError> {
252-
if let Some(client) = self.cluster.get(name) {
253-
match client
254-
.get_nodes()
255-
.await
256-
.change_context(ClientError::Inaccessible)?
257-
{
258-
api::GetNodesResponse::AJSONArrayOfNodesInfoAndVdisksOnThem(_) => {
259-
Ok(StatusCode::OK)
260-
}
261-
api::GetNodesResponse::PermissionDenied => {
262-
Err(ClientError::PermissionDenied.into())
263-
}
264-
}
265-
} else {
266-
Err(ClientError::NoClient.into())
267-
}
268-
}
269-
270251
#[must_use]
271252
pub fn context(&self) -> &ClientContext {
272253
self.main.context()

backend/src/lib.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
#![allow(clippy::multiple_crate_versions, clippy::module_name_repetitions)]
1+
#![allow(
2+
async_fn_in_trait,
3+
clippy::multiple_crate_versions,
4+
clippy::module_name_repetitions
5+
)]
26

37
#[cfg(all(feature = "swagger", debug_assertions))]
48
use axum::{routing::get, Router};

backend/src/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ async fn main() -> Result<(), AppError> {
4444
fn router(cors: CorsLayer) -> Router {
4545
let session_store = MemoryStore::default();
4646
let session_service = ServiceBuilder::new()
47-
.layer(HandleErrorLayer::new(|_: BoxError| async {
47+
.layer(HandleErrorLayer::new(|err: BoxError| async move {
48+
tracing::error!(err);
4849
StatusCode::BAD_REQUEST
4950
}))
5051
.layer(

0 commit comments

Comments
 (0)