1use futures::{future::BoxFuture, FutureExt};
4use std::{
5 fmt,
6 future::Future,
7 pin::Pin,
8 task::{ready, Context, Poll},
9};
10
11pub struct NodeExitFuture {
13 consensus_engine_fut: Option<BoxFuture<'static, eyre::Result<()>>>,
16}
17
18impl fmt::Debug for NodeExitFuture {
19 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20 f.debug_struct("NodeExitFuture").field("consensus_engine_fut", &"...").finish()
21 }
22}
23
24impl NodeExitFuture {
25 pub fn new<F>(consensus_engine_fut: F) -> Self
27 where
28 F: Future<Output = eyre::Result<()>> + 'static + Send,
29 {
30 Self { consensus_engine_fut: Some(Box::pin(consensus_engine_fut)) }
31 }
32}
33
34impl Future for NodeExitFuture {
35 type Output = eyre::Result<()>;
36
37 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
38 let this = self.get_mut();
39 if let Some(rx) = this.consensus_engine_fut.as_mut() {
40 match ready!(rx.poll_unpin(cx)) {
41 Ok(_) => {
42 this.consensus_engine_fut.take();
43 Poll::Ready(Ok(()))
44 }
45 Err(err) => Poll::Ready(Err(err)),
46 }
47 } else {
48 Poll::Pending
49 }
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 #[tokio::test]
58 async fn test_node_exit_future() {
59 let fut = async { Ok(()) };
60
61 let node_exit_future = NodeExitFuture::new(fut);
62
63 let res = node_exit_future.await;
64
65 assert!(res.is_ok());
66 }
67}