cli_v2: add local_api_request with crazy type bound

This commit is contained in:
Alex 2025-01-31 15:53:02 +01:00
parent 10bbb26b30
commit 7b9c047b11
3 changed files with 37 additions and 33 deletions

View file

@ -10,7 +10,6 @@ use serde::{Deserialize, Serialize};
use garage_rpc::*; use garage_rpc::*;
use garage_model::garage::Garage; use garage_model::garage::Garage;
use garage_util::error::Error as GarageError;
use garage_api_common::common_error::CommonErrorDerivative; use garage_api_common::common_error::CommonErrorDerivative;
use garage_api_common::helpers::is_default; use garage_api_common::helpers::is_default;
@ -105,21 +104,6 @@ pub struct MultiResponse<RB> {
pub error: HashMap<String, String>, pub error: HashMap<String, String>,
} }
impl<RB> MultiResponse<RB> {
pub fn into_single_response(self) -> Result<RB, GarageError> {
if let Some((_, e)) = self.error.into_iter().next() {
return Err(GarageError::Message(e));
}
if self.success.len() != 1 {
return Err(GarageError::Message(format!(
"{} responses returned, expected 1",
self.success.len()
)));
}
Ok(self.success.into_iter().next().unwrap().1)
}
}
// ********************************************** // **********************************************
// Special endpoints // Special endpoints
// //

View file

@ -16,7 +16,7 @@ use garage_rpc::*;
use garage_api_admin::api::*; use garage_api_admin::api::*;
use garage_api_admin::api_server::{AdminRpc as ProxyRpc, AdminRpcResponse as ProxyRpcResponse}; use garage_api_admin::api_server::{AdminRpc as ProxyRpc, AdminRpcResponse as ProxyRpcResponse};
use garage_api_admin::RequestHandler as AdminApiEndpoint; use garage_api_admin::RequestHandler;
use crate::admin::*; use crate::admin::*;
use crate::cli as cli_v1; use crate::cli as cli_v1;
@ -74,11 +74,11 @@ impl Cli {
} }
} }
pub async fn api_request<T>(&self, req: T) -> Result<<T as AdminApiEndpoint>::Response, Error> pub async fn api_request<T>(&self, req: T) -> Result<<T as RequestHandler>::Response, Error>
where where
T: AdminApiEndpoint, T: RequestHandler,
AdminApiRequest: From<T>, AdminApiRequest: From<T>,
<T as AdminApiEndpoint>::Response: TryFrom<TaggedAdminApiResponse>, <T as RequestHandler>::Response: TryFrom<TaggedAdminApiResponse>,
{ {
let req = AdminApiRequest::from(req); let req = AdminApiRequest::from(req);
let req_name = req.name(); let req_name = req.name();
@ -88,7 +88,7 @@ impl Cli {
.await?? .await??
{ {
ProxyRpcResponse::ProxyApiOkResponse(resp) => { ProxyRpcResponse::ProxyApiOkResponse(resp) => {
<T as AdminApiEndpoint>::Response::try_from(resp).map_err(|_| { <T as RequestHandler>::Response::try_from(resp).map_err(|_| {
Error::Message(format!("{} returned unexpected response", req_name)) Error::Message(format!("{} returned unexpected response", req_name))
}) })
} }
@ -103,4 +103,32 @@ impl Cli {
m => Err(Error::unexpected_rpc_message(m)), m => Err(Error::unexpected_rpc_message(m)),
} }
} }
pub async fn local_api_request<T>(
&self,
req: T,
) -> Result<<T as RequestHandler>::Response, Error>
where
T: RequestHandler,
MultiRequest<T>: RequestHandler<Response = MultiResponse<<T as RequestHandler>::Response>>,
AdminApiRequest: From<MultiRequest<T>>,
<MultiRequest<T> as RequestHandler>::Response: TryFrom<TaggedAdminApiResponse>,
{
let req = MultiRequest {
node: hex::encode(self.rpc_host),
body: req,
};
let resp = self.api_request(req).await?;
if let Some((_, e)) = resp.error.into_iter().next() {
return Err(Error::Message(e));
}
if resp.success.len() != 1 {
return Err(Error::Message(format!(
"{} responses returned, expected 1",
resp.success.len()
)));
}
Ok(resp.success.into_iter().next().unwrap().1)
}
} }

View file

@ -27,15 +27,11 @@ impl Cli {
pub async fn cmd_list_workers(&self, opt: WorkerListOpt) -> Result<(), Error> { pub async fn cmd_list_workers(&self, opt: WorkerListOpt) -> Result<(), Error> {
let mut list = self let mut list = self
.api_request(ListWorkersRequest { .local_api_request(LocalListWorkersRequest {
node: hex::encode(self.rpc_host),
body: LocalListWorkersRequest {
busy_only: opt.busy, busy_only: opt.busy,
error_only: opt.errors, error_only: opt.errors,
},
}) })
.await? .await?
.into_single_response()?
.0; .0;
list.sort_by_key(|info| { list.sort_by_key(|info| {
@ -90,12 +86,8 @@ impl Cli {
pub async fn cmd_worker_info(&self, tid: usize) -> Result<(), Error> { pub async fn cmd_worker_info(&self, tid: usize) -> Result<(), Error> {
let info = self let info = self
.api_request(GetWorkerInfoRequest { .local_api_request(LocalGetWorkerInfoRequest { id: tid as u64 })
node: hex::encode(self.rpc_host),
body: LocalGetWorkerInfoRequest { id: tid as u64 },
})
.await? .await?
.into_single_response()?
.0; .0;
let mut table = vec![]; let mut table = vec![];