Skip to content

Commit

Permalink
[refactor] hyperledger#3124: Introduced Query request builder into Cl…
Browse files Browse the repository at this point in the history
…ient API

Signed-off-by: Vladimir Pesterev <8786922+pesterev@users.noreply.github.com>
  • Loading branch information
pesterev committed Oct 31, 2023
1 parent a04448e commit 95250b5
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 172 deletions.
127 changes: 10 additions & 117 deletions client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ use self::{blocks_api::AsyncBlockStream, events_api::AsyncEventStream};
use crate::{
http::{Method as HttpMethod, RequestBuilder, Response, StatusCode},
http_default::{self, DefaultRequestBuilder, WebSocketError, WebSocketMessage},
query_builder::QueryRequestBuilder,
};

const APPLICATION_JSON: &str = "application/json";
Expand Down Expand Up @@ -847,139 +848,31 @@ impl Client {
Ok(output)
}

/// Create a request with pagination and sorting.
/// Query API entry point. Shorthand for `self.build_query(r).execute()`.
///
/// # Errors
/// Fails if sending request fails
pub fn request_with_pagination_and_sorting<R: Query + Debug>(
&self,
request: R,
pagination: Pagination,
sorting: Sorting,
) -> QueryResult<<R::Output as QueryOutput>::Target>
pub fn request<R>(&self, request: R) -> QueryResult<<R::Output as QueryOutput>::Target>
where
R: Query + Debug,
R::Output: QueryOutput,
<R::Output as TryFrom<Value>>::Error: Into<eyre::Error>,
{
self.request_with_filter_and_pagination_and_sorting(
request,
pagination,
sorting,
PredicateBox::default(),
)
}

/// Create a request with pagination, sorting, and the given filter.
///
/// # Errors
/// Fails if sending request fails
pub fn request_with_filter_and_pagination<R: Query + Debug>(
&self,
request: R,
pagination: Pagination,
filter: PredicateBox,
) -> QueryResult<<R::Output as QueryOutput>::Target>
where
R::Output: QueryOutput,
<R::Output as TryFrom<Value>>::Error: Into<eyre::Error>,
{
self.request_with_filter_and_pagination_and_sorting(
request,
pagination,
Sorting::default(),
filter,
)
self.build_query(request).execute()
}

/// Create a request with sorting and the given filter.
/// Query API entry point.
/// Creates a [`QueryRequestBuilder`] which can be used to configure requests queries from `Iroha` peers.
///
/// # Errors
/// Fails if sending request fails
pub fn request_with_filter_and_sorting<R: Query + Debug>(
&self,
request: R,
sorting: Sorting,
filter: PredicateBox,
) -> QueryResult<<R::Output as QueryOutput>::Target>
where
R::Output: QueryOutput,
<R::Output as TryFrom<Value>>::Error: Into<eyre::Error>,
{
self.request_with_filter_and_pagination_and_sorting(
request,
Pagination::default(),
sorting,
filter,
)
}

/// Query API entry point. Requests quieries from `Iroha` peers with filter.
///
/// Uses default blocking http-client. If you need some custom integration, look at
/// [`Self::prepare_query_request`].
///
/// # Errors
/// Fails if sending request fails
pub fn request_with_filter<R: Query + Debug>(
&self,
request: R,
filter: PredicateBox,
) -> QueryResult<<R::Output as QueryOutput>::Target>
where
R::Output: QueryOutput,
<R::Output as TryFrom<Value>>::Error: Into<eyre::Error>,
{
self.request_with_filter_and_pagination(request, Pagination::default(), filter)
}

/// Query API entry point. Requests queries from `Iroha` peers with pagination.
///
/// Uses default blocking http-client. If you need some custom integration, look at
/// [`Self::prepare_query_request`].
///
/// # Errors
/// Fails if sending request fails
pub fn request_with_pagination<R: Query + Debug>(
&self,
request: R,
pagination: Pagination,
) -> QueryResult<<R::Output as QueryOutput>::Target>
where
R::Output: QueryOutput,
<R::Output as TryFrom<Value>>::Error: Into<eyre::Error>,
{
self.request_with_filter_and_pagination(request, pagination, PredicateBox::default())
}

/// Query API entry point. Requests queries from `Iroha` peers with sorting.
///
/// # Errors
/// Fails if sending request fails
pub fn request_with_sorting<R: Query + Debug>(
&self,
request: R,
sorting: Sorting,
) -> QueryResult<<R::Output as QueryOutput>::Target>
where
R::Output: QueryOutput,
<R::Output as TryFrom<Value>>::Error: Into<eyre::Error>,
{
self.request_with_pagination_and_sorting(request, Pagination::default(), sorting)
}

/// Query API entry point. Requests queries from `Iroha` peers.
///
/// # Errors
/// Fails if sending request fails
pub fn request<R: Query + Debug>(
&self,
request: R,
) -> QueryResult<<R::Output as QueryOutput>::Target>
pub fn build_query<R>(&self, request: R) -> QueryRequestBuilder<'_, R>
where
R: Query + Debug,
R::Output: QueryOutput,
<R::Output as TryFrom<Value>>::Error: Into<eyre::Error>,
{
self.request_with_pagination(request, Pagination::default())
QueryRequestBuilder::new(self, request)
}

/// Connect (through `WebSocket`) to listen for `Iroha` `pipeline` and `data` events.
Expand Down
1 change: 1 addition & 0 deletions client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub mod client;
/// Module with general communication primitives like an HTTP request builder.
pub mod http;
mod http_default;
mod query_builder;

/// Module containing sample configurations for tests and benchmarks.
pub mod samples {
Expand Down
58 changes: 58 additions & 0 deletions client/src/query_builder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use std::fmt::Debug;

use iroha_data_model::{
predicate::PredicateBox,
query::{sorting::Sorting, Pagination, Query},
Value,
};

use crate::client::{Client, QueryOutput, QueryResult};

pub struct QueryRequestBuilder<'a, R> {
client: &'a Client,
request: R,
pagination: Pagination,
filter: PredicateBox,
sorting: Sorting,
}

impl<'a, R> QueryRequestBuilder<'a, R>
where
R: Query + Debug,
R::Output: QueryOutput,
<R::Output as TryFrom<Value>>::Error: Into<eyre::Error>,
{
pub(crate) fn new(client: &'a Client, request: R) -> Self {
Self {
client,
request,
pagination: Pagination::default(),
sorting: Sorting::default(),
filter: PredicateBox::default(),
}
}

pub fn with_filter(mut self, filter: PredicateBox) -> Self {
self.filter = filter;
self
}

pub fn with_sorting(mut self, sorting: Sorting) -> Self {
self.sorting = sorting;
self
}

pub fn with_pagination(mut self, pagination: Pagination) -> Self {
self.pagination = pagination;
self
}

pub fn execute(self) -> QueryResult<<R::Output as QueryOutput>::Target> {
self.client.request_with_filter_and_pagination_and_sorting(
self.request,
self.pagination,
self.sorting,
self.filter,
)
}
}
15 changes: 7 additions & 8 deletions client/tests/integration/pagination.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,13 @@ fn client_add_asset_quantity_to_existing_asset_should_increase_asset_amount() ->
.collect();
client.submit_all_blocking(register)?;

let vec = client
.request_with_pagination(
asset::all_definitions(),
Pagination {
limit: NonZeroU32::new(5),
start: NonZeroU64::new(5),
},
)?
let vec = &client
.build_query(asset::all_definitions())
.with_pagination(Pagination {
limit: NonZeroU32::new(5),
start: NonZeroU64::new(5),
})
.execute()?
.collect::<QueryResult<Vec<_>>>()?;
assert_eq!(vec.len(), 5);
Ok(())
Expand Down
69 changes: 32 additions & 37 deletions client/tests/integration/sorting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,13 @@ fn correct_pagination_assets_after_creating_new_one() {
let sorting = Sorting::by_metadata_key(sort_by_metadata_key.clone());

let res = test_client
.request_with_pagination_and_sorting(
client::asset::by_account_id(account_id.clone()),
Pagination {
limit: NonZeroU32::new(5),
start: None,
},
sorting.clone(),
)
.build_query(client::asset::by_account_id(account_id.clone()))
.with_pagination(Pagination {
limit: NonZeroU32::new(5),
start: None,
})
.with_sorting(sorting.clone())
.execute()
.expect("Valid")
.collect::<QueryResult<Vec<_>>>()
.expect("Valid");
Expand Down Expand Up @@ -101,14 +100,13 @@ fn correct_pagination_assets_after_creating_new_one() {
.expect("Valid");

let res = test_client
.request_with_pagination_and_sorting(
client::asset::by_account_id(account_id),
Pagination {
limit: NonZeroU32::new(13),
start: NonZeroU64::new(8),
},
sorting,
)
.build_query(client::asset::by_account_id(account_id))
.with_pagination(Pagination {
limit: NonZeroU32::new(13),
start: NonZeroU64::new(8),
})
.with_sorting(sorting)
.execute()
.expect("Valid")
.collect::<QueryResult<Vec<_>>>()
.expect("Valid");
Expand Down Expand Up @@ -162,13 +160,12 @@ fn correct_sorting_of_entities() {
.expect("Valid");

let res = test_client
.request_with_filter_and_sorting(
client::asset::all_definitions(),
Sorting::by_metadata_key(sort_by_metadata_key.clone()),
PredicateBox::new(value::ValuePredicate::Identifiable(
string::StringPredicate::starts_with("xor_"),
)),
)
.build_query(client::asset::all_definitions())
.with_sorting(Sorting::by_metadata_key(sort_by_metadata_key.clone()))
.with_filter(PredicateBox::new(value::ValuePredicate::Identifiable(
string::StringPredicate::starts_with("xor_"),
)))
.execute()
.expect("Valid")
.collect::<QueryResult<Vec<_>>>()
.expect("Valid");
Expand Down Expand Up @@ -213,13 +210,12 @@ fn correct_sorting_of_entities() {
.expect("Valid");

let res = test_client
.request_with_filter_and_sorting(
client::account::all(),
Sorting::by_metadata_key(sort_by_metadata_key.clone()),
PredicateBox::new(value::ValuePredicate::Identifiable(
string::StringPredicate::starts_with("charlie"),
)),
)
.build_query(client::account::all())
.with_sorting(Sorting::by_metadata_key(sort_by_metadata_key.clone()))
.with_filter(PredicateBox::new(value::ValuePredicate::Identifiable(
string::StringPredicate::starts_with("charlie"),
)))
.execute()
.expect("Valid")
.collect::<QueryResult<Vec<_>>>()
.expect("Valid");
Expand Down Expand Up @@ -371,13 +367,12 @@ fn sort_only_elements_which_have_sorting_key() -> Result<()> {
.wrap_err("Failed to register accounts")?;

let res = test_client
.request_with_filter_and_sorting(
client::account::all(),
Sorting::by_metadata_key(sort_by_metadata_key),
PredicateBox::new(value::ValuePredicate::Identifiable(
string::StringPredicate::starts_with("charlie"),
)),
)
.build_query(client::account::all())
.with_sorting(Sorting::by_metadata_key(sort_by_metadata_key))
.with_filter(PredicateBox::new(value::ValuePredicate::Identifiable(
string::StringPredicate::starts_with("charlie"),
)))
.execute()
.wrap_err("Failed to submit request")?
.collect::<QueryResult<Vec<_>>>()?;

Expand Down
13 changes: 6 additions & 7 deletions client/tests/integration/tx_history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,12 @@ fn client_has_rejected_and_acepted_txs_should_return_tx_history() -> Result<()>
thread::sleep(pipeline_time * 5);

let transactions = client
.request_with_pagination(
transaction::by_account_id(account_id.clone()),
Pagination {
limit: NonZeroU32::new(50),
start: NonZeroU64::new(1),
},
)?
.build_query(transaction::by_account_id(account_id.clone()))
.with_pagination(Pagination {
limit: NonZeroU32::new(50),
start: NonZeroU64::new(1),
})
.execute()?
.collect::<QueryResult<Vec<_>>>()?;
assert_eq!(transactions.len(), 50);

Expand Down
Loading

0 comments on commit 95250b5

Please sign in to comment.