use crate::{module::WorkspaceUser, services::server::Server}; use lib_infra::retry::Action; use pin_project::pin_project; use std::{ future::Future, marker::PhantomData, pin::Pin, sync::Arc, task::{Context, Poll}, }; pub(crate) type Builder = Box Fut + Send + Sync>; #[allow(dead_code)] pub(crate) struct RetryAction { token: String, server: Server, user: Arc, builder: Builder, phantom: PhantomData<(T, E)>, } impl RetryAction { #[allow(dead_code)] pub(crate) fn new(server: Server, user: Arc, builder: F) -> Self where Fut: Future> + Send + Sync + 'static, F: Fn(String, Server) -> Fut + Send + Sync + 'static, { let token = user.token().unwrap_or("".to_owned()); Self { token, server, user, builder: Box::new(builder), phantom: PhantomData, } } } impl Action for RetryAction where Fut: Future> + Send + Sync + 'static, T: Send + Sync + 'static, E: Send + Sync + 'static, { type Future = Pin> + Send + Sync>>; type Item = T; type Error = E; fn run(&mut self) -> Self::Future { let fut = (self.builder)(self.token.clone(), self.server.clone()); Box::pin(RetryActionFut { fut: Box::pin(fut) }) } } #[pin_project] struct RetryActionFut { #[pin] fut: Pin> + Send + Sync>>, } impl Future for RetryActionFut where T: Send + Sync + 'static, E: Send + Sync + 'static, { type Output = Result; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let mut this = self.project(); this.fut.as_mut().poll(cx) } }