From 04b937328b8d6d1982d4f42f19a2c397d398bd4e Mon Sep 17 00:00:00 2001 From: Alexander Simmerl Date: Tue, 30 Jun 2020 21:58:34 +0200 Subject: [PATCH] light-client: turn Handle into a trait As we start to depend on the surface of the `Handle` we benefit from it being a trait that can be implemented on a per need basis. This will result in less overhead constructing object graphs in places where we wannt to assert behaviour of other types in remote places, i.e. the light-node rpc server. Overall we hope for an increased ease in writing tests on module level. Ref #219 --- light-client/examples/light_client.rs | 18 ++--- light-client/src/supervisor.rs | 102 ++++++++++++++++---------- 2 files changed, 71 insertions(+), 49 deletions(-) diff --git a/light-client/examples/light_client.rs b/light-client/examples/light_client.rs index 5e5806404..097fb16ef 100644 --- a/light-client/examples/light_client.rs +++ b/light-client/examples/light_client.rs @@ -1,3 +1,12 @@ +use std::collections::HashMap; +use std::{ + path::{Path, PathBuf}, + time::Duration, +}; + +use gumdrop::Options; + +use tendermint_light_client::supervisor::{Handle as _, Instance, Supervisor}; use tendermint_light_client::{ components::{ clock::SystemClock, @@ -11,18 +20,9 @@ use tendermint_light_client::{ peer_list::PeerList, state::State, store::{sled::SledStore, LightStore}, - supervisor::{Instance, Supervisor}, types::{Height, PeerId, Status, Time, TrustThreshold}, }; -use gumdrop::Options; - -use std::collections::HashMap; -use std::{ - path::{Path, PathBuf}, - time::Duration, -}; - #[derive(Debug, Options)] struct CliOptions { #[options(help = "print this help message")] diff --git a/light-client/src/supervisor.rs b/light-client/src/supervisor.rs index c189ee097..c3428487a 100644 --- a/light-client/src/supervisor.rs +++ b/light-client/src/supervisor.rs @@ -15,6 +15,39 @@ use crate::{ types::{Height, LightBlock, PeerId, Status}, }; +pub trait Handle { + /// Get latest trusted block from the [`Supervisor`]. + fn latest_trusted(&mut self) -> Result, Error>; + + /// Verify to the highest block. + fn verify_to_highest(&mut self) -> Result; + + /// Verify to the block at the given height. + fn verify_to_target(&mut self, height: Height) -> Result; + + /// Async version of `verify_to_highest`. + /// + /// The given `callback` will be called asynchronously with the + /// verification result. + fn verify_to_highest_async( + &mut self, + callback: impl FnOnce(Result) -> () + Send + 'static, + ); + + /// Async version of `verify_to_target`. + /// + /// The given `callback` will be called asynchronously with the + /// verification result. + fn verify_to_target_async( + &mut self, + height: Height, + callback: impl FnOnce(Result) -> () + Send + 'static, + ); + + /// Terminate the underlying [`Supervisor`]. + fn terminate(&mut self); +} + /// Input events sent by the [`Handle`]s to the [`Supervisor`]. They carry a [`Callback`] which is /// used to communicate back the responses of the requests. #[derive(Debug)] @@ -134,8 +167,8 @@ impl Supervisor { } /// Create a new handle to this supervisor. - pub fn handle(&mut self) -> Handle { - Handle::new(self.sender.clone()) + pub fn handle(&mut self) -> impl Handle { + SupervisorHandle::new(self.sender.clone()) } #[pre(self.peers.primary().is_some())] @@ -308,21 +341,38 @@ impl Supervisor { } } -/// A handle to a `Supervisor` which allows to communicate with +/// A [`Handle`] to the [`Supervisor`] which allows to communicate with /// the supervisor across thread boundaries via message passing. -pub struct Handle { +struct SupervisorHandle { sender: channel::Sender, } -impl Handle { +impl SupervisorHandle { /// Crate a new handle that sends events to the supervisor via /// the given channel. For internal use only. fn new(sender: channel::Sender) -> Self { Self { sender } } - /// Get latest trusted block from the [`Supervisor`]. - pub fn latest_trusted(&mut self) -> Result, Error> { + fn verify( + &mut self, + make_event: impl FnOnce(Callback>) -> HandleInput, + ) -> Result { + let (sender, receiver) = channel::bounded::>(1); + + let callback = Callback::new(move |result| { + sender.send(result).unwrap(); + }); + + let event = make_event(callback); + self.sender.send(event).unwrap(); + + receiver.recv().unwrap() + } +} + +impl Handle for SupervisorHandle { + fn latest_trusted(&mut self) -> Result, Error> { let (sender, receiver) = channel::bounded::, Error>>(1); let callback = Callback::new(move |result| { @@ -338,38 +388,15 @@ impl Handle { receiver.recv().unwrap() } - /// Verify to the highest block. - pub fn verify_to_highest(&mut self) -> Result { + fn verify_to_highest(&mut self) -> Result { self.verify(HandleInput::VerifyToHighest) } - /// Verify to the block at the given height. - pub fn verify_to_target(&mut self, height: Height) -> Result { + fn verify_to_target(&mut self, height: Height) -> Result { self.verify(|callback| HandleInput::VerifyToTarget(height, callback)) } - /// Verify either to the latest block (if `height == None`) or to a given block (if `height == Some(height)`). - fn verify( - &mut self, - make_event: impl FnOnce(Callback>) -> HandleInput, - ) -> Result { - let (sender, receiver) = channel::bounded::>(1); - - let callback = Callback::new(move |result| { - sender.send(result).unwrap(); - }); - - let event = make_event(callback); - self.sender.send(event).unwrap(); - - receiver.recv().unwrap() - } - - /// Async version of `verify_to_highest`. - /// - /// The given `callback` will be called asynchronously with the - /// verification result. - pub fn verify_to_highest_async( + fn verify_to_highest_async( &mut self, callback: impl FnOnce(Result) -> () + Send + 'static, ) { @@ -377,11 +404,7 @@ impl Handle { self.sender.send(event).unwrap(); } - /// Async version of `verify_to_target`. - /// - /// The given `callback` will be called asynchronously with the - /// verification result. - pub fn verify_to_target_async( + fn verify_to_target_async( &mut self, height: Height, callback: impl FnOnce(Result) -> () + Send + 'static, @@ -390,8 +413,7 @@ impl Handle { self.sender.send(event).unwrap(); } - /// Terminate the underlying supervisor. - pub fn terminate(&mut self) { + fn terminate(&mut self) { let (sender, receiver) = channel::bounded::<()>(1); let callback = Callback::new(move |_| {