mirror of
https://github.com/logos-blockchain/logos-blockchain-testing.git
synced 2026-01-02 13:23:13 +00:00
core: add non-panicking testing-endpoint APIs
This commit is contained in:
parent
8a6d7236ef
commit
e7093df4e5
@ -21,6 +21,14 @@ use tracing::error;
|
||||
pub const DA_GET_TESTING_ENDPOINT_ERROR: &str = "Failed to connect to testing endpoint. The binary was likely built without the 'testing' \
|
||||
feature. Try: cargo build --workspace --all-features";
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum ApiClientError {
|
||||
#[error("{DA_GET_TESTING_ENDPOINT_ERROR}")]
|
||||
TestingEndpointUnavailable,
|
||||
#[error(transparent)]
|
||||
Request(#[from] reqwest::Error),
|
||||
}
|
||||
|
||||
/// Thin async client for node HTTP/testing endpoints.
|
||||
#[derive(Clone)]
|
||||
pub struct ApiClient {
|
||||
@ -154,6 +162,26 @@ impl ApiClient {
|
||||
}
|
||||
|
||||
/// POST JSON to the testing API and return the raw response.
|
||||
pub async fn post_testing_json_response_checked<T>(
|
||||
&self,
|
||||
path: &str,
|
||||
body: &T,
|
||||
) -> Result<Response, ApiClientError>
|
||||
where
|
||||
T: Serialize + Sync + ?Sized,
|
||||
{
|
||||
let testing_url = self
|
||||
.testing_url
|
||||
.as_ref()
|
||||
.ok_or(ApiClientError::TestingEndpointUnavailable)?;
|
||||
self.client
|
||||
.post(Self::join_url(testing_url, path))
|
||||
.json(body)
|
||||
.send()
|
||||
.await
|
||||
.map_err(ApiClientError::Request)
|
||||
}
|
||||
|
||||
pub async fn post_testing_json_response<T>(
|
||||
&self,
|
||||
path: &str,
|
||||
@ -162,27 +190,39 @@ impl ApiClient {
|
||||
where
|
||||
T: Serialize + Sync + ?Sized,
|
||||
{
|
||||
let testing_url = self
|
||||
.testing_url
|
||||
.as_ref()
|
||||
.expect(DA_GET_TESTING_ENDPOINT_ERROR);
|
||||
self.client
|
||||
.post(Self::join_url(testing_url, path))
|
||||
.json(body)
|
||||
.send()
|
||||
.await
|
||||
match self.post_testing_json_response_checked(path, body).await {
|
||||
Ok(resp) => Ok(resp),
|
||||
Err(ApiClientError::Request(err)) => Err(err),
|
||||
Err(ApiClientError::TestingEndpointUnavailable) => {
|
||||
panic!("{DA_GET_TESTING_ENDPOINT_ERROR}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// GET from the testing API and return the raw response.
|
||||
pub async fn get_testing_response(&self, path: &str) -> reqwest::Result<Response> {
|
||||
pub async fn get_testing_response_checked(
|
||||
&self,
|
||||
path: &str,
|
||||
) -> Result<Response, ApiClientError> {
|
||||
let testing_url = self
|
||||
.testing_url
|
||||
.as_ref()
|
||||
.expect(DA_GET_TESTING_ENDPOINT_ERROR);
|
||||
.ok_or(ApiClientError::TestingEndpointUnavailable)?;
|
||||
self.client
|
||||
.get(Self::join_url(testing_url, path))
|
||||
.send()
|
||||
.await
|
||||
.map_err(ApiClientError::Request)
|
||||
}
|
||||
|
||||
pub async fn get_testing_response(&self, path: &str) -> reqwest::Result<Response> {
|
||||
match self.get_testing_response_checked(path).await {
|
||||
Ok(resp) => Ok(resp),
|
||||
Err(ApiClientError::Request(err)) => Err(err),
|
||||
Err(ApiClientError::TestingEndpointUnavailable) => {
|
||||
panic!("{DA_GET_TESTING_ENDPOINT_ERROR}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Block a peer via the DA testing API.
|
||||
@ -258,6 +298,19 @@ impl ApiClient {
|
||||
}
|
||||
|
||||
/// Query DA membership via testing API.
|
||||
pub async fn da_get_membership_checked(
|
||||
&self,
|
||||
session_id: &SessionNumber,
|
||||
) -> Result<MembershipResponse, ApiClientError> {
|
||||
self.post_testing_json_response_checked(DA_GET_MEMBERSHIP, session_id)
|
||||
.await?
|
||||
.error_for_status()
|
||||
.map_err(ApiClientError::Request)?
|
||||
.json()
|
||||
.await
|
||||
.map_err(ApiClientError::Request)
|
||||
}
|
||||
|
||||
pub async fn da_get_membership(
|
||||
&self,
|
||||
session_id: &SessionNumber,
|
||||
|
||||
@ -5,7 +5,7 @@ pub mod validator;
|
||||
|
||||
use std::sync::LazyLock;
|
||||
|
||||
pub use api_client::ApiClient;
|
||||
pub use api_client::{ApiClient, ApiClientError};
|
||||
use tempfile::TempDir;
|
||||
|
||||
pub(crate) const LOGS_PREFIX: &str = "__logs";
|
||||
|
||||
@ -4,7 +4,7 @@ use reqwest::{Client, Url};
|
||||
use thiserror::Error;
|
||||
|
||||
use super::ReadinessCheck;
|
||||
use crate::topology::deployment::Topology;
|
||||
use crate::{nodes::ApiClientError, topology::deployment::Topology};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum MembershipError {
|
||||
@ -15,7 +15,9 @@ pub enum MembershipError {
|
||||
message: String,
|
||||
},
|
||||
#[error(transparent)]
|
||||
Request(#[from] reqwest::Error),
|
||||
Http(#[from] reqwest::Error),
|
||||
#[error(transparent)]
|
||||
ApiClient(#[from] ApiClientError),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -50,7 +52,7 @@ impl<'a> ReadinessCheck<'a> for MembershipReadiness<'a> {
|
||||
async move {
|
||||
let result = node
|
||||
.api()
|
||||
.da_get_membership(&self.session)
|
||||
.da_get_membership_checked(&self.session)
|
||||
.await
|
||||
.map_err(MembershipError::from);
|
||||
NodeMembershipStatus { label, result }
|
||||
@ -72,7 +74,7 @@ impl<'a> ReadinessCheck<'a> for MembershipReadiness<'a> {
|
||||
async move {
|
||||
let result = node
|
||||
.api()
|
||||
.da_get_membership(&self.session)
|
||||
.da_get_membership_checked(&self.session)
|
||||
.await
|
||||
.map_err(MembershipError::from);
|
||||
NodeMembershipStatus { label, result }
|
||||
@ -164,12 +166,12 @@ pub async fn try_fetch_membership(
|
||||
.json(&session)
|
||||
.send()
|
||||
.await
|
||||
.map_err(MembershipError::Request)?
|
||||
.map_err(MembershipError::Http)?
|
||||
.error_for_status()
|
||||
.map_err(MembershipError::Request)?
|
||||
.map_err(MembershipError::Http)?
|
||||
.json()
|
||||
.await
|
||||
.map_err(MembershipError::Request)
|
||||
.map_err(MembershipError::Http)
|
||||
}
|
||||
|
||||
#[deprecated(note = "use try_fetch_membership to avoid panics and preserve error details")]
|
||||
@ -181,7 +183,7 @@ pub async fn fetch_membership(
|
||||
try_fetch_membership(client, base, session)
|
||||
.await
|
||||
.map_err(|err| match err {
|
||||
MembershipError::Request(source) => source,
|
||||
MembershipError::Http(source) => source,
|
||||
MembershipError::JoinUrl {
|
||||
base,
|
||||
path,
|
||||
@ -189,6 +191,7 @@ pub async fn fetch_membership(
|
||||
} => {
|
||||
panic!("failed to join url {base} with path {path}: {message}")
|
||||
}
|
||||
MembershipError::ApiClient(err) => panic!("{err}"),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user