Skip to content

Commit

Permalink
Simplify the BestTipChanged future implementations
Browse files Browse the repository at this point in the history
  • Loading branch information
teor2345 committed Dec 14, 2022
1 parent eaa2fdc commit e72d0eb
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 54 deletions.
47 changes: 16 additions & 31 deletions zebra-chain/src/chain_tip/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,42 +122,27 @@ impl ChainTip for MockChainTip {
}

/// Returns when any sender channel changes.
/// Returns an error if any sender was dropped.
///
/// Unconditionally marks all channels as seen when called.
/// (Rather than only marking a single channel as seen when its response future returns).
/// Marks the changed channel as seen when the returned future completes.
//
// Update this method when each new mock field is added.
fn best_tip_changed(&mut self) -> BestTipChanged {
// Clone all the watch channels
let mut best_tip_height = self.best_tip_height.clone();
let mut best_tip_hash = self.best_tip_hash.clone();
let mut best_tip_block_time = self.best_tip_block_time.clone();
let mut estimated_distance_to_network_chain_tip =
self.estimated_distance_to_network_chain_tip.clone();

// The cloned channels have the original change status,
// so we can mark all the `self` channels as seen.
//
// Normally `changed()` does this, but we need the clones due to lifetimes.
self.mark_best_tip_seen();

// Move them into an async block, to manage lifetimes
let select_changed = async move {
// Get the first watch channel that has changed
future::select_all([
// Erase the differing future types for each channel, and map their error types
BestTipChanged::new(best_tip_height.changed().err_into()),
BestTipChanged::new(best_tip_hash.changed().err_into()),
BestTipChanged::new(best_tip_block_time.changed().err_into()),
BestTipChanged::new(estimated_distance_to_network_chain_tip.changed().err_into()),
])
// Map the select result to the expected type, dropping the unused channels,
// any removing any dependencies on their lifetimes
.map(|(changed_result, _changed_index, _remaining_futures)| changed_result)
.await
};
// A future that returns when the first watch channel has changed
let select_changed = future::select_all([
// Erase the differing future types for each channel, and map their error types
BestTipChanged::new(self.best_tip_height.changed().err_into()),
BestTipChanged::new(self.best_tip_hash.changed().err_into()),
BestTipChanged::new(self.best_tip_block_time.changed().err_into()),
BestTipChanged::new(
self.estimated_distance_to_network_chain_tip
.changed()
.err_into(),
),
])
// Map the select result to the expected type, dropping the unused channels
.map(|(changed_result, _changed_index, _remaining_futures)| changed_result);

// Erase the un-nameable type of the async block
BestTipChanged::new(select_changed)
}

Expand Down
26 changes: 3 additions & 23 deletions zebra-state/src/service/chain_tip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -394,33 +394,13 @@ impl ChainTip for LatestChainTip {

/// Returns when the state tip changes.
///
/// Unconditionally marks the state tip as seen when called.
/// (Rather than only marking it as seen when response future returns).
/// Marks the state tip as seen when the returned future completes.
#[instrument(skip(self))]
fn best_tip_changed(&mut self) -> BestTipChanged {
// The changed() future doesn't lock the value,
// so we don't need to use `with_chain_tip_block()` here.
//
// Clone the watch channel
let mut best_tip = self.receiver.clone();

// The cloned channel has the original change status,
// so we can mark the `self` channel as seen.
//
// Normally `changed()` does this, but we need the clone due to lifetimes.
self.mark_best_tip_seen();

// Move it into an async block, to manage lifetimes
let best_tip_changed = async move {
// Map its error type
best_tip.changed().err_into().await
};

// Erase the un-nameable type of the async block
BestTipChanged::new(best_tip_changed)
BestTipChanged::new(self.receiver.changed().err_into())
}

/// Marks the state tip as seen.
/// Mark the current best state tip as seen.
fn mark_best_tip_seen(&mut self) {
self.receiver.mark_as_seen();
}
Expand Down

0 comments on commit e72d0eb

Please sign in to comment.