actix/fut/future/
mod.rs

1use std::{
2    future::Future,
3    marker::PhantomData,
4    ops::{Deref, DerefMut},
5    pin::Pin,
6    task::{Context, Poll},
7    time::Duration,
8};
9
10pub use map::Map;
11use pin_project_lite::pin_project;
12pub use then::Then;
13pub use timeout::Timeout;
14
15use crate::actor::Actor;
16
17mod either;
18mod map;
19pub mod result;
20mod then;
21mod timeout;
22
23/// Trait for types which are a placeholder of a value that may become
24/// available at some later point in time.
25///
26/// [`ActorFuture`] is very similar to a regular [`Future`], only with subsequent combinator
27/// closures accepting the actor and its context, in addition to the result.
28///
29/// [`ActorFuture`] allows for use cases where future processing requires access to the actor or
30/// its context.
31///
32/// Here is an example of a handler on a single actor, deferring work to another actor, and then
33/// updating the initiating actor's state:
34///
35/// ```no_run
36/// use actix::prelude::*;
37///
38/// // The response type returned by the actor future
39/// type OriginalActorResponse = ();
40/// // The error type returned by the actor future
41/// type MessageError = ();
42/// // This is the needed result for the DeferredWork message
43/// // It's a result that combine both Response and Error from the future response.
44/// type DeferredWorkResult = Result<OriginalActorResponse, MessageError>;
45/// #
46/// # struct ActorState {}
47/// #
48/// # impl ActorState {
49/// #    fn update_from(&mut self, _result: ()) {}
50/// # }
51/// #
52/// # struct OtherActor {}
53/// #
54/// # impl Actor for OtherActor {
55/// #    type Context = Context<Self>;
56/// # }
57/// #
58/// # impl Handler<OtherMessage> for OtherActor {
59/// #    type Result = ();
60/// #
61/// #    fn handle(&mut self, _msg: OtherMessage, _ctx: &mut Context<Self>) -> Self::Result {}
62/// # }
63/// #
64/// # struct OriginalActor{
65/// #     other_actor: Addr<OtherActor>,
66/// #     inner_state: ActorState
67/// # }
68/// #
69/// # impl Actor for OriginalActor{
70/// #     type Context = Context<Self>;
71/// # }
72/// #
73/// # #[derive(Message)]
74/// # #[rtype(result = "Result<(), MessageError>")]
75/// # struct DeferredWork {}
76/// #
77/// # #[derive(Message)]
78/// # #[rtype(result = "()")]
79/// # struct OtherMessage {}
80///
81/// impl Handler<DeferredWork> for OriginalActor {
82///     // Notice the `Response` is an `ActorFuture`-ized version of `Self::Message::Result`.
83///     type Result = ResponseActFuture<Self, DeferredWorkResult>;
84///
85///     fn handle(&mut self, _msg: DeferredWork, _ctx: &mut Context<Self>) -> Self::Result {
86///         // this creates a `Future` representing the `.send` and subsequent
87///         // `Result` from `other_actor`
88///         let update_self = self.other_actor
89///             .send(OtherMessage {})
90///             // Wrap that future so chained handlers can access the actor
91///             // (`self` in the synchronous code) as well as the context.
92///             .into_actor(self)
93///             // once the wrapped future resolves, update this actor's state
94///             .map(|result, actor, _ctx| {
95///                 match result {
96///                     Ok(v) => {
97///                         // update actor (self) state
98///                         actor.inner_state.update_from(v);
99///                         Ok(())
100///                     },
101///                     // Failed to send message to other_actor
102///                     Err(_e) => Err(()),
103///                 }
104///             });
105///
106///         // box and return the wrapped future
107///         Box::pin(update_self)
108///     }
109/// }
110/// ```
111///
112/// See also [`WrapFuture::into_actor()`] which provides future conversion.
113pub trait ActorFuture<A: Actor> {
114    /// The type of value produced on completion.
115    type Output;
116
117    fn poll(
118        self: Pin<&mut Self>,
119        srv: &mut A,
120        ctx: &mut A::Context,
121        task: &mut Context<'_>,
122    ) -> Poll<Self::Output>;
123}
124
125pub trait ActorFutureExt<A: Actor>: ActorFuture<A> {
126    /// Map this future's result to a different type, returning a new future of
127    /// the resulting type.
128    fn map<F, U>(self, f: F) -> Map<Self, F>
129    where
130        F: FnOnce(Self::Output, &mut A, &mut A::Context) -> U,
131        Self: Sized,
132    {
133        Map::new(self, f)
134    }
135
136    /// Chain on a computation for when a future finished, passing the result of
137    /// the future to the provided closure `f`.
138    fn then<F, Fut>(self, f: F) -> Then<Self, Fut, F>
139    where
140        F: FnOnce(Self::Output, &mut A, &mut A::Context) -> Fut,
141        Fut: ActorFuture<A>,
142        Self: Sized,
143    {
144        then::new(self, f)
145    }
146
147    /// Add timeout to futures chain.
148    ///
149    /// `Err(())` returned as a timeout error.
150    fn timeout(self, timeout: Duration) -> Timeout<Self>
151    where
152        Self: Sized,
153    {
154        Timeout::new(self, timeout)
155    }
156
157    /// Wrap the future in a Box, pinning it.
158    ///
159    /// A shortcut for wrapping in [`Box::pin`].
160    fn boxed_local(self) -> LocalBoxActorFuture<A, Self::Output>
161    where
162        Self: Sized + 'static,
163    {
164        Box::pin(self)
165    }
166}
167
168impl<F, A> ActorFutureExt<A> for F
169where
170    F: ActorFuture<A>,
171    A: Actor,
172{
173}
174
175/// Type alias for a pinned box [`ActorFuture`] trait object.
176pub type LocalBoxActorFuture<A, I> = Pin<Box<dyn ActorFuture<A, Output = I>>>;
177
178impl<F, A> ActorFuture<A> for Box<F>
179where
180    F: ActorFuture<A> + Unpin + ?Sized,
181    A: Actor,
182{
183    type Output = F::Output;
184
185    fn poll(
186        mut self: Pin<&mut Self>,
187        srv: &mut A,
188        ctx: &mut A::Context,
189        task: &mut Context<'_>,
190    ) -> Poll<Self::Output> {
191        Pin::new(&mut **self.as_mut()).poll(srv, ctx, task)
192    }
193}
194
195impl<P, A> ActorFuture<A> for Pin<P>
196where
197    P: Unpin + DerefMut,
198    <P as Deref>::Target: ActorFuture<A>,
199    A: Actor,
200{
201    type Output = <<P as Deref>::Target as ActorFuture<A>>::Output;
202
203    fn poll(
204        self: Pin<&mut Self>,
205        srv: &mut A,
206        ctx: &mut A::Context,
207        task: &mut Context<'_>,
208    ) -> Poll<Self::Output> {
209        Pin::get_mut(self).as_mut().poll(srv, ctx, task)
210    }
211}
212
213/// Helper trait that allows conversion of normal future into [`ActorFuture`]
214pub trait WrapFuture<A>
215where
216    A: Actor,
217{
218    /// The future that this type can be converted into.
219    type Future: ActorFuture<A>;
220
221    #[deprecated(since = "0.11.0", note = "Please use WrapFuture::into_actor")]
222    #[doc(hidden)]
223    fn actfuture(self) -> Self::Future;
224
225    /// Convert normal future to a [`ActorFuture`]
226    fn into_actor(self, a: &A) -> Self::Future;
227}
228
229impl<F: Future, A: Actor> WrapFuture<A> for F {
230    type Future = FutureWrap<F, A>;
231
232    #[doc(hidden)]
233    fn actfuture(self) -> Self::Future {
234        wrap_future(self)
235    }
236
237    fn into_actor(self, _: &A) -> Self::Future {
238        wrap_future(self)
239    }
240}
241
242pin_project! {
243    pub struct FutureWrap<F, A>
244    where
245        F: Future,
246        A: Actor,
247    {
248        #[pin]
249        fut: F,
250        _act: PhantomData<A>
251    }
252}
253
254/// Converts normal future into [`ActorFuture`], allowing its processing to
255/// use the actor's state.
256///
257/// See the documentation for [`ActorFuture`] for a practical example involving both
258/// [`wrap_future`] and [`ActorFuture`]
259pub fn wrap_future<F, A>(f: F) -> FutureWrap<F, A>
260where
261    F: Future,
262    A: Actor,
263{
264    FutureWrap {
265        fut: f,
266        _act: PhantomData,
267    }
268}
269
270impl<F, A> ActorFuture<A> for FutureWrap<F, A>
271where
272    F: Future,
273    A: Actor,
274{
275    type Output = F::Output;
276
277    fn poll(
278        self: Pin<&mut Self>,
279        _: &mut A,
280        _: &mut A::Context,
281        task: &mut Context<'_>,
282    ) -> Poll<Self::Output> {
283        self.project().fut.poll(task)
284    }
285}