-
Notifications
You must be signed in to change notification settings - Fork 329
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add pagination and timeout to commitments and ack queries #4110
Conversation
- Implemented pagination for `query_packet_commitments` and `query_packet_acknowledgements` | ||
during the scanning phase to optimize the determination of whether to spawn a packet worker. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Implemented pagination for `query_packet_commitments` and `query_packet_acknowledgements` | |
during the scanning phase to optimize the determination of whether to spawn a packet worker. | |
- Paginate results of `query_packet_commitments` and `query_packet_acknowledgements` | |
queries to speed up the scanning phase. |
@@ -1,6 +1,7 @@ | |||
use core::fmt; | |||
|
|||
use abscissa_core::clap::Parser; | |||
use ibc_relayer::chain::requests::Paginate; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's move this in the import group below.
.and_then(|raw_height| raw_height.try_into().ok()) | ||
.ok_or_else(|| Error::grpc_response_param("height".to_string()))?; | ||
let mut tonic_request = tonic::Request::new(raw_request); | ||
tonic_request.set_timeout(Duration::from_secs(10)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a note for us that we should eventually make this either:
a) Configurable (eg. grpc_timeout
setting)
b) Inferred from the pagination, ie. use larger timeout for Paginate::All
and smaller one otherwise
crates/relayer/src/chain/cosmos.rs
Outdated
|
||
let responses = | ||
results.into_iter().collect::<Result< | ||
Vec<ibc_proto::ibc::core::channel::v1::QueryPacketCommitmentsResponse>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't the inner type be elided here?
Vec<ibc_proto::ibc::core::channel::v1::QueryPacketCommitmentsResponse>, | |
Vec<_>, |
.map(|v| v.sequence.into()) | ||
.collect(); | ||
let mut tonic_request = tonic::Request::new(raw_request); | ||
tonic_request.set_timeout(Duration::from_secs(10)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
crates/relayer/src/chain/cosmos.rs
Outdated
} | ||
|
||
let responses = results.into_iter().collect::<Result< | ||
Vec<ibc_proto::ibc::core::channel::v1::QueryPacketAcknowledgementsResponse>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
) -> Result<Option<(Vec<Sequence>, Height)>, Error> { | ||
let (commitments_on_src, _) = commitments_on_chain(chain, &path.port_id, &path.channel_id)?; | ||
let (commitments_on_src, _) = | ||
commitments_on_chain(chain, &path.port_id, &path.channel_id, pagination.clone())?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Paginate
can be made Copy
:
commitments_on_chain(chain, &path.port_id, &path.channel_id, pagination.clone())?; | |
commitments_on_chain(chain, &path.port_id, &path.channel_id, pagination)?; |
crates/relayer/src/chain/requests.rs
Outdated
if let Paginate::PerPage { | ||
pagination: _, | ||
limit, | ||
} = self | ||
{ | ||
return *limit; | ||
} | ||
0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A simple match
would look more idiomatic here
crates/relayer/src/chain/requests.rs
Outdated
match value { | ||
Paginate::All => PageRequest::all(), | ||
Paginate::PerPage { | ||
pagination: _, | ||
limit, | ||
} => PageRequest::per_page(limit), | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
match value { | |
Paginate::All => PageRequest::all(), | |
Paginate::PerPage { | |
pagination: _, | |
limit, | |
} => PageRequest::per_page(limit), | |
} | |
match value { | |
Paginate::All => PageRequest::all(), | |
Paginate::PerPage { limit, .. } => PageRequest::per_page(limit), | |
} |
crates/relayer/src/chain/requests.rs
Outdated
All, | ||
|
||
PerPage { | ||
pagination: u64, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this field ever used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a mistake in when converting to the PageRequest
. The pagination
should be the limit, number of results, and limit
should be the number of times the query is done. I will update this code
hermes/crates/relayer/src/chain/requests.rs
Line 176 in ead830b
} => PageRequest::per_page(limit), |
pagination
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will rename to:
PerPage {
limit: u64,
max_queries: u64,
},
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
imho it should contain two fields: one which specifies how many results per page we want and one which specifies how many results in total we want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So maybe per_page: u64
and total: u64
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
then we can just stop issuing queries once we either a) have total
results or b) there is no more next page/key
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh I had it set to one field for how many results per page and another one for the maximum number of queries. I will change to the option you suggested
.map_err(Error::grpc_transport)?; | ||
|
||
client = client | ||
.max_decoding_message_size(self.config().max_grpc_decoding_size.get_bytes() as usize); | ||
if request.pagination.is_enabled() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we are dealing with pagination in two queries, and are duplicating a bunch of fairly complex code, how about extracting the pagination logic in a standalone function we can use in both places?
async fn paginate<C, Req, Res, F>(
mut client: C,
request: Req,
mut do_query: impl FnMut(&mut C, Req, Vec<u8>) -> F,
get_next_key: impl Fn(&Res) -> Option<Vec<u8>>,
) -> Vec<Result<Res, Error>>
where
F: Future<Output = Result<Res, Error>> + 'static,
Req: Clone,
{
let mut results = vec![];
let mut page_key = vec![];
loop {
let response =
do_query(&mut client, request.clone(), std::mem::take(&mut page_key)).await;
match response {
Ok(response) => {
let next_key = get_next_key(&response);
results.push(Ok(response));
match next_key {
Some(next_key) if !next_key.is_empty() => {
page_key = next_key;
}
_ => break,
}
}
Err(e) => {
results.push(Err(e));
break;
}
}
}
results
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can leave this for a follow-up PR, or when we add pagination to yet another query.
Closes: #4101
Description
PR author checklist:
unclog
.docs/
).Reviewer checklist:
Files changed
in the GitHub PR explorer.