mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-24 15:55:49 +00:00
chainHead: Support multiple hashes for chainHead_unpin method (#2295)
This PR adds support for multiple hashes being passed to the `chainHeda_unpin` parameters. The `hash` parameter is renamed to `hash_or_hashes` per https://github.com/paritytech/json-rpc-interface-spec/pull/111. While at it, a new integration test is added to check the unpinning of multiple hashes. The API is checked against a hash or a vector of hashes. cc @paritytech/subxt-team --------- Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
This commit is contained in:
@@ -750,22 +750,36 @@ impl<Block: BlockT, BE: Backend<Block>> SubscriptionsInner<Block, BE> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unpin_block(
|
||||
pub fn unpin_blocks(
|
||||
&mut self,
|
||||
sub_id: &str,
|
||||
hash: Block::Hash,
|
||||
hashes: impl IntoIterator<Item = Block::Hash> + Clone,
|
||||
) -> Result<(), SubscriptionManagementError> {
|
||||
let Some(sub) = self.subs.get_mut(sub_id) else {
|
||||
return Err(SubscriptionManagementError::SubscriptionAbsent)
|
||||
};
|
||||
|
||||
// Check that unpin was not called before and the block was pinned
|
||||
// for this subscription.
|
||||
if !sub.unregister_block(hash) {
|
||||
return Err(SubscriptionManagementError::BlockHashAbsent)
|
||||
// Ensure that all blocks are part of the subscription before removing individual
|
||||
// blocks.
|
||||
for hash in hashes.clone() {
|
||||
if !sub.contains_block(hash) {
|
||||
return Err(SubscriptionManagementError::BlockHashAbsent);
|
||||
}
|
||||
}
|
||||
|
||||
// Note: this needs to be separate from the global mappings to avoid barrow checker
|
||||
// thinking we borrow `&mut self` twice: once from `self.subs.get_mut` and once from
|
||||
// `self.global_unregister_block`. Although the borrowing is correct, since different
|
||||
// fields of the structure are borrowed, one at a time.
|
||||
for hash in hashes.clone() {
|
||||
sub.unregister_block(hash);
|
||||
}
|
||||
|
||||
// Block have been removed from the subscription. Remove them from the global tracking.
|
||||
for hash in hashes {
|
||||
self.global_unregister_block(hash);
|
||||
}
|
||||
|
||||
self.global_unregister_block(hash);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1029,11 +1043,11 @@ mod tests {
|
||||
assert_eq!(block.has_runtime(), true);
|
||||
|
||||
let invalid_id = "abc-invalid".to_string();
|
||||
let err = subs.unpin_block(&invalid_id, hash).unwrap_err();
|
||||
let err = subs.unpin_blocks(&invalid_id, vec![hash]).unwrap_err();
|
||||
assert_eq!(err, SubscriptionManagementError::SubscriptionAbsent);
|
||||
|
||||
// Unpin the block.
|
||||
subs.unpin_block(&id, hash).unwrap();
|
||||
subs.unpin_blocks(&id, vec![hash]).unwrap();
|
||||
let err = subs.lock_block(&id, hash, 1).unwrap_err();
|
||||
assert_eq!(err, SubscriptionManagementError::BlockHashAbsent);
|
||||
}
|
||||
@@ -1077,13 +1091,13 @@ mod tests {
|
||||
// Ensure the block propagated to the subscription.
|
||||
subs.subs.get(&id_second).unwrap().blocks.get(&hash).unwrap();
|
||||
|
||||
subs.unpin_block(&id, hash).unwrap();
|
||||
subs.unpin_blocks(&id, vec![hash]).unwrap();
|
||||
assert_eq!(*subs.global_blocks.get(&hash).unwrap(), 1);
|
||||
// Cannot unpin a block twice for the same subscription.
|
||||
let err = subs.unpin_block(&id, hash).unwrap_err();
|
||||
let err = subs.unpin_blocks(&id, vec![hash]).unwrap_err();
|
||||
assert_eq!(err, SubscriptionManagementError::BlockHashAbsent);
|
||||
|
||||
subs.unpin_block(&id_second, hash).unwrap();
|
||||
subs.unpin_blocks(&id_second, vec![hash]).unwrap();
|
||||
// Block unregistered from the memory.
|
||||
assert!(subs.global_blocks.get(&hash).is_none());
|
||||
}
|
||||
|
||||
@@ -94,22 +94,23 @@ impl<Block: BlockT, BE: Backend<Block>> SubscriptionManagement<Block, BE> {
|
||||
inner.pin_block(sub_id, hash)
|
||||
}
|
||||
|
||||
/// Unpin the block from the subscription.
|
||||
/// Unpin the blocks from the subscription.
|
||||
///
|
||||
/// The last subscription that unpins the block is also unpinning the block
|
||||
/// from the backend.
|
||||
/// Blocks are reference counted and when the last subscription unpins a given block, the block
|
||||
/// is also unpinned from the backend.
|
||||
///
|
||||
/// This method is called only once per subscription.
|
||||
///
|
||||
/// Returns an error if the block is not pinned for the subscription or
|
||||
/// the subscription ID is invalid.
|
||||
pub fn unpin_block(
|
||||
/// Returns an error if the subscription ID is invalid, or any of the blocks are not pinned
|
||||
/// for the subscriptions. When an error is returned, it is guaranteed that no blocks have
|
||||
/// been unpinned.
|
||||
pub fn unpin_blocks(
|
||||
&self,
|
||||
sub_id: &str,
|
||||
hash: Block::Hash,
|
||||
hashes: impl IntoIterator<Item = Block::Hash> + Clone,
|
||||
) -> Result<(), SubscriptionManagementError> {
|
||||
let mut inner = self.inner.write();
|
||||
inner.unpin_block(sub_id, hash)
|
||||
inner.unpin_blocks(sub_id, hashes)
|
||||
}
|
||||
|
||||
/// Ensure the block remains pinned until the return object is dropped.
|
||||
|
||||
Reference in New Issue
Block a user